Version: 0.7.0

Scan

$ driftctl scan [OPTIONS]
$ driftctl scan --from tfstate+s3://terraform.tfstate --to github+tf --output console://

Description#

Scan resources from the input Terraform statefile and compare it to your current profile infrastructure.

Options#

FlagEnvironmentDefault
--fromDCTL_FROMtfstate://terraform.tfstate
--outputDCTL_OUTPUTconsole://
--toDCTL_TOaws+tf
--quietDCTL_QUIETfalse

--from#

Currently, driftctl only supports reading IaC from a Terraform state. We are investigating to support the Terraform code as well, as a state does not represent an intention.

note

Multiple states can be read by passing --from flags

Example:

# I want to read a local state and a state stored in an S3 bucket:
$ driftctl scan \
--from tfstate+s3://statebucketdriftctl/terraform.tfstate \
--from tfstate://terraform_toto.tfstate
# You can also read all files under a given prefix for S3
$ driftctl scan --from tfstate+s3://statebucketdriftctl/states
# In a given local folder
# driftctl will recursively use all files under this folder.
#
# N.B. Symlinks under the root folder will be ignored.
# If the folder itself is a symlink it will be followed.
$ driftctl scan --from tfstate://my-states/directory
# We also support HTTP(s) URLs with authentication
# the tool will fetch the file from the given URL
#
# You can use the --headers option if you need to add extra headers to the request (e.g: for authentication purposes)
$ driftctl scan --from tfstate+https://example.com/terraform.tfstate --headers 'Authorization=Basic ...; X-Custom-Header=value'

Supported IaC sources#

  • Terraform state
  • Local: --from tfstate://terraform.tfstate
  • S3: --from tfstate+s3://my-bucket/path/to/state.tfstate
  • HTTPS: --from tfstate+https://my-url/state.tfstate

You can use any unsupported backend by using terraform to pipe your state in a file and then use this file with driftctl:

$ terraform state pull > state.tfstate
$ driftctl scan --from tfstate://state.tfstate

S3#

driftctl needs read-only access so you could use the policy below to ensure minimal access to your state file.

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::mybucket"
},
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/path/to/my/key"
}
]
}

--output#

driftctl supports multiple kinds of output formats and by default uses the standard output (console).

Console#

Environment: DCTL_OUTPUT

Usage#

$ driftctl scan
$ driftctl scan --output console://
$ DCTL_OUTPUT=console:// driftctl scan

Structure#

Found deleted resources:
aws_s3_bucket:
- driftctl-bucket-test-2
Found unmanaged resources:
aws_s3_bucket:
- driftctl-bucket-test-3
Found drifted resources:
- driftctl-bucket-test-1 (aws_s3_bucket):
~ Versioning.0.Enabled: false => true
Found 3 resource(s)
- 33% coverage
- 1 covered by IaC
- 1 not covered by IaC
- 1 deleted on cloud provider
- 1/1 drifted from IaC

JSON#

Usage#

$ driftctl scan --output json:///tmp/result.json # Will output results to /tmp/result.json
$ driftctl scan --output json://result.json # Will output results to ./result.json
$ driftctl scan --output json://stdout # Will output results in json to stdout directly
$ DCTL_OUTPUT=json://result.json driftctl scan

Structure#

{
summary: {
total_resources: 3,
total_drifted: 1,
total_unmanaged: 1,
total_deleted: 1,
total_managed: 1,
},
managed: [
// list of resources found in IaC and in sync with remote
{
id: "driftctl-bucket-test-1",
type: "aws_s3_bucket",
},
],
unmanaged: [
// list of resources found in remote but not in IaC
{
id: "driftctl-bucket-test-3",
type: "aws_s3_bucket",
},
],
deleted: [
// list of resources found in IaC but not on remote
{
id: "driftctl-bucket-test-2",
type: "aws_s3_bucket",
},
],
differences: [
// A list of changes on managed resources
{
res: {
id: "driftctl-bucket-test-1",
type: "aws_s3_bucket",
},
changelog: [
{
type: "update", // Kind of change, could be one of update, create, delete
path: [
// Path of the change, sorted from root to leaf
"Versioning",
"0",
"Enabled",
],
from: false, // Mixed type
to: true, // Mixed type
},
],
},
],
coverage: 33,
}

Computed Fields#

From Terraform documentation, a computed field is often used to represent values that are not user configurable or can not be known at time of terraform plan or apply.

Since those values are not known ahead of time from terraform point of view, it is obviously possible that the values displayed in a terraform state file are not up-to-date and may require a terraform refresh.

Thus, it could be possible that driftctl finds drifts that are considered false positives because of those outdated values.

We decided to output computed fields and to display a message at the end of the scan to remind you of this behavior.

Found drifted resources:
- eipalloc-0e2894d8ea42851df (aws_eip):
~ AssociationId: "" => "eipassoc-0ee67e1ca759733a2" (computed)
~ Instance: "" => "i-004611704837fd09a" (computed)
~ NetworkInterface: "" => "eni-0a62972b0471447f6" (computed)
~ PrivateDns: <nil> => "ip-172-31-40-4.eu-west-3.compute.internal" (computed)
~ PrivateIp: "" => "172.31.40.4" (computed)
Found 1 resource(s)
- 100% coverage
- 1 covered by IaC
- 0 not covered by IaC
- 0 deleted on cloud provider
- 1/1 drifted from IaC
You have diffs on computed fields, check the documentation for potential false positive drifts

--to#

driftctl supports multiple providers. By default it will scan against AWS, but you can change this using --to.

Usage#

Environment: DCTL_TO

$ driftctl scan --to PROVIDER+TYPE
# examples:
$ driftctl scan --to aws+tf
$ DCTL_TO=github+tf driftctl scan

Supported Providers#

driftctl supports these providers:

  • github+tf
  • aws+tf

--quiet#

This flag prevents stdout to be use for anything but the scan result.