What-If Analysis For Terraform

Overview

The SecureCloud what-if analysis is a tool meant for devops administrators using IaC (infrastructure as code) deployment methods. It analyzes the security impact of your proposed changes before implementing them in your cloud infrastructure.

This is achieved by providing SecureCloud with a machine-readable plan of your intended infrastructure change using the SecureCloud asynchronous API and receiving as response a header containing the URL of the results.

Using a second API call, the analysis results can then be retrieved at the results URL received in the first API response. The response from the second API call contains the status of the analysis process and upon successful completion, the results can be reviewed.

The analysis can be run as a manual process or implemented as a “preflight hook” in your CI/CD pipeline, in which you can condition whether or not to apply the planned changes, based on the results of the analysis. You can invoke the SecureCloud “what-if” analysis API from a bash script and integrate it into any CI/CD tool that can execute bash scripts, using simple curl and jq tools.

What's Included in the Analysis?

The what-if analysis assesses the following types of risk:

Limitations

Only the following security controls are supported: AWS security groups, Azure network security groups and GCP firewalls. All other security controls such as Azure firewalls and storage security are ignored.

Prerequisites

  • Your cloud accounts must be monitored and synced in SecureCloud

  • You must have a SecureCloud access key with global admin permissions

  • You must modify your Terraform declarative configuration files so they add the “account_ids” data to the “outputs” of the “planned_values” section of the Terraform plan. SecureCloud requires this data to correlate the changed resources that are listed in the Terraform plan with the monitored account.

    For AWS

    data "aws_caller_identity" "playground" {  
        provider = aws.playground 
    } 
    
    data "aws_caller_identity" "playground2" { 
        provider = aws.playground2 
    } 
    output "account_ids" { 
        value = [{ 
            key = "playground" 
            value= data.aws_caller_identity.playground.account_id 
        }, 
        { 
            key = "playground2" 
            value= data.aws_caller_identity.playground2.account_id 
        }] 
    } 

    For Azure

    data "azurerm_client_config" "current" { 
    } 
    output "account_ids" { 
        value = [{ 
            key = "azurerm" 
            value= data.azurerm_client_config.current.subscription_id 
        }] 
    } 

    For GCP

    data "google_client_config" "playground" { 
        provider = google.playground 
    } 
    output "account_ids" { 
        value = [ 
            { 
                key = "playground" 
                value = data.google_client_config.playground.project 
            }] 
    } 
  • You must have a plan file that describes your Terraform plan in the format of version 0.2 i.e. "terraform02" and this must be converted to json format.

    1. Create your Terraform plan file (see also Terraform official documentation).

      terraform plan -out=<PLAN_FILE> 

      Where <PLAN_FILE> is a name of your choice for the output.

    2. Convert the plan file to json format.

      terraform show -json <PLAN_FILE> 

Running the Analysis

  1. Initiate the analysis. Invoke the first (asynchronous) API call.

    Format:

    curl -D <HEADER_FILE> --request POST 'https://<SECURECLOUD_ACCOUNT>.securecloud.tufin.io/api/v1/iris/model/cross-account/simulation' \
    --header "authorization: Bearer <SECURECLOUD_ACCESS_KEY>" \
    --header 'Format: terraform02' \
    --form 'plan=@"<PLAN_FILE>.json"'

    Where,

    • <HEADER.FILE> is a name of your choice for the header that will be received from the API call,

    • <SECURECLOUD_ACCOUNT> is the name of your SecureCloud account as seen in the URL window of your browser when logged in to SecureCloud e.g. myorg in https://myorg.securecloud.tufin.io,
    • <SECURECLOUD_ACCESS_KEY> is your SecureCloud access key described in Prerequisites
    • <PLAN_FILE>.json is your json plan output file described in Terraform Prerequisites,

    Example API Call:

    curl -D header.txt --request POST 'https://myorganization.securecloud.tufin.io/api/v1/iris/model/cross-account/simulation' \
    --header "authorization: Bearer 5493a1ff-b35c-43c5-8d3e-2f5d3c9547e4" \
    --header 'Format: terraform02' \
    --form 'plan=@"my_plan.json"'

Continue with Analyzing the Results.

Analyzing the Results

  1. Example Header Returned:

    HTTP/2 202
    x-dns-prefetch-control: off 
    x-frame-options: SAMEORIGIN 
    strict-transport-security: max-age=15552000; includeSubDomains 
    x-download-options: noopen 
    x-content-type-options: nosniff 
    x-xss-protection: 1; mode=block 
    access-control-expose-headers: location 
    content-length: 0 
    date: Thu, 13 Jan 2022 15:36:11 GMT 
    location: https://myorganization.securecloud.tufin.io/api/v1/iris/model/cross-account/simulation/5493a1ff-b35c-43c5-8d3e-2f5d3c9547e4 
    server: undefined 
    vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Origin,Access-Control-Request-Method,Access-Control-Request-Headers 
    x-envoy-upstream-service-time: 72 
    x-goproxy: GoProxy, GoProxy 
    permissions-policy: camera=();microphone=();geolocation=();encrypted-media=();payment=();speaker=();usb=(); 
    via: 1.1 google 
    alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 
    		

    Take note of the line starting with location i.e.

    location: https://myorganization.securecloud.tufin.io/api/v1/iris/model/cross-account/simulation/5493a1ff-b35c-43c5-8d3e-2f5d3c9547e4 

    This location value is required for the next step.

  2. Retrieve the what-if results from SecureCloud. Invoke the second API.

    curl <RESULT_URL> -H "Authorization: bearer <SECURECLOUD_ACCESS_KEY>" 

    Where,

    • <RESULT_URL> is the location value from the previous step (i.e. starting with "https:" and ending with "2f5d3c9547e4" in the example above),
    • <SECURECLOUD_ACCESS_KEY> is your SecureCloud access key described in Prerequisites.

    Example API Call:

    curl "https://myorganization.securecloud.tufin.io/api/v1/iris/model/cross-account/simulation/5493a1ff-b35c-43c5-8d3e-2f5d3c9547e4" -H "Authorization: bearer <SECURECLOUD_ACCESS_KEY>" 

    The result will initially contain the text similar to that below. "status" will be "IN_PROGRESS", indicating that the process is still running, "result" will contain some or no data and "error" will be null.

    {  
    "status":"IN_PROGRESS", 
    "result":{ 					
     	}, 
    "error":null 
    } 

    If the process completes successfully, "status" will be modified to "SUCCESS", "error" will be null and "result" will contain the results of the what-if analysis, which you can now parse and analyze.

    If an error occurs, “status” will be modified to “FAIL”, “result” will be null, and “error” will contain the analysis error information. If the cause of error is unclear, contact Tufin support for assistance.

    The status will remain "IN_PROGRESS" until the process completes successfully or fails. The length of time to completion cannot be estimated.

  3. Invoke the second API as described in the previous step, as many times as needed, until the status is no longer "IN_PROGRESS".

Once the value of "status" is "SUCCESS" in the result returned from Running the What-If Analysis, the results can be viewed and assessed.

Structure of the Results

The structure below shows two assets, each with two violations, as an example. The actual number of assets and violations will vary according to your data. This feature is still in beta phase and the structure is liable to change.

{  
  "status":"SUCCESS", 
  "result":{ 
    "asset_violation_diffs":[ 
      { 
        "id":(Asset 1 internal ID)
        "name": (Asset 1 name as shown in SecureCloud)
        "account":{ 
          "id":(Internal ID of asset 1's account), 
          "name":(Name of asset 1's account as shown in SecureCloud), 
          "vendor":(Vendor of asset 1's account as shown in SecureCloud) 
        }, 
        "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
        "security_access_violation_diffs":[ 
          { 
            "id":(Internal), 
            "name":null, 
            "violation_diffs":[ 
              { (Violation 1)
                "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
                "before":(Details),
		 "type: (CLOUD_POLICY, PERMISSIVE_ACCESSES, RISKY_PORTS),
                "after":(Details)
    		}, 
              { (Violation 2)
                "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
                "before":(Details),
     		 "type: (CLOUD_POLICY, PERMISSIVE_ACCESSES, RISKY_PORTS),
                "after":(Details)
	       }, 
            ] 
          } 
        ] 
      }, 
      { 
      } 
      { 
        "id":(Asset 2 internal ID)
        "name": (Asset 2 name as shown in SecureCloud)
        "account":{ 
          "id":(Internal ID of asset 2's account), 
          "name":(Name of asset 2's account as shown in SecureCloud), 
          "vendor":(Vendor of asset 2's account as shown in SecureCloud) 
        }, 
        "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
        "security_access_violation_diffs":[ 
          { 
            "id":(Internal), 
            "name":null, 
            "violation_diffs":[ 
              { (Violation 3)
                "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
                "before":(Details),
		 "type: (CLOUD_POLICY, PERMISSIVE_ACCESSES, RISKY_PORTS),
                "after":(Details)
    		}, 
              { (Violation 4)
                "state":(NEW, FIXED, ESCALATION, IMPROVEMENT, CHANGE), 
                "before":(Details),
     		 "type: (CLOUD_POLICY, PERMISSIVE_ACCESSES, RISKY_PORTS),
                "after":(Details)
	       }, 
            ] 
          } 
        ] 
      }, 
      { 
      } 
    ] 
  }, 
  "error":null 
} 

The results contain a list of assets whose risk level from violations will be changed if the new infrastructure plan is implemented, and in addition, the specific violations whose risk level will be changed are listed for each asset.

Assets and violations that remain at the same risk level, are excluded from the results.

The "state" field is included for each asset and for each violation included in the results:

  • NEW: An asset that has no violations in the monitored cloud account will have violations if the plan is implemented.

  • FIXED: An asset that has violations in the monitored cloud account will have no violations if the plan is implemented.

  • ESCALATION: An asset that has violations in the monitored cloud account will have more violations or more severe violations if the plan is implemented.

  • IMPROVEMENT: An asset that has violations in the monitored cloud account will have fewer violations or less severe violations if the plan is implemented.

  • CHANGE: An asset that has violations in the monitored cloud account will have different violations if the plan is implemented i.e. there will be some combination of the other states listed above.

The action you decide to take, based on the "state" field is your own choice, however, we recommend a best practice of refraining from deploying your plan if any "state" field has a value of NEW, ESCALATION or CHANGE.

Example Result Returned:

This feature is still in beta phase and the structure is liable to change.

{  
  "status":"SUCCESS", 
  "result":{ 
    "asset_violation_diffs":[ 
      { 
        "id":"77e38d96-3c9a-3e51-b566-30e2a89453e8", 
        "name":"test-db", 
        "account":{ 
          "id":"4e794fa5-1f78-40b5-b7cc-79d7127e7e1f", 
          "name":"dev-irisw", 
          "vendor":"AWS" 
        }, 
        "state":"IMPROVEMENT", 
        "security_access_violation_diffs":[ 
          { 
            "id":"2d8c4a6e-02a3-300f-b4c0-61931df5f090", 
            "name":null, 
            "violation_diffs":[ 
              { 
                "state":"FIXED", 
                "before":{ 
                  "type":"CLOUD_POLICY", 
                  "services":[ 
                    { 
                      "type":"TRANSPORT", 
                      "protocol":"TCP", 
                      "min_port":23, 
                      "max_port":23, 
                      "name":"Telnet" 
                    } 
                  ], 
                  "endpoints":[ 
                    { 
                      "type":"IP", 
                      "ip":"10.100.0.0/16" 
                    }, 
                    { 
                      "type":"RESOURCE", 
                      "reference":{ 
                        "id":"2e5e3e24-b131-376c-a5e0-d26c89f5a56d", 
                        "name":"DHCP-Vpc", 
                        "type":"VPC", 
                        "account_id":"4e794fa5-1f78-40b5-b7cc-79d7127e7e1f" 
                      } 
                    }, 
                    { 
                      "type":"INTERNET" 
                    } 
                  ] 
                }, 
                "after":null 
              }, 
              { 
                "state":"FIXED", 
                "before":{ 
                  "type":"PERMISSIVE_ACCESSES", 
                  "sources":[ 
                    { 
                      "type":"ANY" 
                    } 
                  ], 
                  "services":[] 
                }, 
                "after":null 
              } 
            ] 
          } 
        ] 
      }, 
      { 
      } 
    ] 
  }, 
  "error":null 
}