Skip to content

Terraform Plan Quickstart

What is Terraform Plan?


From the official Terraform page:

The terraform plan command creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure.

  • Reads the current state of any already-existing remote objects to make sure that the Terraform state is up-to-date

From the StartLeft perspective, the Terraform Plan Processor (slp_tfplan) leverages the Terraform CLI capabilities to generate a unique Terraform resource file with the final infrastructure and its configuration.

The slp_tfplan module


The slp_tfplan module is the StartLeft Processor responsible for converting an existing Terraform execution plan (tf-plan) along with its graphic representation (tf-graph) into an OTM. This operation is based on a mapping file that enables the client to define the translations between the Terraform resources and the expected output in the OTM file.

How does it work?

We rely on the Terraform CLI to deal with the complexity of a Terraform infrastructure deployment, which is summarized in two single files:

  • Terraform Plan. It contains all the resources along with its configuration.
  • Terraform Graph. It contains the relationships between the resources.

With these two files, we are able to compose a complete architecture diagram by parsing all the components and their relationships.

Once you got familiarized yourself with the basics explained on this page, you will need to know more about how to use and customize the behavior of the processor. To configure your conversions, you should take a look at TFplan mapping page, where you will find all the information you need, from basic to advanced, to build your mapping files.

Apart from this, you may also find interesting the generic usage manuals for the CLI and REST API.

How to use it?


Firstly, it is necessary to generate the tf-plan and tf-graph files by the Terraform CLI.

Generating my own Terraform files

0⃣ Execute the Terraform init (only once):

terraform init

1⃣ Generate the Terraform plan file in JSON format:

terraform plan -out=tf-plan
terraform show -json tf-plan > tf-plan.json

2⃣ Generate the Terraform graph file:

terraform graph -type=plan -plan=tf-plan > tf-graph.gv

Next, you need to have a mapping file to configure the processor mapping behavior.

Terraform Plan Mapping File Example

In the TFplan mapping page you will find all the information you need, from basic to advanced, to build your mapping files.

trustzones:
  - type: b61d6911-338d-46a8-9f39-8dcd24abfe91
    name: Public Cloud
    risk:
      trust_rating: 10
    $default: true

  - type: f0ba7722-39b6-4c81-8290-a30a248bb8d9
    name: Internet
    risk:
      trust_rating: 1

components:

  - label: aws_acm_certificate
    type: CD-ACM
    $singleton: true

  - label: aws_cloudwatch_metric_alarm
    type: cloudwatch
    $singleton: true

  - label: aws_dynamodb_table
    type: dynamodb

  - label: aws_vpc
    type: vpc

  - label: aws_instance
    type: ec2

  - label: aws_subnet
    type: empty-component

  - label: aws_vpc_endpoint
    type: empty-component

  - label: aws_internet_gateway
    type: empty-component

  - label: aws_ecs_service
    type: elastic-container-service

  - label: aws_ecs_task_definition
    type: docker-container

  - label: ["aws_lb", "aws_elb", "aws_alb"]
    type: load-balancer

  - label: aws_kms_key
    type: kms
    $singleton: true

  - label: aws_lambda_function
    type: aws-lambda-function

  - label: aws_cloudwatch_log_group
    type: cloudwatch
    $singleton: true

  - label: ["aws_db_instance", "aws_rds_cluster"]
    type: rds

  - label: aws_route53_zone
    type: route-53

  - label: aws_autoscaling_group
    type: CD-EC2-AUTO-SCALING

  - label: cloudflare_record
    type: empty-component

  - label: [aws_s3_bucket, aws_s3_bucket_object]
    type: s3

  - label: aws_secretsmanager_secret
    type: CD-SECRETS-MANAGER
    $singleton: true

  - label: aws_sqs_queue
    type: sqs-simple-queue-service

  - label: {$regex: ^aws_ssm_\w*$}
    type: CD-SYSTEMS-MANAGER
    $singleton: true

  - label: aws_synthetics_canary
    type: empty-component

  - label: {$regex: ^aws_api_gateway_\w*$}
    type: api-gateway
    $singleton: true

  - label: {$regex: ^aws_athena_\w*$}
    type: athena
    $singleton: true

  - label: {$regex: ^aws_mq_\w*$}
    type: CD-MQ
    $singleton: true

  - label: {$regex: ^aws_cloudfront_\w*$}
    type: cf-cloudfront
    $singleton: true

  - label: aws_cloudtrail
    type: cloudtrail

  - label: ["aws_cognito_user_pool", "aws_cognito_identity_pool"]
    type: cognito

  - label: {$regex: ^aws_config_\w*$}
    type: CD-CONFIG
    $singleton: true

  - label: {$regex: ^aws_ecr_\w*$}
    type: elastic-container-registry
    $singleton: true

  - label: aws_eks_cluster
    type: elastic-container-kubernetes

  - label: {$regex: ^aws_elasticache_\w*$}
    type: elasticache
    $singleton: true

  - label: {$regex: ^aws_guardduty_\w*$}
    type: CD-GUARDDUTY
    $singleton: true

  - label: {$regex: ^aws_inspector_\w*$}
    type: CD-INSPECTOR
    $singleton: true

  - label: {$regex: ^aws_macie2_\w*$}
    type: CD-MACIE
    $singleton: true

  - label: aws_networkfirewall_firewall
    type: CD-AWS-NETWORK-FIREWALL

  - label: aws_redshift_cluster
    type: redshift

  - label: {$regex: ^aws_ses_\w*$}
    type: CD-SES
    $singleton: true

  - label: {$regex: ^aws_sns_\w*$}
    type: sns
    $singleton: true

  - label: {$regex: ^aws_sfn_\w*$}
    type: step-functions

  - label: {$regex: ^aws_waf(.*)_\w*$}
    type: CD-WAF
    $singleton: true

  - label: {$regex: ^aws_kinesis_analytics_\w*$}
    type: kinesis-data-analytics
    $singleton: true

  - label: {$regex: ^aws_kinesis_stream\w*$}
    type: kinesis-data-analytics
    $singleton: true

  - label: {$regex: ^aws_kinesis_firehose_\w*$}
    type: kinesis-data-firehose
    $singleton: true

  - label: {$regex: ^aws_iam_\w*$}
    type: CD-AWS-IAM
    $singleton: true

  - label: {$regex: ^aws_cloudwatch_event_\w*$}
    type: eventbridge
    $singleton: true

  - label: {$regex: ^aws_codebuild_\w*$}
    type: CD-CODEBUILD
    $singleton: true

  - label: {$regex: ^aws_codepipeline\w*$}
    type: CD-CODEPIPELINE
    $singleton: true

  - label: aws_ebs_volume
    type: elastic-block-store

  - label: {$regex: ^aws_shield_\w*$}
    type: CD-SHIELD
    $singleton: true

  - label: {$regex: ^aws_cloudformation_\w*$}
    type: CD-CLOUDFORMATION
    $singleton: true

  - label: aws_glue_job
    type: CD-GLUE

  - label: aws_glue_registry
    type: CD-GLUE-SCHEMA-REGISTRY

  - label: aws_efs_file_system
    type: elastic-file-system

  - label: aws_transfer_server
    type: CD-TRANSFER-FML

  - label: aws_codecommit_repository
    type: CD-CODECOMMIT

  - label: aws_globalaccelerator_accelerator
    type: CD-GLOBAL-ACC

  - label: {$regex: ^aws_dms_\w*$}
    type: CD-DMS
    $singleton: true

  - label: {$regex: ^aws_iot_\w*$}
    type: CD-IOT-CORE
    $singleton: true

  - label: {$regex: ^aws_medialive_\w*$}
    type: CD-MEDIALIVE
    $singleton: true

  - label: {$regex: ^aws_gamelift_\w*$}
    type: CD-GAMELIFT
    $singleton: true

  - label: {$regex: ^aws_directory_service_\w*$}
    type: CD-DIR-SERVICE
    $singleton: true

  - label: {$regex: ^aws_appsync_\w*$}
    type: CD-APPSYNC
    $singleton: true

  - label: {$regex: ^aws_fms_\w*$}
    type: firewall-manager
    $singleton: true

  - label: aws_neptune_cluster
    type: CD-NEPTUNE

  - label: aws_ec2_transit_gateway
    type: CD-AWS-TRANSIT-GW

  - label: {$regex: ^aws_batch_\w*$}
    type: CD-BATCH
    $singleton: true

  - label: aws_elastic_beanstalk_application
    type: CD-ELASTIC-BEANSTALK

  - label: {$regex: ^aws_dx_\w*$}
    type: direct-connect
    $singleton: true

  - label: aws_emr_cluster
    type: CD-EMR

  - label: aws_msk_cluster
    type: CD-MSK

  - label: aws_elastictranscoder_pipeline
    type: CD-ELASTIC-TRANSCODER

  - label: aws_sagemaker_app
    type: CD-SAGEMAKER

  # AZURE
  - label: [ "azurerm_data_share", "azurerm_data_share_account" ]
    type: CD-MICROSOFT-AZURE-DATA-SHARE

  - label: azurerm_elastic_cloud_elasticsearch
    type: CD-MICROSOFT-AZURE-ELASTICSEARCH

  - label: [ "azurerm_media_services_account", "azurerm_media_services_account_filter" ]
    type: CD-MICROSOFT-AZURE-MEDIA-SERVICES

configuration:
  attack_surface:
    client: generic-client
    trustzone: f0ba7722-39b6-4c81-8290-a30a248bb8d9

#  skip:
#    - aws_security_group
#    - aws_db_subnet_group
#  catch_all: empty-component

Now everything is set up. The last step is to execute the commands for IaC TFPLAN parsing to generate the OTM.

CLI

Note: Before continue, make sure you have StartLeft properly installed in your machine.

Save the files above in your file system with these names:

  • tf-plan.json for the Terraform plan file.
  • tf-graph.gv for the Terraform graph file.
  • ir-mappings.yaml for the mapping file.

Now we are going to execute StartLeft for these files so that an ec2.otm file will be generated in our working directory.

startleft parse \
    --iac-type TFPLAN \
    --default-mapping-file ir-mappings.yaml \
    --output-file output.otm \
    --project-id "my-project" \
    --project-name "My project" \
    tf-plan.json tf-graph.gv

cURL

You can get the same result through the StartLeft REST API. For that, first, we need to set up the server with the command:

startleft server

Then, execute the following command to retrieve the OTM file:

curl --location --request POST localhost:5000/api/v1/startleft/iac \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form iac_type="TFPLAN" \
--form iac_file=@"./tf-plan.json" \
--form iac_file=@"./tf-graph.gv" \
--form default_mapping_file=@"./ir-mappings.yaml" \
--form id="my-project" \
--form name="My project"

More examples


The infrastructure built with Terraform may be as complex as you want. For that reason StartLeft, through the mapping files, is intended to be configurable, so you can extend or modify its behavior and/or create your mappings on demand.

To help you to walk through more complex situations with larger Terraform and mapping files, you can see all available examples under the Terraform Examples section.