Snyk でインフラの脆弱性をチェックしてみる

# やりたいこと
[Snykを使ってコードをセキュアにした記事を投稿しよう！ by Snyk Advent Calendar 2023](https://qiita.com/advent-calendar/2023/snyk) についての記事です。

Snyk を使って IaC 化したインフラの脆弱性をチェックしてみます。

:::note warn
過去に投稿した[記事](https://qiita.com/coitate/items/310c848018185b85bf3b)を Advent Calendar 用に再編したものになります。
やや Terraform Cloud 寄りの内容かもしれませんがご容赦を…:pray:
:::

# 環境
* Windows11 Pro
    * WSL2 (Ubuntu22.04)
* Terraform
    * version 1.5.5

# Terraform
まずは Terraform Cloud 側の設定を行っていく。

## Terraform Cloud アカウント作成
以下のページからアカウントを作成する。

https://app.terraform.io/public/signup/account

## ログイン用のトークンを取得する
Terminal で `terraform login` を実行する。`Do you want to proceed?` と表示され、確認を求められるので `yes` と入力して継続する。

Terminal 上に URL (https://app.terraform.io/app/settings/tokens?source=terraform-login) が表示されるので、ブラウザでアクセスする。
(TFCB のホーム画面から、ユーザアイコンをクリックして、User Settings → Token でもアクセス可)

「Generating a user token」というウィンドウが表示されるので、Description と Expiration を設定して「Generate token」をクリックすると、トークンが表示されるので控える (後から確認はできないので注意)。

Terminal に戻り、`Token for app.terraform.io:` と入力を求められている部分に入力するとログインが成功するはず！

## Workspace, Project 作成
HCL から作成する。

Terminal でどこか適当なところに `tfcb-test` というディレクトリを作成して、`provider.tf` というファイルを以下内容で作成する。Organization 名はデフォルトだとユーザ名になっているので、それを指定する。

``` provider.tf
terraform {
  cloud {
    organization = "{YOUR_ORGANIZATION_NAME}"

    workspaces {
      name = "{YOUR_WORKSPACE_NAME}"
    }
  }
}
```

`terraform init` を実行すると、指定した Workspace 名で Workspace が作成される。

これでひとまず Terraform Cloud の初期設定が完了！

## いったん適当なリソースをプロビジョニングしてみる
`provider.tf` を作成したディレクトリと同じところに、`main.tf` というファイルを以下内容で作成する。
(今回は Azure のリソースを Terraform で作成していきます)

``` main.tf
# リソースグループの作成
resource "azurerm_resource_group" "example" {
  name     = "example"
  location = "West Europe"
}
```
参考: https://registry.terraform.io/providers/hashicorp/azurerm/3.50.0/docs/resources/resource_group

Azure のリソースを作成するために `provider.tf` を以下のように変更する。

``` provider.tf
terraform {
  cloud {
    organization = "{YOUR_ORGANIZATION_NAME}"

    workspaces {
      name = "{YOUR_WORKSPACE_NAME}"
    }
  }

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "3.50.0"
    }
  }
}

provider "azurerm" {
  features {}
}
```

変更したら、Terminal で `terraform apply` してみる。特に問題なくリソースの作成が完了するはず。
その後、Terraform Cloud の、Project & Workspace → {YOUR_WORKSPACE_NAME} → Stetes で作成された tfstate ファイルを確認することができる。

もしリソースの作成に失敗した場合は、Azure AD の自身のアカウントにリソースグループ作成の権限があるか確認！

## Terraform Cloud 用サービスプリンシパルの作成
ひとまずリソースの作成はできたものの、個人の AAD アカウントを使っているので CI/CD などを考慮するとよろしくない。ということで TFCB 用のサービスプリンシパルを作成してそれを使うように設定する。

サービスプリンシパルは Azure Portal から作成する。
Azure Active Directory → App registrations から New registration をクリックして、指示に従い作成する。
今回はリソースグループを Terraform で作成するので、対象のサブスクリプションへの Contributor 権限を付与しておく。作成後、Credential が発行されるので控える (後から確認できないので注意)。

TFCB の、Project & Workspace → {YOUR_WORKSPACE_NAME} → Variables で認証情報を環境変数として登録する。一度自身のユーザアカウントで認証されていた状態なので、各 Key の Value をサービスプリンシパルのものに変更する。

![スクリーンショット 2023-06-30 142515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1743460/ad3a4b1b-f121-8505-323a-29726a83e95b.png)


設定を保存後、`main.tf` の内容を以下に変更して、再度 Terminal から `terraform apply` してみる。

``` main.tf
# リソースグループの作成
resource "azurerm_resource_group" "example" {
  name     = "tfcbtest"
  location = "West Europe"
}
```

リソースグループの名前が、example -> tfcbtest に変更されれば OK！

# Snyk
ここから Synk 側の設定。

## セキュリティ系機能を使ってみる
以上は Terraform Cloud の基本的な使い方。ここからは Free プランでも使えるようになったセキュリティ系の機能を使ってみる。

今回は、脆弱性を見つけてくれるプラットフォームである Snyk を使ってみる。

https://go.snyk.io/jp.html

## Snyk アカウントの作成
以下のページから作成する。

https://app.snyk.io/login

## Terraform Cloud との統合
以下のページを参考に、[Workspaceへの関連付け](https://dev.classmethod.jp/articles/snyk-saas-integration-terraform-cloud-overwiew/#toc-5) まで設定する。

https://dev.classmethod.jp/articles/snyk-saas-integration-terraform-cloud-overwiew/

設定後、わざと Synk に指摘されるようなリソースを作成する。`main.tf` を以下のように変更する。

``` main.tf
# リソースグループの作成
resource "azurerm_resource_group" "example" {
  name     = "tfcbtest"
  location = "West Europe"
}

# ストレージアカウントの作成
resource "azurerm_storage_account" "example" {
  name                     = "example"
  resource_group_name      = resource.azurerm_resource_group.example.name
  location                 = resource.azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}
```

変更後、Terminal から `terraform apply` を実行してみる。Terminal 上で以下のような Snyk の警告メッセージが表示されるはず (`****` は伏せ字)。`Details` の URL にアクセスするとどういう脆弱性があるのか確認できる。

```
│ Snyk ⸺   Failed (Advisory)
│ Found:
1 medium severity issue(s).
1 low severity issue(s).
Severity threshold is set to low.
│ Details: https://app.snyk.io/org/****/project/3ce66379-0f2e-48ba-adef-3ddd054efad8/history/e9a7f517-0524-44dc-9c36-d14c0066082b
```

`main.tf` で追加したストレージアカウントのリソースでは、レプリケーションの設定が LRS なのと、信頼する Azure サービスからのアクセスを無効にしていることが指摘されているはず！

その他の脆弱性も検出してくれるので、インフラ構築時のそういったミスが実際に適用する前にわかる！

# ということで
Snyk と Terraform Cloud を使って、インフラの脆弱性検知の仕組みを構築しました。Terraform Cloud の内容も多めでしたが、組み合わせることで `terraform apply` 時に自動的にインフラの脆弱性をチェックしてくれる仕組みを構築することができます。この仕組みを GitHub などからキックすることもできるので、開発体験も向上するのではと思います。
本当は、インフラではなく何らかアプリのコードを書いて Synk で脆弱性チェックした記事を書く予定でしたが、その時間が取れなかったので過去の記事の再編ということでお茶を濁しました…笑
そのあたりについては、また改めて記事にしたいと思っています！


以上です。