KICSを使ってIaCコードの静的解析をしてみよう

# はじめに

みなさん、こんにちは。今回は KICS というオープンソースを利用した IaC コードの静的解析 (SAST、Static Application Security Testing) についてのお話です。

前回の記事で、オープンソースの静的解析ツールの Checkov の紹介をしたときに背景なども書いたので、本記事ではこまかい前置きは抜きにしてさっそく紹介をしていきたいと思います。

https://qiita.com/chacco38/private/f49843ed7552fcd20cd0

# KICSとは

KICS とは、[Checkmarx Ltd.] が開発する GO 言語ベースの静的解析ツールです。本ツールを活用することによって、Infrastructure as Code(IaC) コードの開発サイクルの早い段階で、セキュリティの脆弱性、コンプライアンスの問題、インフラストラクチャの構成ミスを検出することができるようになります。

対応ツールも豊富でTerraform、CloudFormation、AWS CDK や Kubernetes マニフェストに Helm チャート、Ansibleなど主要なツールにはおおよそ対応しており、GitLab CI/CD の IaC 用パイプラインテンプレートでも本ツールがテストステージに組み込まれていたりします。

なお、KICS という名前は **K**eeping **I**nfrastructure as **C**ode **S**ecure の略語となっているようです。

https://github.com/Checkmarx/kics

[Checkmarx Ltd.]: https://checkmarx.com/

# KICSを使ってみよう

今回はローカルに KICS を実行できる環境を作るところからはじめて、簡素な Terraform コードのサンプルを用いた静的解析の手動実行、静的解析を組み込んだシンプルなパイプラインの実装まで紹介していきたいと思います。

## まずは開発環境の構築から

今回は AWS CloudShell 上に開発環境を作っていきたいと思います。KICS のインストール方法としてはいろいろ用意されていますが AWS CloudShell では Docker が利用できないため、今回は Homebrew を使ってインストールしていきたいと思います。それでは、事前準備として Homebrew をインストールしてきます。

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
$ export PATH=/home/linuxbrew/.linuxbrew/bin:$PATH
$ brew --version
Homebrew 4.1.25
```

次に、[KICS公式ドキュメント]を参考に KICS をインストールします。なお、`gcc`パッケージが入っていないと`brew install` でエラーになったため先にインストールしています。

[KICS公式ドキュメント]: https://docs.kics.io/latest/documentation/#installation

```bash
$ sudo yum install -y gcc
$ brew install Checkmarx/tap/kics
$ kics version
Keeping Infrastructure as Code Secure 1.5.1
```

さらに、[Terraform公式ドキュメント] を参考に Terraform をインストールします。

[Terraform公式ドキュメント]: https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

```bash
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
$ sudo yum -y install terraform
$ terraform --version
Terraform v1.6.5
on linux_amd64
```

最後に、AWS CLI の設定をして開発環境の構築は完了です。

```bash
$ aws configure
```

## 手動でテストを実行してみよう

では簡単なサンプルを用いて  を使ったテストを行っていきましょう。

### Step1. テスト対象のIaCコード作成

今回は AWS上に簡単なネットワークリソースを作るだけのシンプルなコードを用意しました。

```tf:main.tf
terraform {
  required_version = "~> 1.6"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.29"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
  default_tags {
    tags = {
      Project     = "matt"
      Environment = "dev"
      Terraform   = "true"
    }
  }
}

locals {
  prefix = "matt-dev-"
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.2"

  name                   = "${local.prefix}vpc"
  cidr                   = "10.0.0.0/16"
  azs                    = ["ap-northeast-1c", "ap-northeast-1d"]
  public_subnets         = ["10.0.0.0/24", "10.0.4.0/24"]
  private_subnets        = ["10.0.128.0/24", "10.0.132.0/24"]
  enable_nat_gateway     = true
  single_nat_gateway     = true
  one_nat_gateway_per_az = false
}

resource "aws_security_group" "ssh" {
  name        = "${local.prefix}sg-ssh"
  description = "Allow SSH inbound traffic"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port        = 22
    to_port          = 22
    protocol         = "tcp"
    cidr_blocks      = ["0.0.0.0/0"]
  }

  egress {
    from_port        = 0
    to_port          = 0
    protocol         = "-1"
    cidr_blocks      = ["0.0.0.0/0"]
  }
}
```

### Step2. テストの手動実行

それでは手動で KICS を実行していきましょう。v1.5.1 だと最初に assets/queries ディレクトリを作成しておかないと `kics scan` コマンドがエラーになるためご留意ください。また、`-p` オプションでIaCコード格納パスの指定も必須なので、こちらも指定を忘れないようにしましょう。

```txt
$ mkdir -p assets/queries
$ kics scan -p .

                   .0MO.                                    
                   OMMMx                                    
                   ;NMX;                                    
                    ...           ...              ....     
WMMMd     cWMMM0.  KMMMO      ;xKWMMMMNOc.     ,xXMMMMMWXkc.
WMMMd   .0MMMN:    KMMMO    :XMMMMMMMMMMMWl   xMMMMMWMMMMMMl
WMMMd  lWMMMO.     KMMMO   xMMMMKc...'lXMk   ,MMMMx   .;dXx 
WMMMd.0MMMX;       KMMMO  cMMMMd        '    'MMMMNl'       
WMMMNWMMMMl        KMMMO  0MMMN               oMMMMMMMXkl.  
WMMMMMMMMMMo       KMMMO  0MMMX                .ckKWMMMMMM0.
WMMMMWokMMMMk      KMMMO  oMMMMc              .     .:OMMMM0
WMMMK.  dMMMM0.    KMMMO   KMMMMx'    ,kNc   :WOc.    .NMMMX
WMMMd    cWMMMX.   KMMMO    kMMMMMWXNMMMMMd .WMMMMWKO0NMMMMl
WMMMd     ,NMMMN,  KMMMO     'xNMMMMMMMNx,   .l0WMMMMMMMWk, 
xkkk:      ,kkkkx  okkkl        ;xKXKx;          ;dOKKkc    


Scanning with Keeping Infrastructure as Code Secure 1.5.1


Preparing Scan Assets: Done
Executing queries: [---------------------------------------------------] 100.00%

Files scanned: 417
Parsed files: 417
Queries loaded: 0
Queries failed to execute: 0

------------------------------------


Results Summary:
HIGH: 0
MEDIUM: 0
LOW: 0
INFO: 0
TOTAL: 0

Scan duration: 5m51.785647777s
A new version 'v1.7.11' of KICS is available, please consider updating
```

、、、本当は「セキュリティグループで不特定多数からの SSH を許可しないで！」と結果が返ってくることが期待だったのですがどうも機嫌がよくなかったようですね^^; 

次のパイプライン経由での実行がメインなので一旦ローカルでの実行はあきらめて次に行ってみましょう。以上、ローカル環境で KICS の静的解析を実行する方法のご紹介でした。

## CI/CDパイプラインに組み込んでみよう

次はもう一歩進んで、ソースコードの更新をトリガーに自動でテストを実行する CI/CD パイプラインを構築し、実際に動かすところまで行ってみたいと思います。今回の例では CI/CD パイプラインとして GitLab CI/CD を使っていきます。

### Step1. パイプライン定義の作成

まずは GitLab CI/CD パイプラインの定義ファイル `.gitlab-ci.yml` を作成していきましょう。今回の例では簡略化のためにテストステージだけを定義し、GitLab の画面からテスト結果を確認しやすいように JUnit 形式で出力しています。

```yaml:.gitlab-ci.yml
stages:
  - test

kics:
  stage: test
  allow_failure: true
  image:
    name: checkmarx/kics:latest
    entrypoint: [""]
  rules:
    - if: $SAST_DISABLED
      when: never
    - if: $CI_COMMIT_BRANCH
      exists:
        - '**/*.yml'
        - '**/*.yaml'
        - '**/*.json'
        - '**/*.template'
        - '**/*.tf'      
        - '**/serverless.yml'
        - '**/serverless.yaml'
  script:
    - kics scan --no-progress -p ${PWD} -o ${PWD} --report-formats junit --output-name kics-results
  artifacts:
    reports:
      junit: "junit-kics-results.xml"
    paths:
      - junit-kics-results.xml
```

### Step2. パイプラインの動作確認

先ほど作成したパイプライン定義 `.gitlab-ci.yml` をリモートリポジトリへ push すると自動的にパイプラインが実行されますので、GitLabの画面からテスト結果を確認してみましょう。

出力例のように Build > Pipelines > 対象パイプライン > Testタブ と遷移させることでテスト結果のサマリーを確認することができます。

![kics-summary.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613908/dd3cfdbd-5c6a-06c2-a3b5-55327b702242.jpeg)

また、テストのサマリー画面にてジョブ名(例ではkics)をクリックすることで、テスト結果の一覧を表示させることができます。

![kics-list.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613908/ec491125-abcc-f702-ff3c-c7bb4b5de2c8.jpeg)

また、この一覧画面で「View detauls」をクリックすることでより詳細な情報を得ることもできます。出力例では、セキュリティグループの定義に対する指摘で「SSH は公開するべきではないよ」と期待通りの指摘を得ることができました。

![kics-detail.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613908/8b29170f-e11a-b9c3-1643-7e7edaaccd46.jpeg)

ちなみに、本来はパイプラインにビルドステージやデプロイステージを持たせたりすると思いますが、ひとまずこれでソースコードのプッシュを契機にテストを走らせる、という最低限の流れを自動化することができました。

# 終わりに

ということで、KICS はいかがだったでしょうか？検出された問題の重大度が出力結果一覧からパッとわからない点は正直やや微妙かもしれませんが、とても簡単に静的解析を導入することができたかと思います。

IaC はしているけど静的解析は何もしてないよ、という方はデプロイ前に致命的なセキュリティ上の問題が含まれていることに気づくことができるように、ぜひ今回紹介する KICS のような静的解析ツールの活用を検討いただくといいのかなと思います。

以上、IaC コードの静的解析を実現する「KICS」のご紹介でした。

---

AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
Terraform は、HashiCorp, Inc. の米国およびその他の国における商標または登録商標です。
その他、記載されている会社名および商品・製品・サービス名は、各社の商標または登録商標です。