RSSAmplifier

Tarjei Husøy’s blag · Jun 4, 2021

Inline feedback from checkov on Github

0
Sign in to vote or save

2021-06-04 12:16 · thusoy.com

checkov is a pretty neat tool to verify that your Infrastructure-as-Code (IaC) repo doesn’t do or omit anything that unintentionally impacts your security posture. The best kind of feedback is early and localized feedback, thus better than having a failed test run is a message directly in the PR diff about where something went wrong. Luckily GitHub has decent support for letting Actions provide localized feedback by using the magic format ::error file=$file,line=$line,col=$col::$message (documented here), which we can fairly easily combine with checkov for a pretty good developer experience.

We can write a quick script to bridge these two, which can be run without any arguments to run checks against the entire repo, or by giving it a list of files to check:

import argparse
import json
import subprocess
import sys
SKIPPED_CHECKS = [
    # I don't like this check
    'CKV_AWS_40',
]
def main():
    args = get_args()
    result, output = get_checkov_output(args.files)
    print_github_errors(output)
    sys.exit(result)
def get_checkov_output(files):
    cmd = ['checkov']
    # If any input files are given, run on only those, otherwise run across everything
    if files:
        for file in files:
            cmd.extend(['--file', file])
    else:
        cmd.extend(['--directory', 'terraform/'])
    cmd.extend([
        '--quiet',
        '--framework', 'terraform',
        '--output', 'json',
        '--skip-check', ','.join(SKIPPED_CHECKS),
    ])
    proc = subprocess.run(cmd, stdout=subprocess.PIPE)
    return proc.returncode, json.loads(proc.stdout.decode('utf-8'))
def print_github_errors(checkov_output):
    for failure in checkov_output['results']['failed_checks']:
        details = ''
        if 'guideline' in failure:
            details = ' Details: %s' % failure['guideline']
        print('::error file=%s,line=%s,col=1::%s (%s).%s' % (
            failure['repo_file_path'][1:],
            failure['file_line_range'][0],
            failure['check_name'],
            failure['check_id'],
            details),
        )
def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('files', nargs='*')
    return parser.parse_args()
if __name__ == '__main__':
    main()

In a GitHub Action we can request to only run this only against changed files in a PR:

name: Checkov
on:
    pull_request:
        paths:
            - .github/workflows/checkov.yml
            - terraform/**
            - tools/terraform_security_check.py
jobs:
    terraform-security-check:
        runs-on: ubuntu-20.04
        steps:
            - uses: actions/checkout@v2
              with:
                  fetch-depth: ${{ github.event.pull_request.commits }}
            - name: Fetch base branch
              run: |
                git fetch --no-tags --prune --depth=1 origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}
            - name: Configure
              run: pip install checkov
            - name: Run checkov
              run: ./tools/terraform_security_check.py $(git diff --name-only "origin/${{ github.base_ref }}.." ./terraform/)

Which lets us get inline feedback like this if a file touched by a PR violates any of the security policies:

Read the original on thusoy.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.