コンテナイメージをPushしたときに脆弱性スキャンを行うECRをTerraformで構築する


インフラエンジニアの寺岡です。
今回はAWSのECRにおいてコンテナイメージをPushしたときに脆弱性スキャンを行う設定を追加してみます。
せっかくなのでTerraformを使って構築してみたいと思います。

ECRとはAWSのマネージドコンテナイメージレジストリです。
Pushしたコンテナイメージを保管してくれますが
そのイメージ自体の脆弱性についてはユーザー側で気を配らなければなりません。

ECRの1機能としてPushしたときに自動で脆弱性スキャンを実行する設定があるため
この設定を有効にしたリポジトリを構築したいと思います。

ECRのリポジトリを作成する

aws_ecr_repositoryというリソースを利用します。

####################
# Provider
####################
variable "aws_access_key" {
  description = "AWS Access Key"
}

variable "aws_secret_key" {
  description = "AWS Secret Key"
}

variable "aws_role_arn" {
  description = "AWS Role Arn"
}

variable "aws_region" {
  default = "ap-northeast-1"
}

provider "aws" {
  access_key = "${var.aws_access_key}"
  secret_key = "${var.aws_secret_key}"
  region     = "${var.aws_region}"

  assume_role {
    role_arn = "${var.aws_role_arn}"
  }
}

####################
# ECR
####################
resource "aws_ecr_repository" "image-scan-test" {
  name                 = "image-scan-test"
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}

image_scanning_configurationブロックのscan_on_pushをtrueにしておきます。
ではinitからやっていきましょう。

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "aws" (hashicorp/aws) 2.56.0...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 2.56"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

念のため反映前にPlanを実行します。

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


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

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_ecr_repository.image-scan-test will be created
  + resource "aws_ecr_repository" "image-scan-test" {
      + arn                  = (known after apply)
      + id                   = (known after apply)
      + image_tag_mutability = "MUTABLE"
      + name                 = "image-scan-test"
      + registry_id          = (known after apply)
      + repository_url       = (known after apply)

      + image_scanning_configuration {
          + scan_on_push = true
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

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

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Applyで反映します。

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_ecr_repository.image-scan-test will be created
  + resource "aws_ecr_repository" "image-scan-test" {
      + arn                  = (known after apply)
      + id                   = (known after apply)
      + image_tag_mutability = "MUTABLE"
      + name                 = "image-scan-test"
      + registry_id          = (known after apply)
      + repository_url       = (known after apply)

      + image_scanning_configuration {
          + scan_on_push = true
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_ecr_repository.image-scan-test: Creating...
aws_ecr_repository.image-scan-test: Creation complete after 0s [id=image-scan-test]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed

反映されました。

ECRにコンテナイメージをPushする

名前からして脆弱性まみれそうな以下のイメージを使います。
事前にローカルにPullしておきましょう。
https://hub.docker.com/r/cved/cve-2019-9978

ECRにPushする場合はaws ecr get-loginコマンドで認証情報を取得しておけば
通常通りdocker pushコマンドを実行するだけで良いです。

$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile test-profile)
$ docker tag cved/cve-2019-9978 XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/image-scan-test:latest
$ docker push XXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/image-scan-test:latest

pushしたらマネジメントコンソールから確認してみます。

という感じで自動でスキャンが実行されて結果を確認できます。
それにしても数が多い、脆弱性との戦いは終わらないですね。。。

まとめ

いかがでしたでしょうか。
設定自体は簡単ですしTerraformでコード化しておくと後々の展開も楽ですね。
皆様も是非使ってみてください。


この記事をかいた人

About the author

寺岡佑樹

2016年新卒入社、現在5年目。
SREとして、社内の運用業務の仕組みの検討・実装をしつつ
社外で技術的な登壇を行うエバンジェリスト的な側面も持つ。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn