タダです.
業務の中で tfsec
を使う機会があり,tfsec
を使って,デフォルトのルールにない条件で解析を行うような仕組み化をやったのでこの記事でどういうことをやったのかをまとめていきます.
tfsec とは
tfsec
は Aqua Security 社が開発している Terraform の静的セキュリティチェックを行い,潜在的なセキュリティ脅威を分析するのに寄与するツールです.
tfsec uses static analysis of your terraform templates to spot potential security issues. Now with terraform CDK support.
tfsec の導入
tfsec
は brew で導入できます.その他の方法についてはこちらを参照ください.また,コンテナイメージも提供されています.
❯❯❯ brew install tfsec
tfsec
のオプションとして次のものがあります.基本的なコマンドは tfsec .
で実行できます.
❯❯❯ tfsec --help tfsec is a simple tool to detect potential security vulnerabilities in your terraformed infrastructure. Usage: tfsec [directory] [flags] Flags: --concise-output Reduce the amount of output and no statistics --config-file string Config file to use during run --custom-check-dir string Explicitly the custom checks dir location --debug Enable debug logging (same as verbose) -G, --disable-grouping Disable grouping of similar results -e, --exclude string Provide comma-separated list of rule IDs to exclude from run. --exclude-downloaded-modules Remove results for downloaded modules in .terraform folder --exclude-path strings Folder path to exclude, can be used multiple times and evaluated in order of specification --filter-results string Filter results to return specific checks only (supports comma-delimited input). --force-all-dirs Don't search for tf files, include everything below provided directory. -f, --format string Select output format: default, json, csv, checkstyle, junit, sarif. To use multiple formats, separate with a comma and specify a base output filename with --out. A file will be written for each type. The first format will additionally be written stdout. -h, --help help for tfsec --ignore-hcl-errors Stop and report an error if an HCL parse error is encountered --include-ignored Include ignored checks in the result output --include-passed Include passed checks in the result output --migrate-ignores Migrate ignore codes to the new ID structure --no-color Disable colored output (American style!) --no-colour Disable coloured output -O, --out string Set output file. This filename will have a format descriptor appended if multiple formats are specified with --format --run-statistics View statistics table of current findings. --single-thread Run checks using a single thread -s, --soft-fail Runs checks but suppresses error code --tfvars-file strings Path to .tfvars file, can be used multiple times and evaluated in order of specification --update Update to latest version --verbose Enable verbose logging (same as debug) -v, --version Show version information and exit -w, --workspace string Specify a workspace for ignore limits (default "default")
tfsec
で提供されているチェックのルールセットには次のものがあり,どのようなチェックを行っているかはこのページから確認できます.今回は AWS Checks
を使います.
- AWS Checks
- Azure Checks
- GCP Checks
- CloudStack Checks
- DigitalOcean Checks
- GitHub Checks
- Kubernetes Checks
- OpenStack Checks
- Oracle Checks
- General Checks
tfsec 実行
tfsec
導入後に,試しに AWS の Terraform コードのディレクトリで tfsec .
で実行してみると,tfsec
のルールセットから違反したコードの箇所が指摘されて出力されます.出力結果から組織的に無視していいものや要対応のものを整理していくことになると思います.無視するときは個別のコードの中で無視するものを設定します.
tfsec . Results #1-2 CRITICAL Security group rule allows egress to multiple public internet addresses. (2 similar results) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── hoge/xx.tf Line 41 ───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 37 │ egress { 38 │ from_port = 0 39 │ to_port = 0 40 │ protocol = "-1" 41 │ cidr_blocks = ["0.0.0.0/0"] 42 │ } ───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Individual Causes - /Users/tady/hoge/xx.tf:25-47 (xxx.xx) - /Users/tady/hoge/xx.tf:1-6 (xxx.xx) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ID aws-vpc-no-public-egress-sgr Impact Your port is egressing data to the internet Resolution Set a more restrictive cidr range More Information - https://aquasecurity.github.io/tfsec/v1.6.2/checks/aws/vpc/no-public-egress-sgr/ - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ~中略~ timings ────────────────────────────────────────── disk i/o 6.723876ms parsing 15.561457ms adaptation 2.028416ms checks 4.20521ms total 28.518959ms counts ────────────────────────────────────────── blocks 108 modules 5 files 46 results ────────────────────────────────────────── ignored 0 excluded 0 critical 6 high 15 medium 2 low 14 37 potential problem(s) detected.
カスタムルールを作って GitHub Actions でチェックする
組織的にルールセットにないけどチェックしたい定義があったらカスタムルールを作って解析します..tfsec
ディレクトリを作り,_tfchecks.yaml
か _tfchecks.json
を置いてくとチェックしてくれます.今回は,Terraform で管理されているリソースに必ず terraform
タグを付けるようにチェックするルールにしました.
--- checks: - code: CUS001 description: Check if the terraform tag set for all supported resources. errorMessage: The required terraform tag was missing matchSpec: action: contains name: tags value: terraform requiredTypes: - resource requiredLabels: - aws_* severity: ERROR
加えて GitHub Actions でプルリクエストが上がってきたときに編集したリソースが違反しているかチェックするよう reviewdog/action-tfsec で仕組み化してみます.
name: tfsec on: pull_request: jobs: tfsec: runs-on: ubuntu-latest steps: - name: checkout uses: actions/checkout@v3 - name: Run tfsec with reviewdog uses: reviewdog/action-tfsec@master with: github_token: ${{ secrets.github_token }} level: info working_directory: my_directory reporter: github-pr-review fail_on_error: true filter_mode: nofilter
関連情報
テスト実行
テスト実行をしたいので試しに セキュリティグループを追加するようなコードを書いてプルリクエストを出したとします.この状態だと terraform
タグがないのでチェックに上がってきます.これでプルリクエストの段階で組織的にチェックしたいルールを仕組み化していけそうです.
resource "aws_security_group" "ecr_vpcendpoint_sg" { name = "ecr-vpc-endpoint-sg" vpc_id = aws_vpc.tf_vpc.id ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [aws_vpc.tf_vpc.cidr_block] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "ecr-vpc-endpoint-sg" } }
プルリクエストでチェックされたときの例
まとめ
tfsec
のカスタムチェックで組織的にルール化したいことを定義してみました.こういったガバナンスを効かせて統一的なチェックを行うのは人力では難しいと思うので,こういった仕組み化をしていけると長期的に見て良さそうだと感じました.