Well-Architected コンテナアプリケーションレンズを作る試み
-②実践編:製造工程-
投稿日: 2024/03/11
AWSで実装するSP800-190
前回の記事ではコンテナアプリケーションの有用性を紹介しましたが、一方でセキュリティについて満たすためにはユーザの対策が必要になることもお伝えしました。これを考える上で紹介していたのがSP800-190になります。このガイドラインで挙げられている観点を基にAWSでのセキュリティを考えていきます。
https://www.ipa.go.jp/security/reports/oversea/nist/ug65p90000019cp4-att/000085279.pdf
コンテナ技術は性質上アプリケーションとインフラの境界が曖昧な部分があります。一方、観点を変えるとコンテナは製造工程とリリース工程に分けることができます。まずは製造工程についてセキュリティを強化していきます。リリースと連携する箇所もあるため、完全に割り切れませんがリリースの準備と見ていただければと思います。
コンテナイメージリスク
コンテナイメージはコンテナアプリケーションにおける成果物であり、pip,npm,maven,gradleやrpm,debなどのパッケージ群と同じようなもの、またはこれらをさらに内包したものになります。そのため、アプリケーション開発として考えるべきリスクに対応する必要があります。
また、コンテナはWebサーバ,APサーバのようなミドルウェアを含んで構成を行う事ができ、稼働するホストOSに対しても操作範囲が及びます。そのため、デプロイをするためのミドルウェア設定、コンテナ設定についても考える必要があります。
イメージを作成するにあたり、考えられるリスクは下記の通りです。前回でも述べた通り、アプリケーション部分のため全てユーザ責任になります。3rdPartyのツールを用いる、他の機能で担保できるものもあるため必ずこの構成にする必要はありませんが、観点については満たすべきです。
イメージのリスク
項目 | 詳細 | 対象 |
---|---|---|
イメージの脆弱性 | 脆弱性のあるコード記述、パッケージやライブラリを含んでしまうリスク | ソースコード、ライブラリ、パッケージ、コンテナイメージ |
イメージ設定の不具合 | イメージビルドの設定(DockerFile)でセキュリティ情報を満たしていない | DockerFile、ベースイメージ |
埋め込まれたマルウェア | マルウェアを含んだイメージが混入していないか | コンテナイメージ |
埋め込まれた平文の秘密情報 | ソースコードにシークレット情報が含まれていたり、変数が使いまわされるなどのリスク | ソースコード、認証情報を含んだファイル(Git上) |
信頼できないイメージの使用 | オープンソースの信頼できないイメージを無制限に扱ってしまうリスク | コンテナイメージ |
コンテナイメージリスクへの対策
上記のリスクについてユーザができる対策を見ていきましょう。確かにアプリケーション部分なので責任共有モデル上ユーザが責任を負うものですが、AWSのサービスを利用、組み合わせることでその負担を軽減する事ができます。
イメージの脆弱性対策1:CodeGuruを用いたSAST
https://aws.amazon.com/jp/codeguru/features/
CodeGuruのセキュリティスキャンによりコードに含まれる脆弱性情報を検出できます。Gitと統合してソースコードをスキャンしたり、ファイルをアップロードしてスキャンをかける事も可能です。

実際にサンプルコードでスキャンを行うと検出された脆弱性が一覧表示されました。危険性の説明から対策についても記載がされています。この検出と対策をCIパイプラインに組み込み承認フェーズを挟みSASTで合格した脆弱性のないコードだけが以降ビルドされていきます。

イメージの脆弱性対策2:ECR +Inspectorによるイメージスキャン
ソースコードで対策されていれば十分というわけでは必ずしもありません。というのも、既にビルドしてリリースされているイメージが新規の脆弱性を含んでしまった場合に対応できないためです。また、ソースコードでなくパッケージやライブラリなどビルド過程で初めて利用、混入するものについては捕捉しきれないためです。
ECRでは無償の基本スキャンと拡張スキャンが提供されています。前者はECRのみで実行され、後者はInspectorと統合されています。CodeGuruや3rdParty製品ではソースコードやビルド定義をスキャンしていましたが、ここでは最終成果物であるコンテナイメージに対してスキャンを実施しています。基本スキャンはOSパッケージに対してのみなので、パッケージやライブラリについても拡充するのであれば有償の拡張スキャンを利用する方がよいです。
実際に古いバージョンのNginxを拡張スキャンを有効にしたECRにPushしスキャンをかけてみました。するとInspector上のECR及びPushされたコンテナイメージに脆弱性情報が出力されました。CodeGuruと同様に脆弱性情報と対策が記載されています。


オープンソースやサードパーティのCWP(Cloud Workload Protection)ツールでも同様の機能が利用可能ですが、マネージドサービスとして提供されコンテナレジストリとセットで提供されているのは非常に有用です。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-scanning.html
https://docs.aws.amazon.com/ja_jp/inspector/latest/user/scanning-ecr.html
イメージ設定の不具合対策:3rdパーティー製品の力を借りてスキャンを行う
ソースコードの対策を行った後はDockerfileへの対策です。DockerFile、ビルド時のベストプラクティスは以下に提示されています。
https://docs.docker.jp/develop/develop-images/dockerfile_best-practices.html
Dockerfileやビルド時のセキュリティ対策についてはOSSが充実しているのもあり、CodeBuildや利用中のCIツール内でOSSによるスキャンを行うケースがAWSとしても紹介されています。
主なオープンソースとしてはTrivy、checkov、dockleなどがあります。他にも有償の製品内でカバーするものがあればそちらを利用しても良いでしょう。
対象OSS | リンク |
---|---|
Trivy | https://aquasecurity.github.io/trivy/v0.45/docs/scanner/misconfiguration/ |
checkov | https://www.checkov.io/ |
dockle | https://github.com/goodwithtech/dockle |
また、DockerでないApp2Containerなどを利用の方は各サービス、ソフトのビルド時のベストプラクティスを適用しましょう。
https://docs.aws.amazon.com/ja_jp/app2container/latest/UserGuide/iam-a2c.html
埋め込まれたマルウェアの対策:GuardDuty Malware Protectionによる検知
開発段階で不審なライブラリやパッケージが入らないようにする。後述の署名付きのイメージのみ利用できるようにする事でほぼ防げますが、混入した場合に何も対処できないというのは心もとあないです。予防的統制ではなく発見的統制となりますが、GuardDutyのMalwareProtectionを用いることにより、不審な振る舞いを検出することができます。
MalwareProtectionではEBSのスナップショットを取得してそこからスキャンを行う事ができます。エージェントレスで対応できるのが魅力ですが、EBSを軸としているためFargateは対象外になります。また、リアルタイムでの検出までは行えませんのでその点は注意が必要です。
リリース工程でのセキュリティ対策、製造工程での混入を防げば基本的には問題ないですが、さらに対策を立てたい場合はMalwareProtectionまたは3rdParty製品を活用するのも手です。

埋め込まれた平文の秘密情報対策:脆弱性スキャンとシークレットの管理一元化
シークレットがソースコードやファイルにハードコードされて登録されている場合は上記のCodeGuruまたはECR/Inspectorのスキャンで検出する事が可能です。一方、シークレットをどう扱うかというとAWSとしてはやはりSecretManagerを用いる事が最善です。
Secretの自動更新と一元管理を行えるため、ファイルやGit上で管理するよりも効率よくかつ安全に管理ができます。
https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/intro.html
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/manage-secrets.html

信頼できないイメージの使用への対策:イメージスキャンとSigner署名の実施
前述で試しに操作した通り、外部から取得したNginxのイメージをECR/Inspectorでスキャンし脆弱性診断を行う事ができました。一見するとこれで満たせるようにも思えますが、スキャンで脆弱性や脅威を見つけるまででPullについて制限は特にありません。そのため、脆弱性を含んでいてもPullする事ができてしまいます。これを防ぐために署名を活用します。
AWSではSigner/ECRを用いてECRのPushに合わせて署名を付与することができます。CNCF認定のオープンソースであるNotation(旧Nonary)と統合されており、Notationの署名をPush時に行う事で付与でき、その署名はSigner/ECRに保管、管理されます。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-signing.html

また、この署名を持ったイメージだけをPullできるよう制限がないと足りません。リリース工程の話にはなりますが、K8sのAdmission Controller機能と連携したKyvernoなどポリシーエンジンをデプロイする事で署名されたイメージだけをデプロイさせる事が可能になります。
https://kyverno.io/docs/writing-policies/verify-images/
イメージのリスクと対策
ECRの拡張スキャン有効化により満たせる項目が多くありますが、全てを担保できません。開発工程で脆弱性が入り込まないように3rdParty製品を組み合わせたり、リリース後にGuardDutyで捕捉する事でより拡充できます。
しかし、完全に満たすためにはどうしても利用料が高額になります。ECRの基本スキャンやCIツール内でOSSのイメージスキャン、イメージ設定スキャンを行うツールの導入を行う事から始め、より自動化/安定化のフェーズに入ってから、本番環境から導入としても良いかと思います。
項目 | 詳細 | AWSでの対策 |
---|---|---|
イメージの脆弱性 | 脆弱性のあるコード記述、パッケージやライブラリを含んでしまうリスク | CodeGuru,ECR/Inspector拡張スキャン |
イメージ設定の不具合 | イメージビルドの設定(DockerFile)でセキュリティ情報を満たしていない | CodeBuild(他CIツールも可)にOSS,3rdParty製品のスキャン |
埋め込まれたマルウェア | マルウェアを含んだイメージが混入していないか | CodeBuild(他CIツールも可)にOSS,3rdParty製品のスキャン |
埋め込まれた平文の秘密情報 | ソースコードにシークレット情報が含まれていたり、変数が使いまわされるなどのリスク | ECR/Inspector拡張スキャン,SecretManager |
信頼できないイメージの使用 | オープンソースの信頼できないイメージを無制限に扱ってしまうリスク | ECR/Inspector拡張スキャン,ECR/Signerによる署名,EKS上での署名付きイメージ判定 |
コンテナレジストリリスク
コンテナレジストリはコンテナイメージを格納するためのストレージまたはパッケージ管理ツールに該当するものです。レジストリへのアクセス管理と中身のイメージについて管理がなされているかを評価します。イメージのリスクでも触れた通り、レジストリの機能を利用する事で防げるリスクがある一方でレジストリ自体に危険が及ぶ事も考えないといけません。
コンテナレジストリを扱う上でのリスク
項目 | 詳細 | 対象 |
---|---|---|
レジストリへのセキュアでない接続 | 暗号化されていない通信によるアクセス | ネットワーク、レジストリ設定 |
レジストリ内の古いイメージ | 過去作成・格納したイメージが削除または更新されず脆弱性を含んだままになっている | コンテナイメージ、レジストリ設定 |
不十分な認証・認可制限 | レジストリに対する認証認可の管理がなされておらずアクセス制限がない | ImagePullSecret、レジストリ設定 |
コンテナレジストリリスクへの対策
せっかくセキュアなイメージを作成しても、それを保管するレジストリの管理がセキュアでないと不正なイメージを持ち込んだり、開発したイメージを持ち出されたり、脆弱性のあるイメージを放置してしまう可能性があります。ECRを使えば設定はユーザ責であるものの、レジストリ自体はAWS責になります。正しく設定をする事で担保ができます。
コンテナレジストリリスクへの対策:暗号化されていない通信によるアクセス
レジストリをPrivateネットワークで構成し、かつTLSを有効にした通信を行う事で担保できます。ECRを用いる事で解消可能です。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/Registries.html
一方、よりセキュアにするには、コンテナをPush/Pull/ReplicateするPrincipal(主体)が何でどの経路を通るのか見直す事です。インターネットを介さない閉域ネットワークまたはAWSに閉じた通信とするのか、インターネットを介した通信があるのかもポイントとなります。暗号化に加えて通信経路を制限したい場合はVPCエンドポイントを用いて通信を閉じる事で担保ができます。

経路についてはそこまで心配していない、エンドポイントの利用にお金をかけられないようなシステムであればECR利用をするだけでこのリスクは対策できます。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/vpc-endpoints.html
コンテナレジストリリスクへの対策:レジストリに対する認証認可の管理がなされておらずアクセス制限がない
通信でも触れましたが、”何”がECRにアクセスしてくるのかを考えます。
例えばコンテナを格納するPushをするのは原則CIツールのみ、コンテナを展開するPullをするのはCDツールのみ(GitOps対応であればArgoCD/FluxCD)、DRやイメージ配布用にReplicationしてくるのは別アカウントまたは別リージョンのECRのみとなります。
原則これらがPrincipalとして扱われるべきです。そして各Principalが操作できるAction範囲はその用途に限定されるべきです。つまり基本的には最小権限の原則に従うことになります。
ECRの認証認可の制御はアイデンティティベース(IAM)とリソースベース(ECR)の2つのポリシーが利用できます。前者はPrincipal側での許可、後者はリソース側でPrincipalやResourceを限定した許可を行うものになります。基本的にはS3のバケットポリシーとIAMでのS3操作と変わりません。
#CloudBuildだけにPushを許可するリソースベースポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowService",
"Effect": "Allow",
"Principal": {
"Service": [
"codebuild.amazonaws.com"
]
},
"Action":[
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:BatchGetImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
"ecr:PutImage"
],
}
]
}
また、GitOpsの場合、CDツールはK8sのクラスタ上にコンテナとして存在しています。そのため、EKS上のコンテナがアクセスしてくるためのリソースベースポリシーが必要となります。EKSのPodにIAMロールを持たせつつ、それが何なのかを限定します。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/service-accounts.html
一方、EKS上で動かす前にコンテナをローカルやEC2,Cloud9などでPullして挙動を確かめたい場合などもあると思います。その場合でも必ずPrincipalを特定して限定し他を許容しないようにします。
コンテナレジストリリスクへの対策:過去作成・格納したイメージが削除または更新されず脆弱性を含んだままになっている
ECRのライフサイクルポリシーの適用で実現が可能です。イメージ数の上限を決めて上限を超えた場合に消すパターンとPushからの期限を決めて期限を超過した場合に消すパターンの二つが実装可能です。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/lifecycle_policy_examples.html

誤って消してはいけないものを消してしまうリスクがあるため、どちらを採用するかどのように運用すべきかに注意すべきです。
最悪ソースコード,パッケージ,DockerFileなどイメージ作成に必要な資源は全てGit上に存在していればイメージは再作成が可能です。また、即時前のバージョンにロールバックを行う事も考えてイメージ数上限を使うのがおすすめと考えます。イメージ数上限を例えば2にしてしまえば1世代前までに限定でき、RollBackを可能にしつつ最新のイメージを原則参照できる最小数のためです。
また、本番用のタグがついたイメージはその運用にし、開発/リリース検証用のイメージは時間経過で消し残さない運用ができます。
コンテナレジストリのリスクと対策
ECRを利用し適切な設定を行うことでこれらリスクに対応可能です。しかし、S3と同じようにリソースベースのポリシーやライフサイクルルール、パブリック公開の有無などAWSとして適切な設定を行う必要があり、これはユーザ責です。ここを便利だから、楽だからと安易にワイルドカードで全許可する事を堪えてセキュアな設定を入れましょう。
項目 | 詳細 | AWSでの対策 |
---|---|---|
レジストリへのセキュアでない接続 | 暗号化されていない通信によるアクセス | ECRをPrivateで構成 |
レジストリ内の古いイメージ | 過去作成・格納したイメージが削除または更新されず脆弱性を含んだままになっている | ECRのライフサイクルルールを設定 |
不十分な認証・認可制限 | レジストリに対する認証認可の管理がなされておらずアクセス制限がない | ECRのリソースベースポリシーとアイデンティティベースポリシーを最小権限で構成 |
まとめ
コンテナアプリケーションの開発工程で混入しうるセキュリティリスクを抑える対策について今回触れてきました。コンテナだからK8sだからだけでなく、非コンテナのパッケージ作成までのアプリケーションでも通用する内容でした。
他にもAWSのサービスを代替するOSSや3rdParty製品も多くあり、そちらと組み合わせて対策を実現することも可能です。AWSをメインで他のクラウドがサブ、AWS一本ということであればマネージドサービスを使わない手はないです。
コンテナは動かす土台さえあればラップトップ上でもクラウドでもオンプレミスでもどこでも動かせます。また、ダウンロードとアップロードが容易なために、ついオープンソースや開発中のコンテナを無制限にPush/Pullして稼働させてしまいがちです。せっかくの利便性を全て台無しにしないよう、まずは開発工程からセキュリティを考えてみてはいかがでしょうか?
CTCは、AWSのビジネス利活用に向けて、お客様のステージに合わせた幅広い構築・運用支援サービスを提供しています。
経験豊富なエンジニアが、ワンストップかつ柔軟にご支援します。
ぜひ、お気軽にお問い合わせください。