
Hello, envzero fans! As some of you know, we have almost unlimited extensibility with 3rd party tools, using our custom workflows. You can hook in pretty much any tool, in any phase of the deployment. Today, we’re going to talk about how to prevent cloud misconfigurations before they start. We’re going to do this by chaining a tool in the deployment after the terraform plan phase. This is where our friends at Bridgecrew come in. Just like we at envzero have open-sourced the Terratag module of our platform, Bridgecrew has open-sourced Checkov!
Checkov
Checkov is a static code analysis tool for infrastructure-as-code. It scans cloud infrastructure managed in Terraform, Cloudformation, Kubernetes, Arm templates, or Serverless Framework and detects misconfigurations.

Setup
For illustration purposes, we’re going to use Bridgecrew’s demo application called TerraGoat. TerraGoat is Bridgecrew’s “Vulnerable by Design” Terraform repository. TerraGoat is a learning and training project that demonstrates how common configuration errors can find their way into production cloud environments.
DISCLAIMER: DO NOT ACTUALLY DEPLOY THIS APPLICATION INTO YOUR CLOUD INFRASTRUCTURE. IT IS PURPOSELY COMPROMISED.
I have created a template of TerraGoat inside of envzero and linked it to our Bridgecrew Demo project.

The only other thing we have to do is to actually call Checkov to do the check during the deployment. We need to do this after the Terraform plan phase, so that we have a plan to check. Here is what the env0.yml file will look like:
This adds 3 commands that run after the Terraform Plan, and before Terraform Apply. We put it here so that the Apply doesn’t run in case of failures. We don’t want to see the errors after the resources are applied. We want the deployment to fail if there are errors.
This command installs Checkov into our runtime environment using the pip3 package installer so we can run it against our Terraform plan.
This command essentially formats our .tf-plan file into tf.json so that it can be parsed and run against Checkov.
This command has a lot going on and is in 2 parts. First, it quietly executes Checkov against our tf.json (the reformatted tf.plan file) and looks for a 0 exit code. The double pipe || tells bash to only execute the 2nd command if the exit code of the first command is not 0. So if your Checkov results are clear, your deployment gets the 0 exit code and continues on with the deployment.
If not, then the second part of the command runs. Knowing if this part runs, it is because of a failure, we’re just going to format our error message here. We run Checkov again so we can pipe the error with the echoed error notification text to the console. The 1>&2 routs stdout to stderror, and the exit 1 code tells envzero that the stage failed, and to end the deployment run.

The envzero platform will parse the error, and give you the clear error printed on the Environment deployment page. But, if you want the full logs from Checkov, you can find those in the After: Terraform Plan deployment logs.

And that’s it! A little bit of YAML, and you’ve implemented Checkov to protect yourself against the deployment of misconfigured cloud resources. That is instantly added value to your organization by shifting the security left in your deployment process with env0.
You can find more information on Checkov here. You can find the open-source repository on GitHub. And be sure to see how you can automate your infrastructure security from commit to cloud at Bridgecrew.io.
‍
Related Content

Today we're launching the env zero Free Tier, a free-forever plan that gives platform teams the full env zero orchestration experience rather than a locked-down demo of it. If you've been waiting for a way to try real IaC orchestration on your own terms, this is your front door.
Why we built the env zero Free Tier
Platform engineering is a bottom-up discipline. You don't adopt a new IaC platform because someone signed a contract. You adopt it because you spun it up on a Friday, pointed it at a repo, and saw it solve the orchestration and self-service problems you live with every day.
For too long, trying env zero meant talking to us first, and that's the wrong answer to "I just want to see if this works for my team." So we changed it. The Free Tier is self-serve from the first click. Create an org, connect your VCS, and run.
With the IaC landscape shifting and long-standing free options disappearing, a lot of teams are re-evaluating how they orchestrate Terraform and OpenTofu right now. We wanted env zero to be the obvious place to land. We looked hard at the competitive landscape and sought to include a feature and entitlements set that would make env zero the superior option.
Who it's for
The Free Tier is built for the platform engineer standing up self-service infrastructure for their org, whether that's a solo practitioner proving out a workflow or a small platform team giving developers a paved road to deploy on.
It's a fit if you want to:
- Give your developers self-service environments without handing them the keys to production
- Run drift detection against your live infrastructure so state surprises stop being surprises
- Wire in SSO and bring your whole team in from day one, not just yourself and one teammate
- Orchestrate Terraform and OpenTofu with real guardrails, before you've had a single procurement conversation
What you get
The Free Tier ships with the complete env zero Navigator feature set. We took the position early that a paying customer should never receive less than a free user does, so instead of carving out a feature-limited "lite" plan, we gave the free tier the full product and set generous usage limits around it.
| Price | $0, in perpetuity |
|---|---|
| Runs | 250 / month |
| Environments | Up to 30 |
| Deploying users | Unlimited, humans and agents |
| Features | Full Navigator feature set, including drift detection and OIDC SSO |
| Support | Community support |
A few things worth spelling out for the way platform teams actually work:
A "run" is an outcome. One run equals one successful apply or one drift detection. Plans and failed runs don't burn your monthly allowance, so you're only metered on work that actually happened.
Unlimited users, including agents. There's no per-seat gate and no "invite two people, then pay." Bring your whole platform team and your automation. As IaC pipelines increasingly include non-human actors, we didn't want a seat cap to be the thing that boxed you in.
Drift detection and SSO are included. These are the capabilities teams usually have to upgrade to reach elsewhere. On env zero they're part of the free experience, because they're part of running infrastructure responsibly.
Where the limits are, and what's next
The Free Tier is designed to run real workloads, not just a hello-world. The two dials that define it are 250 runs per month and 30 environments. When your team consistently pushes past those, that's the natural signal you've outgrown free. Our paid tiers, Cloud Navigator and Cloud Pilot, lift those ceilings and add direct support and more advanced capabilities as you scale.
There's no downgrade trap and no bait-and-switch. Free stays free, and the path up is there when you need it and not before.
Get started
You can be deploying in minutes:
- Sign up for env zero. Every new self-serve account lands on the Free Tier automatically.
- Connect your VCS and point env zero at an IaC repo.
- Run your first deployment, turn on drift detection, and invite your team.
No trial countdown. No credit card. No gatekeeper.
FAQ
Is it really free forever? Yes. The Free Tier is $0 in perpetuity. It isn't a promotional rate or a countdown to a paid plan.
Is there a trial? Do I need a credit card? No trial and no credit card. Every new self-serve account lands directly on the Free Tier, so you start on Free from your very first login and stay there. There's no trial period to expire and nothing that quietly downgrades on you later.
What counts as a run? A run is one successful apply or one drift detection. Plans and failed runs don't count against your monthly total, so you're only ever metered on work that completed.
What happens when I hit 250 runs or 30 environments? Those are the two limits that define the Free Tier. When you reach a cap, env zero lets you know and shows you the path to more capacity through Cloud Navigator or Cloud Pilot. Your existing environments and configuration stay intact.
Do I get fewer features on Free than on a paid plan? No. The Free Tier includes the complete Navigator feature set, drift detection and OIDC SSO included. The paid tiers raise your usage limits and add direct support and more advanced capabilities as you scale, rather than unlocking basic functionality.
Can I add my whole team? Yes. Deploying users are unlimited on Free, both human teammates and automation or agents. There's no per-seat charge.
What support is included? Free Tier comes with community support. Direct support is part of the Cloud Navigator and Cloud Pilot tiers. Paid support plans are available for Free Tier users, simply Contact Us.
How do I upgrade when I outgrow Free? When your team consistently pushes past the run or environment limits, you can move up to Cloud Navigator or Cloud Pilot for higher ceilings, direct support, and additional capabilities. Your work carries over.
Introducing the env zero Free Tier: full-featured IaC orchestration, free forever


You run [.code]terraform apply[.code], it fails partway through, and the next command you run refuses to move: [.code]Error acquiring the state lock[.code]. Nothing is broken yet, but nothing will proceed either until the lock is cleared.
This guide covers what [.code]force-unlock[.code] actually does, when it is safe to use, how to find the lock ID on every major backend, and what to do if the command itself does not fix things.
What does terraform force-unlock do?
Terraform locks state before any operation that could write to it. The lock stops two processes from writing to the same state file at once, which is the most common way a state file gets corrupted. Locking happens automatically and silently on every plan and apply where the backend supports it. You will not see a message unless acquiring the lock takes longer than expected.
[.code]force-unlock[.code] is the manual override for when that automatic process gets stuck. It removes the lock record so a new operation can proceed. According to HashiCorp, the command does not modify your infrastructure, and on most backends it does not touch your state data either. It just clears the record that says the state is currently held.
Usage:
terraform force-unlock [options] LOCK_ID
The only option is [.code]-force[.code], which skips the yes or no confirmation prompt. That is useful inside a script or CI job where nothing is available to type “yes” into. Otherwise leave it off, since the confirmation step is the last chance to catch a mistake before you unlock something someone else is actively using.
The lock ID is not optional and is not guessable. Terraform prints it in the error message when a lock is already held, and [.code]force-unlock[.code] requires an exact match. Per HashiCorp's own documentation, the ID works as a nonce, a one-time verification token that ensures a lock and an unlock target the same lock. That is deliberate: you can only release a lock you can identify, not just any lock on the state file.
One thing worth flagging up front: on the local backend, a stuck lock can only be cleared by the same machine and user that created it. There is no separate process to force it from elsewhere, which is one more reason most teams move to a remote backend, such as the ones covered in this backend configuration guide, before this becomes a live problem.
When should you use the force-unlock command?
Treat [.code]force-unlock[.code] as a last resort, not a first response. If two operations are genuinely running against the same state at the same time, forcing a lock open defeats the entire purpose of state locking and can leave you with a corrupted state file. Only run it when you are certain the process that created the lock is no longer active.
A stuck lock usually traces back to one of a few causes:
- A [.code]terraform apply[.code] or [.code]plan[.code] was cancelled or errored mid-run, for example because a CI job timed out or someone hit Ctrl+C, so Terraform never reached the step where it releases the lock.
- The machine or build agent running Terraform lost its network connection to the backend before the lock could be released.
- The backend storage itself changed mid-operation, for example a Terraform run modifying firewall rules, private endpoints, or access policies on the very storage account that holds the state file.
If none of those match your situation and you are not sure why the lock exists, treat that as a reason to investigate before clearing it, not a reason to assume it is safe to force.
Where to find the lock ID for every backend
In most cases you will not need to go looking. The lock ID appears directly in the [.code]Error acquiring the state lock[.code] message, under the [.code]ID:[.code] field, alongside who holds it and when it was created. The backend-specific detail below matters mainly when you are troubleshooting secondhand, for example clearing a lock a teammate reported without a fresh error message in front of you.
Local backend
Terraform writes a [.code].terraform.tfstate.lock.info[.code] file next to the state file while an operation is in progress. It is a small JSON object containing the lock [.code]ID[.code], the operation type, and who created it. On clean exit, Terraform deletes this file automatically. As noted above, a lock created by one machine cannot be released by [.code]force-unlock[.code] from a different one.
Amazon S3
As of Terraform 1.11, the S3 backend supports native state locking through the [.code]use_lockfile[.code] argument, and no longer requires a separate DynamoDB table. Setting it to [.code]true[.code] tells Terraform to create a lock object in the same S3 bucket as your state, using conditional writes so only one process can create it at a time.
terraform {
backend "s3" {
bucket = "mybucket"
key = "path/to/my/key"
region = "us-east-1"
use_lockfile = true
}
}
With native locking, the lock ID is whatever the error message reports; there is no separate table to query. If your configuration still uses the older [.code]dynamodb_table[.code] argument, note that HashiCorp has deprecated it in favor of [.code]use_lockfile[.code]. On that legacy path, the lock lives as an item in the DynamoDB table, keyed by a partition key named [.code]LockID[.code], and you can inspect it directly:
aws dynamodb get-item \
--table-name your-lock-table \
--key '{"LockID": {"S": "your-bucket/path/to/terraform.tfstate"}}'
Azure Blob Storage
Azure Blob Storage implements locking through native blob leases, with no extra backend configuration required. If a run is interrupted mid-apply, the lease can be left in place. The lock ID appears in the error message, but you can also inspect the lease state directly:
az storage blob show \
--account-name YOUR_STORAGE_ACCOUNT \
--container-name YOUR_CONTAINER \
--name path/to/terraform.tfstate \
--query 'properties.lease'
If [.code]force-unlock[.code] is not an option, for example the lock ID is unavailable, you can break the lease directly through the Azure CLI, which achieves the same result at the storage layer:
az storage blob lease break \
--account-name YOUR_STORAGE_ACCOUNT \
--container-name YOUR_CONTAINER \
--blob-name path/to/terraform.tfstate
Google Cloud Storage
The GCS backend also locks natively with zero extra configuration. Terraform writes a lock object at [.code]/.tflock[.code] in the same bucket as your state, and the lock ID is the object's generation number, which is included in the error message. Deleting that object directly is the manual equivalent of [.code]force-unlock[.code] if the CLI command fails for some reason.
HCP Terraform and Terraform Enterprise
This is a common point of confusion: [.code]terraform force-unlock[.code] is a CLI command that works against backends where Terraform itself manages the lock file. HCP Terraform and Terraform Enterprise instead lock and unlock workspaces through their own UI and API, not the CLI command. In the workspace's Actions menu, you can select Lock workspace or Unlock workspace directly, or call the workspaces API endpoint to do the same thing from automation.
Consul
With the Consul backend, lock information lives in the Consul key-value store rather than in a file. You can list it with the [.code]consul kv get [.code] command, or query the same data through Consul's HTTP API.
Using terraform force-unlock: a worked example
- Identify the lock ID from the error message. For example: [.code]Lock Info: ID: b8814894-4a5f-217b-e97b-c4f5c02a1f88[.code].
- Confirm nobody else is running an operation against this state. Check your CI/CD dashboard, ask your team, or check the environment's deployment history if you are running on a platform that centralizes this, before assuming the lock is actually stale.
- Run the command with the ID from step one: [.code]terraform force-unlock b8814894-4a5f-217b-e97b-c4f5c02a1f88[.code]. Confirm the prompt with [.code]yes[.code], or add [.code]-force[.code] if you are running this non-interactively.
- Verify the fix by re-running the command that originally failed, such as [.code]terraform plan[.code]. If it proceeds past the locking step without error, the lock is cleared.
Unlocking remote state: alternatives to force-unlock
Wait instead of forcing: -lock-timeout
If two operations occasionally overlap for a few seconds, for example two CI jobs kicking off close together, [.code]force-unlock[.code] is the wrong tool. The [.code]-lock-timeout[.code] flag tells Terraform to wait for the lock to clear on its own instead of failing immediately:
terraform plan -lock-timeout=5m
This is worth setting as a default in CI pipelines that run plan, apply, or destroy operations back to back, so a brief overlap resolves itself instead of surfacing as a lock error at all.
Manual removal as a last resort
Occasionally [.code]force-unlock[.code] itself fails, usually because the backend is unreachable or credentials cannot reach the lock record. HashiCorp's guide to recovering state from backup covers this scenario directly. In that situation, the remaining options are backend-specific: delete the lock object from S3 or GCS, edit or remove the DynamoDB item, or break the Azure blob lease as shown above. All of these bypass Terraform entirely, so treat them with the same caution as [.code]force-unlock[.code] itself.
Coordinate before you unlock
Whichever method you use, confirm no other process is mid-write before you touch the lock, and consider pulling a backup first with [.code]terraform state pull[.code]. Never use [.code]-lock=false[.code] as a standing workaround for frequent lock errors. It disables the protection entirely rather than resolving whatever is causing the contention.
Troubleshooting force-unlock errors
The lock ID does not match
[.code]force-unlock[.code] will refuse an ID that does not match the current lock. This almost always means you are using a stale ID from an old error message. Re-run the failing command to get the current lock's ID and try again.
Permission errors during force-unlock
Clearing a lock requires write or delete access to wherever the lock record lives, for example [.code]s3:DeleteObject[.code] on the lock object, or the equivalent DynamoDB, GCS, or Azure permission. A permissions error here usually points to the credentials Terraform is running with, not the lock itself.
The same lock error comes back immediately
If you clear a lock and it reappears right away, something is still actively writing to that state. Stop and investigate before unlocking again. This pattern usually means step two of the worked example above was skipped.
Managing state locking at scale with env zero
Clearing a stuck lock by hand does not scale once a platform team is managing hundreds of environments across multiple backends. Ad Hoc Tasks in env zero let you run a command, including [.code]terraform force-unlock -force LOCK_ID[.code], directly on the environment's deployment container from the UI. That means resolving a stuck lock does not require local CLI access, a checked-out copy of the Terraform configuration, or direct credentials to the backend that holds the state.
By default, ad hoc tasks are restricted to organization administrators, since they allow arbitrary commands against a live deployment container. Teams that want to delegate lock-clearing to platform engineers without granting full admin access can do that with a custom role scoped to just that permission.
It is worth distinguishing this from Environment Locking in env zero, which is a separate, deliberate governance control rather than Terraform's automatic state lock. Locking an environment in env zero blocks deploys, destroys, plans, and drift detection outright, with a reason attached for anyone else who looks at it, and it stays in effect until someone with permission unlocks it. A Terraform state lock, by contrast, is transient by design and normally clears itself within seconds. If you are troubleshooting a “locked” environment in env zero and [.code]force-unlock[.code] does not seem relevant, this distinction is usually why.
Key takeaways
- [.code]terraform force-unlock LOCK_ID[.code] manually clears a stuck state lock. It does not touch your infrastructure, and on most backends it does not touch your state data either.
- Only use it when you are certain the process that created the lock is no longer running. Unlocking an active operation risks a corrupted state file.
- The lock ID is usually sitting right in the error message. You only need to hunt through backend-specific tooling when troubleshooting without that message in hand.
- S3 no longer needs DynamoDB for locking. [.code]use_lockfile = true[.code] has been the supported path since Terraform 1.11.
- [.code]-lock-timeout[.code] prevents most stuck-lock situations in CI before they happen, by waiting instead of failing immediately.
Frequently asked questions
Q. How do I fix a Terraform state lock?
Run [.code]terraform force-unlock LOCK_ID[.code], using the ID from the [.code]Error acquiring the state lock[.code] message. Only do this once you are certain no other operation is currently running against the same state.
Q. What is Terraform state locking for?
State locking prevents two operations from writing to the same state file at the same time, which is one of the most common causes of state corruption. Terraform acquires the lock automatically before any operation that could write state and releases it when the operation finishes.
Q. Can force-unlock corrupt my Terraform state?
[.code]force-unlock[.code] itself does not modify your infrastructure or your state data; it only removes the lock record. The risk is indirect: if you unlock a state that another process is actively writing to, that process and yours can both write at once, which can corrupt the state file.
Q. Does the S3 backend still need DynamoDB for state locking?
No. Since Terraform 1.11, the S3 backend supports native locking through [.code]use_lockfile = true[.code], using S3 conditional writes instead of a separate DynamoDB table. The older [.code]dynamodb_table[.code] argument still works but is deprecated.
Q. How do I avoid stuck state locks in the first place?
Avoid cancelling Terraform runs mid-operation, set [.code]-lock-timeout[.code] in CI so brief overlaps wait instead of failing, and use a platform that centralizes deployment history so you can quickly confirm whether a lock is stale before clearing it.
Terraform Force-Unlock: How to Safely Unlock a Locked State File
Cost visibility without governance is just expensive awareness. Governance without real-time data is just expensive guessing.
The Infracost team published something worth reading: a breakdown of the ten cloud cost anti-patterns that quietly drain infrastructure budgets. These include old EC2 instance families, orphaned test environments, log groups retaining data forever, and multi-AZ replication running in dev because someone copy-pasted a prod config.
Their diagnosis is correct. These aren't careless mistakes. They're reasonable decisions made without cost context at the moment those decisions happen.
But the billing console only tells you what already happened. And a PR-level cost estimate only tells you what's about to happen. Neither one tells you what your infrastructure is costing you right now, across every environment, every team, every account.
That's three separate problems. They need three separate capabilities… working together.
The Three Moments That Matter
Cloud cost control has a timeline, but most teams only address one part of it.
Before deployment: An engineer writes a Terraform module. They pick an instance type, configure a database, set retention policies. Every decision they make has a cost implication. Without visibility at this stage, those implications are invisible until the bill arrives.
At deployment: Code merges. Infrastructure provisions. Policies either enforce standards or they don't. This is the last moment a cost problem is cheap to fix.
After deployment: The environment is live and then configurations drift. New services get adopted without a clear cost model, while test environments survive longer than they should. Costs accumulate quietly, outside any PR, outside any policy review.
Most teams have partial coverage at best. Infracost handles the first moment. env zero handles the second. CloudQuery—now part of env zero—handles the third.
Before You Ship: Infracost + env zero
Infracost surfaces cost estimates in pull requests (and they support more than 10 million SKUs across clouds). An engineer sees that the RDS instance is over-provisioned for a dev workload. They see the monthly delta. The context is there, at the exact moment the fix is a two-minute edit rather than a production change requiring a maintenance window.
env zero extends that context into enforcement. A cost threshold policy blocks the deployment if the estimated spend exceeds a defined limit. A tagging policy requires every environment to carry an owner tag and an expiry date before it merges. A governance workflow routes high-cost changes to a reviewer with authority to approve or reject.
The engineer isn't the last line of defense anymore; the platform is.
Customers using env zero's pre-deployment cost enforcement have cut IaC-related infrastructure spend by 45%. That's not optimization after the fact; that's the problem not happening.
After You Ship: env zero + CloudQuery
Pre-deployment governance catches what you can see before the merge. It doesn't catch what changes after it.
Infrastructure drifts. Engineers provision resources outside the standard pipeline. A test environment spun up six months ago never got an expiry date. A new managed service got adopted without anyone mapping out what it costs at scale. These problems live in your running infrastructure, not in your pull requests.
CloudQuery is now part of env zero. It continuously queries your live cloud infrastructure—across AWS, Azure, and GCP—and surfaces what's actually running, what it's actually costing, and where it deviates from the standards your platform team has defined.
This is the real-time half of cloud cost governance. Not what an engineer estimated before the merge. What your infrastructure is actually spending right now.
The Test Environment Problem, Fully Solved
The Infracost piece calls out the test environment that never got torn down. Every platform engineer has several of these.
env zero handles this at the policy level before deployment: every environment carries a TTL, auto-expiry terminates it on schedule, no engineer has to remember anything.
CloudQuery handles the environments that already exist without those controls. It finds them. It surfaces their running cost. It gives your platform team the data to act on.
Virgin Media O2 went from spending half a day standing up a single POC environment to spinning one up in under 10 minutes with 5 variables. Auto-expiry controls costs automatically. CloudQuery makes sure nothing slips through the cracks of what's already running.
Governance Across the Full Infrastructure Lifecycle
The common thread in every cloud cost anti-pattern Infracost identified: engineers made reasonable decisions without the right context at the right moment.
The fix isn't better finance reviews after the fact, but rather, closing all three gaps before deployment, at deployment, and in production.
Infracost provides cost context in the PR. env zero enforces the policies that make that context binding. CloudQuery, now part of env zero, continuously monitors what's running and surfaces what the enforcement layer didn't catch.
That's not three tools. That's one governance lifecycle from the first line of Terraform to the last running resource.
See how env zero governs the full infrastructure lifecycle →
Learn more about the env zero Infracost integration →
Learn more about CloudQuery →
Related: env0’s AWS integration brings environment management, cost controls, and deployment guardrails to your AWS infrastructure workflows.
The Full Picture of Cloud Cost Control: How Infracost, env zero, and CloudQuery Close the Loop for Platform Teams


Hello, env zero fans! As some of you know, we have almost unlimited extensibility with 3rd party tools, using our custom workflows. You can hook in pretty much any tool, in any phase of the deployment. Today, we’re going to talk about how to prevent cloud misconfigurations before they start. We’re going to do this by chaining a tool in the deployment after the terraform plan phase. This is where our friends at Bridgecrew come in. Just like we at env zero have open-sourced the Terratag module of our platform, Bridgecrew has open-sourced Checkov!
Checkov
Checkov is a static code analysis tool for infrastructure-as-code. It scans cloud infrastructure managed in Terraform, Cloudformation, Kubernetes, Arm templates, or Serverless Framework and detects misconfigurations.

Setup
For illustration purposes, we’re going to use Bridgecrew’s demo application called TerraGoat. TerraGoat is Bridgecrew’s “Vulnerable by Design” Terraform repository. TerraGoat is a learning and training project that demonstrates how common configuration errors can find their way into production cloud environments.
DISCLAIMER: DO NOT ACTUALLY DEPLOY THIS APPLICATION INTO YOUR CLOUD INFRASTRUCTURE. IT IS PURPOSELY COMPROMISED.
I have created a template of TerraGoat inside of env zero and linked it to our Bridgecrew Demo project.

The only other thing we have to do is to actually call Checkov to do the check during the deployment. We need to do this after the Terraform plan phase, so that we have a plan to check. Here is what the env0.yml file will look like:
This adds 3 commands that run after the Terraform Plan, and before Terraform Apply. We put it here so that the Apply doesn’t run in case of failures. We don’t want to see the errors after the resources are applied. We want the deployment to fail if there are errors.
This command installs Checkov into our runtime environment using the pip3 package installer so we can run it against our Terraform plan.
This command essentially formats our .tf-plan file into tf.json so that it can be parsed and run against Checkov.
This command has a lot going on and is in 2 parts. First, it quietly executes Checkov against our tf.json (the reformatted tf.plan file) and looks for a 0 exit code. The double pipe || tells bash to only execute the 2nd command if the exit code of the first command is not 0. So if your Checkov results are clear, your deployment gets the 0 exit code and continues on with the deployment.
If not, then the second part of the command runs. Knowing if this part runs, it is because of a failure, we’re just going to format our error message here. We run Checkov again so we can pipe the error with the echoed error notification text to the console. The 1>&2 routs stdout to stderror, and the exit 1 code tells env zero that the stage failed, and to end the deployment run.

The env zero platform will parse the error, and give you the clear error printed on the Environment deployment page. But, if you want the full logs from Checkov, you can find those in the After: Terraform Plan deployment logs.

And that’s it! A little bit of YAML, and you’ve implemented Checkov to protect yourself against the deployment of misconfigured cloud resources. That is instantly added value to your organization by shifting the security left in your deployment process with env0.
You can find more information on Checkov here. You can find the open-source repository on GitHub. And be sure to see how you can automate your infrastructure security from commit to cloud at Bridgecrew.io.
‍
Better Together: Checkov and env0


This quick video talks about the static code analysis tool, Checkov by Bridgecrew. We'll use it to fix a problem with a Terraform deployment into Azure. Be sure to star their repository if you like the project.
Checkov, Analysis Tool by Bridgecrew and env0


