# Use Steampipe to scan Terraform code, plans, and state files

> Query all aspects of your Terraform environment to answer ad-hoc questions and scan for security best practices.

By Steampipe Team
Published: 2023-10-04


When the [Terraform plugin](https://hub.steampipe.io/plugins/turbot/terraform) arrived in December 2021, it was an immediate game-changer. Now you could not only query live [AWS](https://hub.steampipe.io/plugins/turbot/aws), [Azure](https://hub.steampipe.io/plugins/turbot/azure), and [GCP](https://hub.steampipe.io/plugins/turbot/gcp) infrastructure, you could also write SQL to answer questions about the Terraform configurations that deploy that infrastructure. Then in January 2022 the other shoe dropped. New compliance mods enabled you to also check Terraform-configured [AWS](https://hub.steampipe.io/mods/turbot/terraform_aws_compliance), [Azure](https://hub.steampipe.io/mods/turbot/terraform_azure_compliance), and [GCP](https://hub.steampipe.io/mods/turbot/terraform_gcp_compliance) infrastructure. We've since added hundreds of controls to the suite of Terraform Compliance mods. And you can now query your plan and state files, as well as your `.tf` files.

## Query your `.tf` files

Let's first review the basics. You've always been able to run queries against static `.tf` files. Here's a query to answer the question: "How are public access blocks configured for S3 buckets?"

```sql
select
  attributes_std ->> 'block_public_acls' as block_public_acls, path 
from 
  terraform_resource
where 
  type = 'aws_s3_bucket_public_access_block'
```

```
+-------------------+-----------------------------------------------------------------------------------+
| block_public_acls | path                                                                              |
+-------------------+-----------------------------------------------------------------------------------+
| false             | /home/jon/terraform-examples/launchweek/bucket.tf                                 |
+-------------------+-----------------------------------------------------------------------------------+
```

And this query answers the question: "How many resources of each type are configured?"

```sql
select
  type,
  count(*)
from
  terraform_resource
group by 
  type 
order by
  count desc
```

```
+---------------------------------------------+-------+
| type                                        | count |
+---------------------------------------------+-------+
| aws_route53_record                          | 13    |
| google_bigquery_table                       | 11    |
| aws_iam_role_policy_attachment              | 7     |
| google_storage_bucket_object                | 7     |
| aws_security_group                          | 7     |
...
```

## Check `.tf` files for S3 bucket public access

The [Terraform AWS Compliance](https://hub.steampipe.io/mods/turbot/terraform_aws_compliance) mod uses this query capability to define controls. For example, as shown in the first query, the `block_public_acls` setting was false for one resource. Here's the offending code.

```
resource "aws_s3_bucket_public_access_block" "public_access_bucket_1" {
  bucket = aws_s3_bucket.my_bucket_1.id

  block_public_acls   = false # should be true
  block_public_policy = true
  ignore_public_acls = true
  restrict_public_buckets = true
}
```

There's a [control](https://hub.steampipe.io/mods/turbot/terraform_aws_compliance/controls/control.s3_bucket_public_access_blocked) to check for that misconfiguration.

```bash
steampipe check control.s3_bucket_public_access_blocked
```
![terraform public access alarm](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-alarm.png)

After setting `block_public_acls` to `true` in the `.tf` file, we're all green.

![terraform public access ok](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-ok.png)

## Check the plan

Static analysis of `.tf` files isn't the only tool you'd like to have in your Steampipe Terraform kit. Plan and state files are also rich sources of information. And now the Terraform plugin can interrogate those too. Why? Let's look at a few examples.

In this scenario, the settings are defined by variables. 

```hcl
variable "block_public_acls" {
  type        = bool
  default     = true
}

resource "aws_s3_bucket_public_access_block" "public_access_bucket_1" {
  bucket = aws_s3_bucket.my_bucket_1.id

  block_public_acls   = var.block_public_acls
  ...
}
```

Now somebody runs `terraform plan` in a way that injects a misconfiguration. 

```
terraform plan -var 'block_public_acls=false' -out=plan.tfplan
```

If you run the control again, it'll still be green because nothing has changed in the `.tf` file. Now let's make the plan queryable as well. 

```
terraform show -json plan.tfplan > plan.json
```

Now the control reports trouble. The `.tf` passes, but the plan reveals the problem.

![terraform public access plan alarm](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-plan-alarm.png)

## Check the state file too!

But we're feeling reckless, and we deploy anyway. Now we're in worse trouble! 

![terraform public access plan and state alarm](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-plan-and-state-alarm.png)

Let's  redo the plan without the `-var` to get the good default, and recheck.

![terraform public access plan ok state alarm](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-plan-ok-state-alarm.png)

 Finally let's deploy the fix and check one more time.
 
 ![terraform public access tf and plan and state ok](/images/blog/2023-10-launch-terraform-scans/public-access-blocks-tf-and-plan-and-state-ok.png)

All green again!

## See it in action

<div className="flex justify-center">
<iframe
    class="youtube-video"
    src="https://www.youtube-nocookie.com/embed/JG8eOffr4jk"
    frameBorder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    allowFullScreen
    title="Interrogate Terraform: Scan and query Terraform code, plans and state files."
>
</iframe>
</div>

## Tailor-made for GitOps shops

This unified ability to query and scan Terraform files (as well as deployed infrastructure) is available everywhere Steampipe can run. That includes [CI/CD pipelines](https://steampipe.io/docs/integrations/overview) where, for GitHub in particular, we have just announced [two new actions](https://steampipe.io/blog/github-actions) that make it easier than ever to run Steampipe queries and checks in GitHub workflows, and now also embed annotations in pull requests to flag compliance issues.

There are a million ways to use these new features and controls. Give them a try and [let us know](https://steampipe.io/community/join) how it goes!

