
Are you looking to start your journey into Infrastructure as Code? Or have you already jumped in head-first? Either way, this session is for you! We'll talk about many of the common pitfalls of IaC, and how you can avoid them. From infrastructure pitfalls, to coding pitfalls, we'll go over all kinds of things that you may not have thought of yet.
Related Content

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

In this guide, we will be exploring three IaC scanning tools, Checkov, tfsec, and Terrascan. We will go into detail of each tool, as well as compare the features of all three. You can explore the other parts of this guide below.
Jump to section:
Checkov vs tfsec vs Terrascan: Which IaC Scanning Tool is the Best?
Infrastructure as Code (IaC) is a popular approach to automate the provisioning and management of cloud computing resources using declarative configuration files. However, IaC also introduces new security challenges and risks that need to be addressed before deploying to production. In this blog post, we will compare three popular IaC scan tools: Checkov, tfsec, and Terrascan. These tools can help you identify and fix security issues in your IaC code before they become vulnerabilities in your cloud environment. We will compare them based on their features, performance, usability, and compatibility with different IaC frameworks and cloud providers.
Comparing IaC Scan Tools: Video walkthrough
Our setup
Let’s take a look at our setup.
Requirements
- A GitHub account (all the hands-on sections will utilize GitHub’s Codespaces so you won’t need to install anything on your machine)
Repository
TL;DR: You can find the repo here.
What is an IaC scan tool and what is it used for?
Alright, before we dig in, let’s get an understanding of a few concepts.
An IaC scan tool is a software application that analyzes your IaC files and detects security vulnerabilities, misconfigurations, compliance violations and other issues. IaC scan tools improve the quality and security of IaC files before they are deployed to cloud environments. These tools can help developers, DevSecOps and DevOps teams identify and fix potential problems in their code early in the development lifecycle, reducing the risk of potential data breaches, data leaks, downtime and other incidents.
What is Static Code Analysis?
Static code analysis is a method that examines the source code of a program without running it. Static code analysis tools can automate this process and detect possible errors, security vulnerabilities, and code quality issues. Static code analysis can help developers find and fix problems early in the development cycle, before they become more costly and difficult to resolve. Static code analysis can also help ensure that the code meets certain standards and guidelines, for such issues as coding style, performance, or compliance.
How does IaC scanning work?
IaC scanning works by applying a set of rules or policies to the IaC configuration files that check for common security best practices, such as encryption, authentication, authorization, logging, and monitoring. The rules or policies can be based on industry standards, such as CIS benchmarks, or customized to fit the specific needs of the organization. The IaC scanning tools can then generate a report that shows the results of the analysis, such as the number and severity of vulnerabilities found, the location of the vulnerable code, and the recommended remediation steps. The scan report itself can also be integrated with other tools, such as GitLab or GitHub, to provide feedback and guidance to developers in their workflows.
Why do you need IaC security scanning?
Imagine you are building a house and you have a blueprint that shows how everything should look and work. You wouldn't want to start construction without checking the blueprint for errors, right? You might end up with a leaky roof, a crooked wall, or faulty wiring. That's why you need IaC security scanning. It helps you find and fix any issues in your infrastructure as code before you deploy it to the cloud. It's like having a quality assurance team for your blueprint. IaC security scanning can save you time, money, and headaches in the long run.
Which IaC scanning tools exist?
Some of the most popular IaC scanning tools are checkov, tfsec, and terrascan. These tools can help you identify common vulnerabilities and best practices in your IaC code, such as Terraform, CloudFormation, Kubernetes, and more. However, they are not perfect and they may have some limitations or false positives. Here is a brief comparison of these three tools and later we will dig deeper into each one.
- Checkov: A comprehensive tool that supports Terraform, CloudFormation, Kubernetes, Helm, Serverless Framework, and more. It has a rich set of features and integrations, such as pre-commit hooks, GitHub actions, VS Code extension, etc. However, it may be slower and more complex than other tools.
- tfsec: A fast and lightweight tool that supports Terrafor. It has a simple installation process and a nice output format. However, it may not cover all the resources or scenarios that you need.
- Terrascan: A modular tool that supports Terraform, Kubernetes, Helm, Dockerfiles, and more. It has a flexible architecture that allows you to write your own policies using Open Policy Agent (OPA). However, it may have a steeper learning curve and less documentation than other tools.
As you can see, there is no one-size-fits-all solution for IaC scanning. You may need to try different tools and see which one works best for your use case. Or you may need to use a combination of tools to achieve the best results. The important thing is to scan your IaC code regularly and fix any issues that you find before they become a problem.
Which IaC Scanning Tool is the Best?: Comparing Checkov vs tfsec vs Terrascan


In this section of the IaC Scanning Tools Guide, we will be looking at tfsec and discussing the benefits, key features, and looking at some real world examples. You can explore the other parts of this guide below.
Jump to section:
- What is an IaC scan tool?
- What is Checkov?
- What is Terrascan?
- Comparing Checkov vs. tfsec vs. Terrascan
What is tfsec?
tfsec is a security scanner for your Terraform code. It performs static analysis of your code and detects potential misconfigurations that could lead to security risks. It supports multiple cloud providers, such as AWS, Azure, and GCP, and has hundreds of built-in rules. It also allows you to define your own custom rules using Rego policies or JSON/YAML custom policies. You can run tfsec locally or in your CI pipelines, and get developer-friendly output in various formats. tfsec is an open-source project backed by Aqua Security that aims to help you secure code in your IaC.
Benefits and Key Features of using tfsec
Some benefits and key features of using tfsec are:
| Feature | Details |
|---|---|
| Scanning IaC | Yes for security and compliance before deployment |
| IaC Frameworks Supported | Only Terraform |
| Reporting | Detailed reports and recommendations for fixing the detected issues in different formats such as text, JSON, CSV, Checkstyle, JUnit, and SARIF. |
| Integrations | Many tools including GitHub Actions, GitLab CI, and VS Code |
| Policy Customizations | Yes using JSON or YAML |
| Open-source | Yes |
| Example of Issues that can be detected | Insecure use of plain text secrets or hard-coded credentials Misconfigured network access rules or firewall settings Unencrypted data storage or communication Missing or outdated security features or patches Non-compliance with industry standards or regulations |
How to get started with tfsec
How to install tfsec?
There are several ways to install tfsec on your system. You can use a package manager such as brew (for macOS or Linux), choco (for Windows), or scoop (for Windows). You can also download the binary for your system from the releases page on GitHub. Alternatively, you can install tfsec with Go using the command:
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest
If you don't want to install tfsec on your system, you can also run it in a Docker container using the command:
docker run --rm -it -v "$(pwd):/src" aquasec/tfsec /src
If you follow along with our GitHub repo using Codespaces, it will be installed for you.
How to use tfsec?
To use tfsec, you simply need to run it on a directory that contains your Terraform code. For example:
tfsec ./Terraform
By default, tfsec will use a lovely output format that shows the severity, description, location, and resolution of each problem. You can change the output format using the --format flag.
For example:
tfsec ./Terraform --format json
This will output the results in JSON format. You can also use other formats such as csv, checkstyle, junit, sarif, text, markdown, html, and gif.
You can also customize the behavior of tfsec using various flags or a configuration file. For example, you can exclude certain checks using the --exclude flag. You can also enable or disable colors, force exit codes, ignore warnings or errors, set custom paths for modules or policies, and more. For a full list of flags you can run tfsec -h
Example use cases of tfsec
Use case 1: Scan your Terraform code for security issues before applying it
One of the most common use cases of tfsec is to scan your Terraform code for security issues before applying it to your cloud environment. This way, you can catch and fix any problems before they cause any damage or expose any vulnerabilities.
Let’s scan the same folder we scanned with checkov. Run the following commands:
tfsec ./Terraform
This will scan all the Terraform files in the current directory and print out a report of any issues found. For example:


As you can see, tfsec provides a clear and concise output that shows the location, severity, and description of each issue. It also provides a link to the documentation page where you can learn more about the issue and how to fix it.
Use case 2: Scan your Kubernetes manifests
Unfortunately, tfsec does not support scanning Kubernetes manifests. It was built specifically to scan Terraform files.
tfsec Custom Policies
Similar to checkov, you can create custom checks in tfsec either using YAML or JSON or using Rego. Let’s create a check similar to the one we did with checkov. We shouldn’t allow an S3 bucket’s ACL to be public-read when it is tagged with the key Scope and the value of PCI.
Custom checks are defined as JSON files or YAML files which sit in the .tfsec folder in the root check path. Any file with the suffix tfchecks.json or tfchecks.yaml will be parsed and the checks included during the run.
Check the pci_policy_tfchecks.yaml in the .tfsec folder in our repo. Below is the content:
---
checks:
- code: CUS999
description: Make sure S3 bucket ACL is NOT public-read if it has a Scope=PCI tag
impact: We would violate our PCI compliance
resolution: Make sure the ACL is not public-read
requiredTypes:
- resource
requiredLabels:
- aws_s3_bucket
severity: CRITICAL
matchSpec:
action : or
predicateMatchSpec :
- action : notContains
name : tags
value:
Scope: "PCI"
- action : notContains
name : acl
value: public
errorMessage: S3 bucket ACL is public-read with Scope=PCI tag
relatedLinks:
- http://internal.acmecorp.com/standards/aws/tagging.html
Use the normal command to run:
tfsec ./Terraform
And examine the output:

What is tfsec: Benefits, Key Features, and Examples


In this section of the IaC Scanning Tools Guide, we will be looking at Terrascan and discussing the benefits, key features, and looking at some real world examples. You can explore the other parts of this guide below.
Jump to section:
What is Terrascan?
Terrascan is a tool that helps you to scan your Infrastructure as Code for security and compliance policy violations. It supports various IaC languages such as Terraform, Kubernetes, Dockerfile, and more. It also integrates with different cloud platforms such as AWS, Azure, and GCP. Terrascan can detect over 500 policies for best practices and prevent risks before provisioning cloud infrastructure. You can run Terrascan locally or in your CI/CD pipeline to automate the scanning process.
Benefits and Key Features of using Terrascan
Some of the benefits and key features of using Terrascan are:
| Feature | Details |
|---|---|
| Scanning IaC | Yes for security and compliance before deployment |
| IaC Frameworks Supported | Multiple IaC frameworks such as Terraform, Kubernetes, Helm, Kustomize, and more |
| Reporting | Detailed reports and recommendations for fixing the detected issues in different formats such as JSON, YAML, XML, JUnit XML, and SARIF |
| Integrations | Many tools including GitHub, GitLab, Jenkins, Azure DevOps, and more |
| Policy Customizations | Yes using Rego, a declarative language for policy enforcement |
| Open-source | Yes |
| User Interface | CLI interface as well as a REST API and a web UI for easy usage and automation |
How to get started with Terrascan
Installing Terrascan
There are several ways to install Terrascan, depending on your preference and platform. You can download the binary from the GitHub releases page, install it using Homebrew or run it as a Docker image. For example, to install Terrascan on macOS using Homebrew, you can run the following command:
brew install terrascan
To verify that Terrascan is installed correctly, you can run:
terrascan version
You should see the output similar to this:
version: v1.18.1
If you’re following along in our GitHub repo with codespaces, terrascan is already installed for you.
Scanning your IaC code
To scan your IaC code for security issues, you can use the terrascan scan command. By default, Terrascan will scan the current directory for Terraform files and report any violations found. You can also specify the type of IaC using the -i flag, such as -i k8s for Kubernetes or -i dockerfile for Dockerfile.
For example, to scan a single Terraform file, you can run:
terrascan scan -f Terraform/s3.tf
You should see the output similar to this:

As you can see, Terrascan has detected one high-severity violation that indicate that the S3 bucket versioning is recommended for easy recovery from unintended user actions.
Example use cases of Terrascan
Use case 1: Scan Terraform Files
Now let’s scan our same Terraform files using Terrascan. Run the following commands:
terrascan scan -d ./Terraform
Let’s examine the output:


Use case 2: Scanning Kubernetes manifests
Let’s see how terrascan performs when it comes to Kubernetes manifests. Run the following commands:
terrascan scan -d ./Kubernetes -i k8s
And here is the output:



Terrascan Custom Policies
Once again, let’s create a custom policy. We will use Rego with Terrascan to check if an S3 bucket has an ACL that is public-read with a tag Scope=”PCI”.
First, you will need to install the OPA binary. On Linux you can use the following script:
curl -L -o opa https://openpolicyagent.org/downloads/v0.51.0/opa_linux_amd64_static
And on Mac use:
curl -L -o opa curl -L -o opa https://openpolicyagent.org/downloads/v0.51.0/opa_darwin_amd64
Once again, if you are following along with GitHub codespaces, it will already be installed for you.
Now let’s examine the files you will need. You need to files, a .json one where you specify a few attributes of the policy and a .rego file where you define the actual policy.
We’ve included these 2 files in the terrascan_custom_policy folder in our repo under the Terraform folder.
Below is the content of the pci_policy_terrascan.json file:
{
"name": "PCI_S3_PUBLIC_READ",
"file": "pci_policy_terrascan.rego",
"policy_type": "AWS",
"resource_type": "aws_s3_bucket",
"template_args": {
"name": "PCI_S3_PUBLIC_READ",
"prefix": "",
"suffix": ""
},
"severity": "HIGH",
"description": "Make sure S3 bucket ACL is NOT public-read if it has a Scope=PCI tag",
"category": "Identity and Access Management",
"version": 1,
"id": "pci_policy_terrascan"
}
And below is the content of the pci_policy_terrascan.rego file:
package accurics
{{.prefix}}{{.name}}{{.suffix}}[array.id] {
array := input.aws_s3_bucket[_]
array.config.acl == "public-read"
array.config.tags == {"Scope": "PCI"}
}
An easy way to generate the above two files is to use the Terrascan Rego Editor VS Code extension.
Now we’re ready to run our scan, you can use the command below that will do it for us. Notice how we use the --policy-path to point to the directory where our custom rego policies live. The second --policy-path flag points to the general place where terrascan stores all its policies. If you omit the last --policy-path you will only run the scans for the custom policy that we created.
terrascan scan --policy-path ./Terraform/terrascan_custom_policy --policy-path ~/.terrascan/pkg/policies/opa/rego}
Finally, the output will be as shown below:

What is Terrascan: Benefits, Key Features, and Examples


What is Infrastructure-as-Code
Infrastructure-as-Code (IaC) is a method of automating the management and provisioning of infrastructure resources. Instead of manually clicking buttons on a web console, IaC enables organizations to describe their system architecture using code, allowing them to store, version, and track changes to their systems and application infrastructure.
The goal is to automate the process of setting up, configuring, deploying, and managing applications. IaC is a powerful technology that allows you to provision and manage any cloud resource in an automated, declarative way. Infrastructure-as-Code is now the de facto standard for new projects and the focus of many organizations is now migrating from legacy architecture to IaC.
Before Infrastructure-as-Code: Pre-IaC Architecture
IaC’s major transformation was that developers could now create a consistent, repeatable workflow, bringing about wider-scale deployments across a range of resources, environments, and locations.
Delving a bit deeper, how did it achieve this? IaC provisions infrastructure and application resources through machine-readable definition files instead of through physical hardware configuration or interactive configuration tools.
Before, infrastructure management was a costly, manual process that hindered scale and availability. There was extreme variability in infrastructure largely due to manual configuration. Manual processes were more error-prone and could not be scaled, much less standardized. Remote access tools slowly entered the market, but system administrators (sysadmins) still had to provision new hardware and resources manually by connecting to remote cloud providers via APIs.
Environment drift: When infrastructure for an application's software development process – development, staging, and production environments falls out of sync. Environment drift, or configuration drift, causes inefficiencies and can be expensive in direct cost and potential user experience impacts. If your app’s development environment varies from the production environment, this can lead to failure in production or bugs, and even prevent recovery in the event of disaster.
Automation changed that, reducing the problem of forgotten tasks, automating configuration drift detection, and allowing other features to automatically manage infrastructure problems or remedy issues. Among those revolutionary features were version control systems (VCS), configuration management tools, and orchestration capabilities.
Infrastructure-as-Code Benefits
Now, IaC has made IT more efficient than ever before, solving numerous IT challenges and enabling new capabilities such as:
Recreating environments
It used to be challenging to recreate an identical environment after deployment because the systems it interacted with also had to be updated.
With Infrastructure-as-Code, users can recreate infrastructure from scratch, and on-demand, simply by replaying code. The pipeline uses a prescribed set of parameters for deployment and creates a new environment that is identical in terms of the number of hosts, networks, data centers, clusters, data stores, etc., every time that it runs. The infrastructure code can even be versioned with the product, making it easy for engineers to recreate the infrastructure as it was when a previous version of the product was released.
Minimizing errors
IaC minimizes the need for manual infrastructure management, reducing the risk of human error. Rather than depending on engineers to remember past configurations or respond to failures, everything is in the code, under your source control system.
When changes go to production, the infrastructure code is checked in a code review or in a review by a gatekeeper.
Supporting teamwork and collaboration
Using IaC, engineers don’t have to deal with problems caused by conflicting changes in a shared environment. Infrastructure-as-Code makes it easier to work as a team and to share code with colleagues and other teams, so they can utilize it to set up their own environments. Using a VCS, different teams can each work on a separate piece of the infrastructure, rolling out their changes in a controlled manner.
Reducing cloud expenditure
The shift from bare metal infrastructure investments to the cloud reduced CapEx, and IaC has reduced them even further by enabling auto-scaling capabilities. With IaC, a software developer writes code and configuration management instructions that trigger actions according to actual needs and accurately reflects the structure of the real operating environment. Infrastructure-as-Code lets you manage your environments easily and automatically deactivates environments you no longer need.
DevOps and Infrastructure-as-Code
DevOps emphasizes automating manual tasks that typically take up a lot of software developers’ and IT operators’ time. IaC is one of the key technical practices that enable DevOps within an organization, by automating the provisioning and management of IT infrastructure. With IaC, developers can self-serve the provisioning of environments, saving time for them and the operations team.
How Infrastructure-as-Code Works
Key Concepts
- GitOps – This involves integrations between your IaC tech stack and the infrastructure itself via your Git repository (on GitHub, GitLab, Bitbucket, etc.). This includes streamlining changes as much as possible, such as embedded PR commands.
- Version Control – This is related to GitOps, where you will want to have a firm grasp on what versions of a framework, module, provider, or code you are using for your current work or for a specific kind of deployment.
- State Management – This refers to the storage and maintenance of your desired state. Some IaC tools do not encrypt state files by default. For example, Terraform does not encrypt (it’s a premium feature in Terraform Cloud) while OpenTofu does.
- Registry – A registry is a marketplace for finding add-ons, integrations, packages, and policies. It often refers to the Terraform Registry.
- Templates – Templates refer to reusable packages of code or files that provision resources in certain configurations. They should be git-based.
- Modules – This is the term for a configuration package, or collection of config files, in Terraform.
- Providers – This is the term for an integration mechanism, akin to an API, between Terraform and a third-party app.
- FinOps – This refers to the automation of cost monitoring, spending projections (cost estimation), and budget notifications/alerts so users can track the expense of their cloud deployments (in IaC and other sectors of DevOps).
- IaC Pipelines – This is an ordered sequence of common or repetitive tasks that is configured to run automatically so as to save teams time with projects.
- IaC Workflows – This refers to the sequence of status changes of infrastructure within a pipeline.
Declarative vs. Imperative Approach for Infrastructure Configuration
As with other subjects in DevOps, infrastructure has declarative and imperative approaches. Think of it like a means to an end; or rather, the imperative approach defines the means and the declarative approach defines the end.
The imperative approach focuses on the sequence of commands needed to reach the desired state of your application, specifically in this case your infrastructure. In contrast, the declarative approach is becoming more popular thanks to better automation tools, as devs can define the endgame state and a given tool will configure an environment to reach that stated goal.
Chef is the most prominent tool relying on imperative programming for IaC. Some have a mix of imperative and declarative implementations, namely Pulumi, Salt, and Ansible. However, declarative is gaining traction and effectiveness thanks to advances in automation. Declarative IaC tools include OpenTofu, Terraform, AWS CloudFormation, and Puppet.

Challenges and Best Practices
Many best practices for IaC overlap with DevOps best practices in general. However, there are caveats specific to maintaining code-based infrastructure.
Idempotency
Yeah, read that word carefully. This refers to being able to reapply code multiple times while getting a consistent result every time. This is as much a principle as it is a requirement to automate infrastructure, and templating will reduce or outright eliminate errors in many use cases. The goal of consistency also relates to testing, making sure that a deployment works in multiple environments and avoids the ‘it works on my machine’ problem.
CI/CD & Testing
Many teams have not instilled continuous integration and continuous deployment into their infrastructure deployments. CI/CD should be standardized in all layers of development and operations, including IaC. Constant changes to infra require testing and full VCS integration.
Observability – Logs & Debugging
Depending on the kind of deployment, you should have logging configured across your entire tech stack. Additionally, consider metrics and tracing to monitor every level of your infrastructure. Finally, debugging should be standard protocol with any code changes, especially if you’re changing code within a resource instead of switching out resources.
Immutability (when applicable)
Immutability refers to making code unchangeable. In such cases, changes mean replacing a resource entirely rather than editing its internal code. This is not always practical, but when it is, it eliminates an area prone to frustrating errors.
Version Control (including environmental parity)
As mentioned with CI/CD, VCS can protect you from influencing the wrong environment or pushing changes that aren’t applicable in some versions of your Infrastructure-as-Code framework. This is even more essential when dealing with multi-framework deployments, which get confusing.
Cost Management/FinOps
Cost management and cost projection/prediction are getting better with newer tooling available to all classes of developers, and the same with IaC FinOps for system architects. Tracking cloud spending gets tricky, especially with the long list of internal features that cloud providers like AWS or Azure offer.
State Management
Storing the state of your IaC framework is fundamental. With many tools moving toward declarative programming, keeping that well-defined state protected is crucial.
Modularization
Relating to templates and paralleling containers, IaC frameworks like Terraform and OpenTofu rely on modules to organize resources defined by configuration files in the same directory. In the case of Terraform, they will be .tf or .tfjson files. There are three primary reasons behind using a Terraform module: 1) packaging resources together that will be used together in a reusable configuration, 2) sharing standardized configurations across organizations, and 3) don’t-repeat-yourself programming (DRY).
Access (Roles and Users)
This is part of the security concerns of an IaC setup. You want to manage and allow access to as many people in your organization as possible, but make sure that levels of access are well-defined in specific roles. This makes RBAC, role-based access control, as essential in IaC as any other sector of DevOps.
Watch out for these IaC Pitfalls...
While IaC has clear advantages, it also presents unique challenges that usually emerge as you scale.
1. Integration with management tools
To harness the full benefits of IaC, it must be integrated into all processes, including CI/CD workflows, notification tools like Slack, security tools, system administration, IT operations teams, and DevOps teams, with well-documented policies and procedures. Without full integration, errors can quickly spread across the system.
2. Longer turnaround
When using IaC, every change has to be coded, tested, and reviewed before it is applied. Changes are more complex and must be planned carefully to avoid significant downtime. Learn more: Video: Top IaC Challenges
3. Lack of cloud expense oversight
Since IaC deploys infrastructure components automatically, it can be hard to keep track of expenses. Development teams are often unaware of the financial ramifications of their code, and expenses can build up quickly without monitoring tools that are designed for IaC.
That’s why some would explicitly include FinOps in the rubric of IaC. Regardless, it’s an essential part of managing complex infrastructure. For instance, env zero includes cloud cost monitoring and optimization in its feature set.
IaC Toolchain Sprawl
One of the primary benefits of adopting Infrastructure-as-Code is consistency, which is only possible if teams across your organization are using different IaC tools and approaches. In many cases, implementing IaC requires a cultural shift in addition to the technical one to ensure success. The advantages far outweigh any overhead associated with implementing and managing IaC.
We’ll try to make some sense of that tool sprawl with the following section, covering the major frameworks and associated platforms in the world of infra.
Infrastructure-as-Code Frameworks
IaC’s major tools are frameworks that incorporate multiple functions into a single platform. The list below starts with those assets and then continues with IaC tools that are popular for one or multiple functions within IaC tech stacks. The following Venn diagram shows what kind of features go into a complete IaC framework, but note its complex structure that shows some tools can cover much of what you need for a deployment, but not everything.

Terraform & OpenTofu
Terraform is an IaC tool created and maintained by HashiCorp; it is currently the most widely used Infrastructure-as-Code tool in the industry. It is widely credited with creating common best practices including arguably the use of declarative programming.
In Summer 2023, Terraform moved away from Open Source licensing. As a response, several companies (including env0) collaborated to create an open-source, alternative known as OpenTofu. OpenTofu is currently managed by the Linux Foundation. Its initial release, v1.6.alpha, seeks to be a drop-in replacement for the Terraform version of the same number.
Terragrunt
Terragrunt is a thin wrapper for Terraform that provides additional tools for deploying hooks, managing dependencies, remote states and multiple environments, as well as keeping your Terraform configuration files DRY (Don't Repeat Yourself). Terragrunt is open-source and a popular choice for Terraform users looking for ways to keep their codebase efficient, clean and well-organized.
AWS CloudFormation
CloudFormation is the AWS service for IaC. It uses JSON or YAML to define resources. Its added advantage is that it works seamlessly with other AWS tools. On the flip side, its main disadvantage is that it only handles AWS infrastructure resources. Additionally, it limits templates to only 500 resources apiece, arbitrarily still keeps some processes manual, and has confusing documentation.
Pulumi
Pulumi is an open-source IaC framework that uses common programming languages to configure and provision resources rather than a domain-specific language like HCL. That also allows it to take advantage of inherent features of languages like Python, JavaScript, C#, and Go among others, as well as various implementations of those languages like TypeScript, Node.js, .NET, etc.
Like Terraform and OpenTofu, Pulumi supports major cloud providers - AWS, Azure, and GCP cloud providers. It also features its own state management and language hosting, plus a command-line interface (CLI).
Crossplane
Crossplane is an open-source IaC framework managed by the Cloud Native Computing Foundation (CNCF) with a specific focus on managing Kubernetes infrastructure. It keeps application and infrastructure configuration in the same control plane (Kubernetes application layer), and uses other common k8s tools like Helm or Kustomize to launch IaC templates.
Atlantis
Atlantis is a GitOps-focused tool that often acts as an add-on to basic IaC frameworks. It applies infrastructure automation with Terraform actions by use of commands embedded in pull requests (PRs) and to work from within their VCS. It still uses the webhooks native to Terraform to manage this, trying to get more done in Terraform by working through comments and PRs from GitHub, GitLab, and other version control systems.
CI/CD & Configuration Tools Used for IaC
Ansible
Ansible is an open-source CI/CD application that applies automation to pipelines but also functions as a configuration manager and orchestration tool. It is often compared with Jenkins, though the two tools can also function together in certain environments. In addition, Ansible integrates with Terraform. It is written in Python and works from the command line/terminal.
Argo CD
Argo CD is an open-source continuous delivery tool focused on Kubernetes that uses declarative programming. It monitors activity in Kubernetes clusters and compares infrastructure there to the version stored in a specified git repository. It will resolve any differences between the two versions to maintain the desired state. ArgoCD is commonly used in conjunction with IaC tools for managing and orchestrating applications alongside infrastructure.
Jenkins
Jenkins is mainly an open-source continuous integration tool. It automates testing, packaging, building, and deployment. It is more broadly considered a CI/CD tool, as it also handles continuous delivery. It supports several VCSs from the most popular to more niche options: GitHub, GitLab, Bitbucket, Git, Mercurial, Subversion, etc. Many developers use Jenkins to deploy infrastructure components, but it has limitations relative to fully IaC-dedicated frameworks. It can run multiple jobs through multi-threading.
CircleCI
CircleCI is, despite the limiting name, a full CI/CD tool for automating builds, testing, and deployments. Through its integration with a VCS, any change in a repository will trigger a CircleCI run job and run jobs simultaneously through parallelism/parallel processing (in contrast to Jenkins’ multi-threaded approach).
SaltStack
SaltStack, also known as the Salt Project or simply Salt, mainly serves as an orchestration and configuration tool. It has an emphasis on automating repeated DRY tasks. It uses the push method to make changes to code.
Chef
Chef is usually defined as a configuration management tool, which automates – writes, tests, and deploys – code. It can also be defined broadly as an infrastructure-as-code framework and automation platform. Its DSL is based on Ruby. To draw an analogy with Terraform’s modules, Chef’s “cookbooks” package together multiple “recipes,” e.g. config files that cover which resources to manage and in what order to execute them. As mentioned above, Chef relies mainly on imperative programming. Its client-side server architecture is known to support popular operating systems like Ubuntu and Windows.
Puppet
Puppet is a configuration management tool for automating code; it is often directly compared with Chef. It can also be defined broadly as an IaC framework with uses for orchestration, CI/CD, and monitoring. It mainly supports declarative programming. It supports different implementations of Linux in addition to other operating systems (MacOS, Windows, Ubuntu, Debian, etc.). It relies more on the pull method to make changes.
Infrastructure Management at Scale with env0
env zero is a self-service automation platform and management layer that sits above an IaC framework. It provides a simplified user interface for administering environment templates, controlling access roles, managing variables, defining policies, overseeing FinOps mech anisms, setting parameters for different developer environments (including ephemeral), and more.
All in all, env0’s product reflects what the company sees as best practices for Infrastructure-as-Code, and therefore offers a suite of services:
Infrastructure Automation
env zero extends the creation of pipelines and workflows to Infrastructure-as-Code, using what are now established best practices in other segments of DevOps. env zero integrates with tools from different parts of the IaC tech stack – version control systems, configuration managers, orchestration tools, and CI/CD platforms – to create a consistent workflow with persistent changes pushed/pulled to your infrastructure.

Self-Service & Visibility
The emphasis on self-service leads to an emphasis on ‘granular RBAC’, where admins can add numerous specifications to custom roles in order to extend secure access across an entire organization as widely as possible. Utilizing Policy-as-Code and integrations with tools like OPA or Checkov, you can be confident that the right people have the right amount of access and let teams function independently to push/pull their changes to code.
With that, teams do not have to wait for someone else’s okay to be productive. Organization members can achieve that by using ephemeral environments (with time-to-live settings) to test new features, automated scheduling, and configurable templates.
Additional features like dashboarding and audit logs, plus available integrations with several major observability platforms, give admins even more data to adjust those policies in the long-term.
Covering All Frameworks
env zero is framework-agnostic. In other words, env zero covers Terraform, Pulumi, CloudFormation, Terragrunt, and others. While some companies (HashiCorp, AWS) provide a premium service on top of their IaC frameworks, they often encourage vendor lock-in and cover their own frameworks at the expense of others.
Fair Pricing, FinOps Built-in
env zero encourages scale by using deployment-based pricing. However, other services such as Terraform Cloud price by RUM – or resources under management. RUM guarantees a higher bill for companies month to month, as teams are always adding more complex code and configuration changes.
Deployment pricing provides flexibility to team managers to customize their environments in such a way to be smart with their cloud spending. env zero encourages this further with its slew of FinOps features like cost management, budget notifications, and project-based calculations. Those analyses inform future policies to limit or increase budgets for users, teams, specific resources, or particular deployments.
What is Infrastructure-as-Code? IaC 101


In this section of the IaC Scanning Tools Guide, we will be looking at Checkov and discussing the benefits, key features, and looking at some real world examples. You can explore the other parts of this guide below.
Jump to section:
What is Checkov?
From the Checkov website:
Checkov scans cloud infrastructure configurations to find misconfigurations before they're deployed.
Checkov uses a common command line interface to manage and analyze infrastructure as code scan results across platforms such as Terraform, CloudFormation, Kubernetes, Helm, ARM Templates and Serverless framework.
Checkov works by scanning IaC files for common security and compliance issues, such as open security groups, unencrypted storage buckets, or missing encryption keys. It uses a policy-as-code framework that allows users to define and enforce rules for their cloud resources. Checkov comes with more than 750 built-in policies that cover industry standards like CIS Benchmarks, PCI, and HIPAA. Users can also create and contribute custom policies using Python or YAML.
Checkov can be installed as a command-line tool or as a Visual Studio Code extension. It can also be run as a pre-commit hook or as part of a continuous integration pipeline. Checkov provides detailed reports of the scan results, highlighting the violated policies and suggesting remediation steps.
Checkov is an open-source project created by Bridgecrew, a cloud security company that provides end-to-end solutions for cloud-native environments. Palo Alto Networks has acquired Bridgecrew in March of 2021. Checkov is actively maintained and updated by Bridgecrew and a community of contributors. You can find more information about Checkov on its website or GitHub repository. Users can also leverage the Bridgecrew platform to get additional features like runtime scanning, pull request annotations, repository badges, compliance reports, and more.
Benefits and Key Features of using Checkov
Some benefits and key features of using Checkov are:
| Feature | Details |
|---|---|
| Scanning IaC | Yes for security and compliance before deployment |
| IaC Frameworks Supported | Multiple including Terraform, CloudFormationn, and Kubernetes |
| Reporting | Detailed reports and recommendations for fixing the detected issues |
| Integrations | Many tools including GitHub, GitLab, Bitbucket, Jenkins, and VS Code |
| Policy Customizations | Yes using Python or YAML |
| Open-source | Yes |
How to get started with Checkov
How to install Checkov?
The first step is to install Checkov on your machine. If you follow along with our GitHub repo using Codespaces, it will be installed for you. Otherwise, you can use pip, brew, or docker to install Checkov. For example, to install Checkov using pip, you can run the following command:
pip install checkov
How to use Checkov?
Once you have Checkov installed, you can use it to scan your IaC files for security and compliance issues. You can run Checkov on a single file, a directory, or a git repository. For example, to scan a Terraform file named main.tf, you can run the following command:
checkov -f main.tf
Checkov will output a list of checks that passed or failed for each resource in your file. You can also see the check ID, the check name, where in the file the check occurred and a URL to a guide for more explanation. You can also get the severity level for each check if you sign up for a free account with Bridgecrew and add your API. Check this link to see how to work with severity levels: Prioritize, skip, and fail with policy severities in Checkov - Bridgecrew Blog
Here is a sample output of Checkov without using the API:


You can also use the guide URL to access the Bridgecrew platform and see more details and remediation steps for each check.
You can customize Checkov's behavior by using various flags and options. For example, you can use the --framework flag to specify which IaC framework you want to scan (terraform, cloudformation, kubernetes, etc.). You can use the --check flag to run only specific checks by their ID or name. You can use the --skip-check flag to skip specific checks by their ID or name. You can use the --output flag to change the output format (cli, json, junitxml, sarif, etc.)
Example use cases of Checkov
Now let’s take a look at two use cases. One for scanning Terraform files and the other for scanning Kubernetes manifests.
Use case 1: Scan your Terraform files for misconfigurations
Terraform is a widely used tool for provisioning and managing cloud resources using declarative configuration files. However, writing Terraform code can be prone to human errors and oversights that can lead to security and compliance risks for cloud resources. For example, you might accidentally expose a sensitive resource to the public internet, or forget to enable encryption or logging for a storage bucket.
Checkov can help you avoid these common pitfalls by scanning your Terraform files for hundreds of predefined policies that cover best practices and standards such as CIS benchmarks, PCI, HIPAA, and more. Checkov can also help you enforce custom policies that match your organization's specific requirements and preferences.
To use checkov to scan your Terraform files, you can simply run the following command in your terminal, the -d flag tells checkov to scan an entire directory.
checkov -d /path/to/terraform/code
This will output a report that shows the status of each policy check (passed or failed), the resource and attribute that triggered the check, and a link to a detailed explanation of the policy and how to fix it.
We’ve taken some Terraform code from the terragoat GitHub repo for illustration.
Try it yourself. Change your directory into the Terraform folder in our repo and then run the following command:
checkov -d ./Terraform
The output is too verbose to show here but it is similar to the above-shown snapshots.
You can also use checkov to scan your Terraform files before applying them to your cloud environment, by integrating it with your CI/CD pipeline or using a pre-commit hook. This way, you can catch and fix any issues before they become a problem in production.
Use case 2: Scan your Kubernetes manifests for security best practices
Kubernetes is a powerful platform for orchestrating and scaling containerized applications. However, Kubernetes also introduces new challenges and complexities for securing your workloads and clusters. For example, you might need to ensure that your pods run with the least privilege principle, that your network policies restrict unauthorized access, or that your secrets are stored securely.
Checkov can help you audit and harden your Kubernetes manifests by scanning them for dozens of policies that cover security best practices and recommendations from sources such as the Kubernetes documentation, the CIS Kubernetes benchmark, and the NSA/CISA Kubernetes hardening guidance.
To use checkov to scan your Kubernetes manifests, you can run the following command in your terminal:
checkov -d /path/to/kubernetes/code --framework kubernetes
This will output a report similar to the one for Terraform, showing the status of each policy check, the resource and attribute that triggered the check, and a link to a detailed explanation of the policy and how to fix it.
Let’s try it. Using the following NGINX deployment found in the folder Kubernetes and the file nginx_deployment.yaml in our repo:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Run the commands below:
checkov -d ./Kubernetes --framework kubernetes
Check the output. Below is a small section of the output:


Checkov Custom Policies
As mentioned before, we can create our own custom policy in Python or YAML. In this example, we will use Python as shown in the docs.
This example assumes a unique need to enforce bucket ACL policies only when the tag Scope=PCI is present.
You will find a file called s3_pci.tf containing the following S3 bucket Terraform resource. Notice how we specified the acl to be public-read and the tag is Scope=”PCI” to trigger a violation.
resource "aws_s3_bucket" "credit_cards_bucket" {
region = var.region
bucket = local.bucket_name
acl = "public-read"
force_destroy = true
tags = {
Scope = "PCI",
}
}
Notice the content of the folder called checkov_my_extra_checks:

The __init__.py file contains the following:
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
And S3PCIPrivateACL.py contains the following:
from lark import Token
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.common.models.enums import CheckResult, CheckCategories
class S3PCIPrivateACL(BaseResourceCheck):
def __init__(self):
name = "Ensure PCI Scope buckets has private ACL (enable public ACL for non-pci buckets)"
id = "CKV_AWS_999"
supported_resources = ['aws_s3_bucket']
# CheckCategories are defined in models/enums.py
categories = [CheckCategories.BACKUP_AND_RECOVERY]
guideline = "Follow the link to get more info https://docs.bridgecrew.io/docs"
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources, guideline=guideline)
def scan_resource_conf(self, conf):
"""
Looks for ACL configuration at aws_s3_bucket and Tag values:
https://www.terraform.io/docs/providers/aws/r/s3_bucket.html
:param conf: aws_s3_bucket configuration
:return:
"""
if 'tags' in conf.keys():
environment_tag = Token("IDENTIFIER", "Scope")
if environment_tag in conf['tags'][0].keys():
if conf['tags'][0][environment_tag] == "PCI":
if 'acl' in conf.keys():
acl_block = conf['acl']
if acl_block in [["public-read"], ["public-read-write"], ["website"]]:
return CheckResult.FAILED
return CheckResult.PASSED
check = S3PCIPrivateACL()
Now run the command below and observe the output:
checkov -f Terraform/s3_pci.tf --external-checks-dir Terraform/checkov_my_extra_checks --check CKV_AWS_999

Notice that using the above command, we specified the exact check that we created with ID: CKV_AWS_999. There is a violation because the tag contains the scope PCI and the acl is public-read. If you’re interested in using YAML for custom policies, check out the documentation.
What is Checkov: Benefits, Key Features, and Examples


