Getting started on driftctl: start tracking drifts from a clean state

How to start tracking drifts from a clean baseline even if you are moving to Terraform.

Share on twitter
Share on reddit
Share on linkedin

This post is part of the walkthrough that will get you started on driftctl in a couple of steps. If you haven’t already done so, you should consider setting up your AWS authentication to use driftctl in a secure way and configuring your Terraform provider version as well.


Many of us have reasons to not target 100% IaC coverage of our AWS accounts. Some of us are moving to Terraform. In this case, driftctl continuously delivers drift notifications that we don’t care about. Behold! There’s a solution.

In this post, we’ll show how to start using driftctl with a clean state, by ignoring all the current resources that are not yet under control. This will be easily done in a couple of seconds by generating a .driftignore file from a driftctl JSON output.

We’ll start with a heavily drifted AWS account, and end up with a clean state so you can actually start tracking resources. We’ll do all the steps with both the CLI and Docker container version.

Day 1, too many unmanaged resources

What are unmanaged resources? Those are simply resources (EC2 instances, Security Groups, S3 buckets…) that are not managed by Terraform. When we run driftctl against a bunch of Terraform states, unmanaged resources will show up.

But in many cases, it’s perfectly understandable and acceptable for the time being to have unmanaged resources in the AWS account.

Many of us:

  • do not have the luxury to have AWS accounts fully managed by Terraform,
  • use a mix of CloudFormation (CFN) and Terraform, or some legacy scripts running here and there,
  • work with different teams on shared AWS accounts,
  • are currently moving existing projects to Terraform ,
  • create new projects in existing AWS accounts,
  • will fix those drifts soon, but not now (“it’s in the backlog!”)

So, the driftctl experience is quite frustrating for now in this mixed situation: while we have very good reasons to want to know what goes wrong from now on, we are still getting a ton of noise in the output that renders the tool almost useless.

Sure, there’s the .driftignore file, that works similarly to the .gitignore file, and we could still fill the file manually. But it works with a handful of resources, definitely not with a lot of resources.

The good news is that driftctl v0.9.0 ships with a generator of .driftignore, so we can get started in no time and ignore all the drifts!

How to automatically generate a .driftignore file

If you’re like me, always trying stuff here and there, or if you are moving to Terraform, you’ll end up with a messy driftctl output like that:

					$ driftctl scan --from tfstate://**/*.tfstate
Scanned states (4) 
Scanned resources (62)      
Found resources not covered by IaC:
    - AKIASBXWQ3AYR4KWTMHD (User: driftctl_ro)
    - AKIASBXWQ3AYT7WXIBNE (User: labs)
    - AKIASBXWQ3AYUFW6ZCWO (User: endgame-s3-demo)
    - AKIASBXWQ3AYWVVI6DEW (User: terraform)
    - AWSServiceRoleForAccessAnalyzer-arn:aws:iam::aws:policy/aws-service-role/AccessAnalyzerServiceRolePolicy
    - AWSServiceRoleForConfig-arn:aws:iam::aws:policy/aws-service-role/AWSConfigServiceRolePolicy
    - AWSServiceRoleForRDS-arn:aws:iam::aws:policy/aws-service-role/AmazonRDSServiceRolePolicy
    - AWSServiceRoleForSSO-arn:aws:iam::aws:policy/aws-service-role/AWSSSOServiceRolePolicy
    - driftctl_ro-arn:aws:iam::141177182257:policy/driftctl_ro
    - endgame-s3-demo-arn:aws:iam::aws:policy/AmazonS3FullAccess
    - labs-arn:aws:iam::aws:policy/AdministratorAccess
    - terraform-arn:aws:iam::aws:policy/AdministratorAccess
    - driftctl_assume_role
    - Source: arn:aws:sqs:us-east-1:141177182257:queue-6qaidu.fifo Dest: arn:aws:lambda:us-east-1:141177182257:function:lk6n03-lambda-demo
    - arn:aws:iam::141177182257:policy/cloudskiff_qa_policy
    - arn:aws:iam::141177182257:policy/driftctl_ro
    - arn:aws:iam::141177182257:policy/test123
    - driftctl_assume_role:driftctl_policy
    - driftctl_ro
    - endgame-s3-demo
    - labs
    - terraform
    - a-bucket-filled-with-files
    - blob-9082437
    - dctl-1
    - driftctl-tfstates
    - s3-bucket-1-6qaidu
    - test-resource-exposure-caxyxllsajfrzbwe
    - test-resource-exposure-caxyxllsajfrzbwe
Found 32 resource(s)
 - 3% coverage
 - 1 covered by IaC
 - 31 not covered by IaC
 - 0 missing on cloud provider
 - 0/1 changed outside of IaC

Hint: use gen-driftignore command to generate a .driftignore file based on your drifts

It’s cool the first time we launch the tool, so we have a clear overview of drifted and unmanaged resources, based on the cumulative layers of Terraform states – but it’s pretty useless afterwards, as we won’t fix all the drifts right away.

Step 1 - Generate a JSON output

So let’s start by creating a workable JSON output of this scan:

					$ driftctl scan --from tfstate://**/*.tfstate --output json://drifts.json
Scanned states (4) 
Scanned resources (62)      

Hint: use gen-driftignore command to generate a .driftignore file based on your drifts


Take a look at this drifts.json file. It contains the exact same output, but as a structured JSON:

					$ jq '.unmanaged' < drifts.json
    "type": "aws_iam_access_key"
    "type": "aws_iam_access_key"

Step 2 - Generate a .driftignore from JSON

Now we will simply use the new driftctl gen-drifignore command to generate a .driftignore file:

					$ driftctl gen-driftignore -i drifts.json > .driftignore 

Take a look at the newly generated file, all the resources are now included with the proper format!

					$ head .driftignore
# Resources not covered by IaC


Finally, we can enjoy a driftctl scan with all the drifts ignored, while keeping a complete list of them in the .driftignore file, so we don’t forget about them.

					$ driftctl scan --from tfstate://**/*.tfstate
Scanned states (4) 
Scanned resources (62)      
Found 1 resource(s)
 - 100% coverage
Congrats! Your infrastructure is fully in sync.

Wait! I'm using Docker.

Here’s a quick primer on how to achieve all the above steps very quickly using the official Docker image.

The pre-requisites for this example are:

  • ~/.aws contains the AWS profiles, so we can share one named AWS_PROFILE
  • current directory contains a few Terraform states (available under /app inside the container)
  • ~/.driftctl to reuse the local provider cache

Confirm we can actually run a successful driftctl scan using Docker:

					$ docker run -it --rm \
  -v ~/.aws:/root/.aws:ro \
  -v $(pwd):/app \
  -v ~/.driftctl:/root/.driftctl \
  -e AWS_PROFILE=cloudskiff-demo \
  -e AWS_REGION=us-east-1 \
  cloudskiff/driftctl scan --from tfstate://**/*.tfstate 

Now we can easily generate the JSON file:

					$ docker run -it --rm \
  -v ~/.aws:/root/.aws:ro \
  -v $(pwd):/app \
  -v ~/.driftctl:/root/.driftctl \
  -e AWS_PROFILE=cloudskiff-demo \
  -e AWS_REGION=us-east-1 \
  cloudskiff/driftctl scan --from tfstate://**/*.tfstate --output json://drifts.json

Finally generate the .driftignore file from the JSON:

					$ docker run -it --rm \
  -v ~/.aws:/root/.aws:ro \
  -v $(pwd):/app \
  -v ~/.driftctl:/root/.driftctl \
  -e AWS_PROFILE=cloudskiff-demo \
  -e AWS_REGION=us-east-1 \
  cloudskiff/driftctl gen-driftignore -i drifts.json > .driftignore

We now have our .driftignore file fully generated in seconds, using driftctl and Docker!

Next Steps

Now we’re starting from a clean state, the next step could be to generate your own HTML reports and quickly spot any relevant information easy to read and to share.

Stay in touch

Get product updates and occasional news.