コンテナのセキュリティ対策まとめ

# はじめに
クラウドネイティブ学習の一環として、コンテナにおけるセキュリティ対策について学びました。
今回学んだこと忘れず実務で必要になった時に参照できるよう、記事にまとめました。

# コンテナのセキュリティ対策
コンテナ型アプリケーションにおいて、コンテナに対するセキュリティ対策は、従来型のサーバ型仮想化（ハイパーバイザー型）とは異なるアプローチが必要となる。
コンテナを構成する階層ごとに脆弱性が存在し、それぞれセキュリティ対策が必要。
具体的には、下記のレイヤーに分けられる。
- **コンテナイメージ**
- **レジストリ**
- **オーケストレータ（Kubernetes）**
- **コンテナ**
- **ホスト**
- **コード**



## コンテナイメージ
- コンテナイメージには、ベースイメージとアプリケーションフレームワークといった各種ソフトウェアから構成されており、インストールされたツールに既知の脆弱性が内在する恐れがある。
- ツールの脆弱性に十分対処していたとしても、人的な不備により、Dockerfileテンプレートにセキュリティ上危険な設定が記述されている可能性がある。
- イメージへの脆弱性対策として、**イメージに対する脆弱性スキャンを継続的に実行する**ことが必要。
  - イメージスキャナによって、主に下記項目を検出する。
・**イメージの脆弱性**
・**信頼できないイメージの使用**
・**独自のチェック項目（業界的なコンプライアンスに準拠しているかどうか等）**
・**マルウェア**
・**シークレット情報（平文パスワード、SSH秘密鍵等）**
  - **イメージスキャナツール**としては``Trivy``, ``Dockle``がある。またAWSでは、``Inspcetor v2``によりECRに格納されたイメージの継続的スキャンが可能。これらツールは要件に応じて組み合わせて利用する。
- **イメージのスリム化**もイメージの脆弱性対策に有効。
  - **イメージ軽量化はアプリケーションのパフォーマンス向上に寄与するだけでなく、攻撃対象の削減にもなる**。
  - スクラッチイメージから必要なランタイム、ツールのみインストールする **「加算アプローチ」** を検討する。
  - 必要なければシェルプログラム（/bin/sh, /bin/bash）はイメージに含めない。
  → 攻撃者がコンテナ内のシェルを奪取してリモートコマンド実行することを防止


## レジストリ
- クラウドのレジストリサービスとしては、AWS ECRやAzure ContainerRegistryがあるが、**必要最低限のユーザ/サービスからのみアクセス許可し、通信経路もセキュアなもののみに限定する**といった対策が必要。
- AWSでいえば、下記のような対策があげられる。
  - ECRにアクセス可能な``IAMロール/IAMユーザ``の管理
  - ECR側で権限管理したい場合は、```リポジトリポリシー```の使用も検討
  - ECR用```VPCエンドポイント```の使用（セキュアな通信経路の確保）
- 古い使っていないイメージが溜まりリポジトリが肥大化していく恐れがあるため、定期的なチェックと**不要イメージのクリーンナップ**が必要。
→誤ったイメージの使用防止



## オーケストレータ（Kubernetes）
オーケストレータのセキュリティ対策は非常に多岐にわたるため、ここでは一部のみ簡単に記載する。（余力があれば別で記事作りたい）
- **コントロールプレーンの保護**
  - **プライベートAPIエンドポイント**のみの使用（VPC内からのアクセスのみ許可）
  - パブリックAPIエンドポイントを使用する場合は、IPによるアクセス制限
- dev/stg/prdといった環境別での**namespaceの分離**
- **RBAC**による、職務別（ex:開発者、テスター、クラスター管理者等）でのK8sリソースへのアクセス制御 

## コンテナ
K8s等オーケストレータによりデプロイされたコンテナに脆弱性があり侵害された場合、その影響範囲は単独のコンテナ内にとどまらない。
そのため被害を最小限に抑えることを目的に、下記のような対策が必要。（K8マニフェストで設定可能）
- Podに付与されるホスト（ノード）へのアクセス権限最小化
- Podのホストへのファイルマウント最小化
- 必要ない限り、コンテナ間通信を無効化
- Linuxセキュリティモジュール（seccomp, AppArmor, SELinux）を使用


## ホスト（K8sノード）
コンテナを稼働させるホストへのセキュリティ侵害防止には、下記が考えられる。
- データプレーンに**マネージドサービス**を利用しセキュリティ運用を省略
  - ex:EKSなら、EC2ではなく**AWS Fargate**を使う。
  - 起動速度や料金等の問題があるため、要件によりFargateを使えるか検討が必要。
- コンテナに **最適化されたOS（CoreOS, RancherOS）** を使用して攻撃対象領域を削減
- ホストへの**リモートアクセスを最小化**
  - SSHは廃止し、セッションマネージャによるアクセスに限定など

## コード
　IaC（CloudFormation, Terraform, K8sマニフェスト等）によってインフラを構成管理することで、構築の属人化防止やベースラインの確保が可能になった。
　それに加えIaC導入により、セキュリティ的な観点でもテンプレートの静的セキュリティスキャンが可能になり自動的・継続的なセキュリティ問題の検知の仕組みも構築しやすくなった。
　以下のような対策を検討する必要がある。

- **デプロイ前の静的スキャン**
  - インフラコードもアプリケーションコードと同様、CI/CDパイプラインによりデプロイ前に静的スキャンを行い自動テストすることで、インフラ構成の継続的な脆弱性対策が可能。
  - コードのセキュリティスキャンツールとして``trivy``などが利用可能。以下のような脆弱性を検知する。
・過剰な権限を有するロール
・サービスの外部公開
・暗号化されていないストレージ
・不十分なロギング

- **ドリフトの監視**
  - デプロイ後であっても、ユーザが手動で構成に変更を加え想定外の脆弱性が発生する恐れがある。そこで構成ドリフトを継続的に検出することが望ましい。
  - AWSでは、ConfigとEventBridgeの組み合わせにより**継続的なドリフト監視・自動通知**が可能。
    （参考：[AWS CloudFormationスタックのドリフトを検出してSlackに通知する](https://ts223.hatenablog.com/entry/aws/cfn-drift-detector)）

- **宣言的セキュリティポリシー制御**
  - **OPA(Open Policy Agent)** によりKubernetes APIへのkubectlリクエストに対し、認可制御を実装できる。
  - OPAポリシー（ユーザのどのようなkubectl操作を許可するか）はRegoという言語で記述できる。
（このような、ポリシーを宣言的に定義することを**Policy as Code**と呼ぶ。）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577028/4ab89552-254b-ba98-3489-d775dc2f7c09.png)


# 参考記事
- [クラウドネイティブセキュリティ入門](https://www.amazon.co.jp/%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E5%85%A5%E9%96%80-%E6%BE%A4%E6%A9%8B-%E6%9D%BE%E7%8E%8B/dp/4863543492)
- [NECセキュリティブログ - コンテナイメージのセキュリティ](https://jpn.nec.com/cybersecurity/blog/220128/index.html)
- [Open Policy Agent とは？](https://openstandia.jp/oss_info/open-policy-agent/)