Lacework
Access helpful articles and other FAQs on Lacework
Kate_M
Community Manager
Community Manager
Article Id 334676
Description

Lacework scanner can be integrated inside deployment Workflows. The following is an example of using Lacework Scanner with Github Actions and Terraform. To achieve that, we will create a basic three-job Workflow that will test tools, run the IaC scan, and finally deploy the infrastructure using Terraform.

Scope Lacework / Github
Solution

Setting the Workflow

The first step is to decide what events will trigger this workflow. In this case, we want to trigger this workflow when a push is committed to the main branch (whether direct push or as a result of a merge). In addition we need to give this Workflow the proper permissions:

 

name: lacework-iac-scan-push-main

on:

 push:

   branches:

     - 'main'

 workflow_dispatch:

permissions:

     id-token: write

     contents: read

     security-events: write

     actions: read

 

Job 1: Testing the tools

This serves as a straightforward test to verify the presence of necessary tools (like AWS, Terraform, etc.) within the container image we've selected, such as 'ubuntu-latest'
 

Initialize:

   runs-on: ubuntu-latest

   steps:

     - name: Test Tools

       run: |

         aws --version

         terraform --version

 

Job 2: Running the scanner

This is the Job that we are most interested in. We will use ubuntu-latest and we will Checkout the source code. Which is in this case Terraform HCL files.
 

Lacework-Scanner:

   needs: Initialize

   runs-on: ubuntu-latest

   steps:

     - name: Checkout Code

       uses: actions/checkout@v3

 

The next step is to run the actual scanner. We will need to configure our environment with Lacework keys and we also need to set those as repository secrets in Github repo. Please refer to this link for details on how to generate those keys and set them as secret values: https://docs.lacework.net/iac/restricted/github-actions

Once you have the keys, we will need to set then as ENV variables inside the Workflow

 

 - name: Lacework IaC Scan

       id: laceworkscan

       env:

         LW_ACCOUNT: ${{ secrets.LW_ACCOUNT }}

         LW_API_KEY: ${{ secrets.API_KEY }}

         LW_API_SECRET: ${{ secrets.API_SECRET_TOKEN }}

 

Next, we will need to use those secrets as well as additional configuration to execute the scanner. I have added notes that explain what each line does.

 

run: |            # Setup            IAC_REPORTS_DIR="/tmp/iac_reports"            env | grep "GITHUB_\|LW_\|CI_" > env.list    # Set Lacework and other secrets            echo "SCAN_COMMAND=tf-scan" >> env.list      # Configure the scanner to run Terraform Scan            echo "WORKSPACE=src" >> env.list                        echo "EXIT_FLAG=critical" >> env.list      # Cause the pipline to fail if any Critical violations are discovered            echo "JUNIT_OUTPUT_FILE=/tmp/lacework-report.junit.xml"  >> env.list            echo "JSON_OUTPUT_FILE=/tmp/lacework-report.json"  >> env.list                       # Run the Scan            docker run --env-file env.list -v "$(pwd):/app/src" lacework/codesec-iac:latest                       # Copy the report outside lacework/codesec-iac:latest container            CONTAINER_ID=$(docker ps -a |grep lacework |head -n1 |cut -d ' ' -f1) # Extracts the latest container ID (Inside a Workflow there should be only one anyways)            mkdir $IAC_REPORTS_DIR            docker container cp "$CONTAINER_ID:/tmp/lacework-report.json" $IAC_REPORTS_DIR            docker container cp "$CONTAINER_ID:/tmp/lacework-report.junit.xml" $IAC_REPORTS_DIR            # Set GITHUB_ENV            RESULTS_JSON="$IAC_REPORTS_DIR/lacework-report.json"            echo "RESULTS_JSON=$RESULTS_JSON" >> "$GITHUB_ENV"

 

Once the scan is done, Lacework Scanner will upload the results to your Lacework console. But the above configuration will also produce two types of report files, JUNIT and JSON. This is a common way for engineers to find these results without having to go to the Lacework Console. These reports can also be published inside the Workflow or using third party tools

To Upload/Store the results:

 

 - name: 'Upload Artifacts'

       uses: actions/upload-artifact@v3

       with:

         name: Lacework Junit Report

         path: /tmp/iac_reports/*

 

There are many Github Actions that can help us to publish report results. However, in this example, we have created our own from scratch:
     

- name: Publish IaC Scan Results

       run: |

           # Create results summary

           TESTS=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass'| wc -l)

           echo "TESTS: $TESTS"

           TESTS_PASSED=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass' | grep true | wc -l)

           echo "TESTS_PASSED: $TESTS_PASSED"

           TESTS_FAILED=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass' | grep false| wc -l)

           echo "TESTS_FAILED: $TESTS_FAILED"



           # Set GITHUB_ENV

           echo "TESTS=$TESTS" >> "$GITHUB_ENV"

           echo "TESTS_PASSED=$TESTS_PASSED" >> "$GITHUB_ENV"

           echo "TESTS_FAILED=$TESTS_FAILED" >> "$GITHUB_ENV"



           # Adding a Step Summary to the workflow using $GITHUB_STEP_SUMMARY

           echo "<table><tr><th><th>Tests</th><th>Passed ✅</th><th>Failed ❌</th></tr><tr><td>Lacework TF-SCAN JUnit Results</td><td>${TESTS} Ran</td><td>${TESTS_PASSED} Passed</td><td>${TESTS_FAILED} Failed</td></tr></table>" >> $GITHUB_STEP_SUMMARY

 

In the example above, we are creating a summary of the report based on the JSON output,TEST, TEST_PASSED, and TESTS_FAILED are the three values that we need to extract and present as a summary. 

The actual summary is designed and built by writing to the $GITHUB_STEPS_SUMMARY variable. 

 

The step summary would look like this:

 

Kate_M_0-1724144665820.png

 

 

Job 3:  Terraform Deployment

In the final job, we will run Terraform Plan and Apply to deploy our infrastructure. Notice that we are using OpenID Connect in Amazon Web Services to have the Workflow to assume a role into our target AWS account. More on this in the references below.

 

Terraform-Deploy:

   runs-on: ubuntu-latest

   needs: Lacework-Scanner

   steps:

     - name: Checkout Code

       uses: actions/checkout@v3

     - name: configure aws credentials

       uses: aws-actions/configure-aws-credentials@v4

       with:

         role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT}}:role/github-actions

         role-session-name: GitHub_to_AWS_via_FederatedOIDC

         aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

     - name: Sts GetCallerIdentity

       run: |

           aws sts get-caller-identity

     - name: Terraform Plan

       run: |

             terraform init

             terraform plan -out tf.plan

     - name: Terraform Apply

       run: |

         terraform apply --auto-approve tf.plan

 

Finally, putting the entire Workflow together, it should look something like this:

name: lacework-iac-scan-push-main

on:

 push:

   branches:

     - 'main'

 workflow_dispatch:

permissions:

     id-token: write

     contents: read

     security-events: write

     actions: read

jobs:

 Initialize:

   runs-on: ubuntu-latest

   steps:

     - name: Test Tools

       run: |

         aws --version

         terraform --version

 Lacework-Scanner:

   needs: Initialize

   runs-on: ubuntu-latest

   steps:

     - name: Checkout Code

       uses: actions/checkout@v3

     - name: Lacework IaC Scan

       id: laceworkscan

       env:

         LW_ACCOUNT: ${{ secrets.LW_ACCOUNT }}

         LW_API_KEY: ${{ secrets.API_KEY }}

         LW_API_SECRET: ${{ secrets.API_SECRET_TOKEN }}

       run: |

            # Setup

            IAC_REPORTS_DIR="/tmp/iac_reports"

            env | grep "GITHUB_\|LW_\|CI_" > env.list    # Set Lacework and other secrets

            echo "SCAN_COMMAND=tf-scan" >> env.list      # Configure the scanner to run Terraform Scan

            echo "WORKSPACE=src" >> env.list            

            echo "EXIT_FLAG=critical" >> env.list      # Cause the pipline to fail if any Critical violations are discovered

            echo "JUNIT_OUTPUT_FILE=/tmp/lacework-report.junit.xml"  >> env.list

            echo "JSON_OUTPUT_FILE=/tmp/lacework-report.json"  >> env.list

           

            # Run the Scan

            docker run --env-file env.list -v "$(pwd):/app/src" lacework/codesec-iac:latest

           

            # Copy the report outside lacework/codesec-iac:latest container

            CONTAINER_ID=$(docker ps -a |grep lacework |head -n1 |cut -d ' ' -f1) # Extracts the latest container ID (Inside a Workflow there should be only one anyways)

            mkdir $IAC_REPORTS_DIR

            docker container cp "$CONTAINER_ID:/tmp/lacework-report.json" $IAC_REPORTS_DIR

            docker container cp "$CONTAINER_ID:/tmp/lacework-report.junit.xml" $IAC_REPORTS_DIR



            # Set GITHUB_ENV

            RESULTS_JSON="$IAC_REPORTS_DIR/lacework-report.json"

            echo "RESULTS_JSON=$RESULTS_JSON" >> "$GITHUB_ENV"

      

     - name: 'Upload Artifacts'

       uses: actions/upload-artifact@v3

       with:

         name: Lacework Junit Report

         path: /tmp/iac_reports/*

     - name: Publish IaC Scan Results

       run: |

           # Create results summary

           TESTS=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass'| wc -l)

           echo "TESTS: $TESTS"

           TESTS_PASSED=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass' | grep true | wc -l)

           echo "TESTS_PASSED: $TESTS_PASSED"

           TESTS_FAILED=$(cat $RESULTS_JSON |jq -r '.[].findings | .[].pass' | grep false| wc -l)

           echo "TESTS_FAILED: $TESTS_FAILED"



           # Set GITHUB_ENV

           echo "TESTS=$TESTS" >> "$GITHUB_ENV"

           echo "TESTS_PASSED=$TESTS_PASSED" >> "$GITHUB_ENV"

           echo "TESTS_FAILED=$TESTS_FAILED" >> "$GITHUB_ENV"



           # Adding a Step Summary to the workflow using $GITHUB_STEP_SUMMARY

           echo "<table><tr><th><th>Tests</th><th>Passed ✅</th><th>Failed ❌</th></tr><tr><td>Lacework TF-SCAN JUnit Results</td><td>${TESTS} Ran</td><td>${TESTS_PASSED} Passed</td><td>${TESTS_FAILED} Failed</td></tr></table>" >> $GITHUB_STEP_SUMMARY

 Terraform-Deploy:

   runs-on: ubuntu-latest

   needs: Lacework-Scanner

   steps:

     - name: Checkout Code

       uses: actions/checkout@v3

     - name: configure aws credentials

       uses: aws-actions/configure-aws-credentials@v4

       with:

         role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT}}:role/github-actions

         role-session-name: GitHub_to_AWS_via_FederatedOIDC

         aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

     - name: Sts GetCallerIdentity

       run: |

           aws sts get-caller-identity

     - name: Terraform Plan

       run: |

             terraform init

             terraform plan -out tf.plan

     - name: Terraform Apply

       run: |

         terraform apply --auto-approve tf.plan

 

Once the Workflow completes successfully, it should look something like this:

 

Kate_M_1-1724144665923.png

 

References:

Contributors