セキュアなデプロイメントを実現するKubernetesアドミッションコントローラ
本文の内容は、2019年6月4日にSysdigのKaizhe Hungが投稿したブログ(https://sysdig.com/blog/kubernetes-admission-controllers/)を元に日本語に翻訳・再構成した内容となっております。
Kubernetesアドミッションコントローラは、Kubernetesネイティブのパワフルな機能で、何をクラスタ上で稼働させるのかについて定義とカスタマイズを支援します。アドミッションコントローラは、インターセプトを介して、オブジェクトの永続化の前にリクエストが認証、および承認された後に、Kubernetes APIに対してプロセスのリクエストを行います。
この記事では、Kubernetesアドミッションコントローラの機能とSysdig Secureを統合して、クラスタにデプロイされるすべてのイメージにイメージスキャンとカスタムセキュリティポリシーを適用する方法について説明します。
API機能を拡張することで、リクエストの変更(MutatingAdmissionWebhook)や、実行を許可するかどうかを決定したりするコードをフック(ValidatingAdmissionWebhook)することができます。 先ほど述べたように、基本的にリクエストがetcdに永続化の実行前に行われます。これらの機能により、Kubernetesアドミッションコントローラは、予防的なセキュリティコントロールをクラスタへデプロイするのにとてもうってつけな選択肢と言えます。
コントローラは、kube-apiserverバイナリにコンパイルされており、クラスタ管理者によってのみ有効化または更新されます。 下図は、アドミッションコントローラがKubernetesリソース作成ワークフローにどのように作用するかを示しています。
上の図からわかるように、Kubernetes APIサーバーとカスタムコード実装の間の通信には、かなり標準的なWebhookインターフェイスが使用されているため、サードパーティコードとの統合とインター接続が比較的簡単に実現が可能です。
Kubernetesアドミッションコントローラは何をするのですか?
コンテナ化されたマイクロサービスは、通常、ポッド内で動的に作成、エフェメナルに実行します。これらの機能はソフトウェアライフサイクルにとって画期的なものですが、クラウドネイティブセキュリティを急速に変化させている要因ともなっています。 新しいデプロイやポッドを作成または自動スケールするときはいつでも、クラスタ管理者が答えるべき多くの質問が出てきます。
- ポッドが多すぎるリソースを要求していませんか?
- マイクロサービスポッドの作成に使用されるベースイメージは安全ですか?
- このデプロイメントの優先順位は他のものと比べていかがでしょうか?
- たとえば、クラスタのリソースが不足していてポッドをデリートする必要がある場合
- このポッド/デプロイメントにリンクしているサービスアカウントに現在付与されている特権はどれですか?
- 彼らは最小特権の原則を遵守していますか?
これらの質問に答えることができることは、信頼性の高い安全なサービスを実行するために不可欠です。 各組織には独自のポリシーとデフォルトのベストプラクティスがあります。 このため、ベースコードを複雑にすることなくKubernetes APIの機能を拡張できる「プラグイン」ポリシーメカニズムが必要になりました。
あなたはたぶんすでにあなたの標準的なデプロイメントであらかじめ構成されたアウトオブボックスないくつかのKubernetesアドミッションコントローラを稼働させているかも知れません。 以下は、どんな一般的なデプロイメントでも見つけることができる推奨されるKubernetesアドミッションコントローラのセットです。
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota,PodSecurityPolicy
ポッドの優先順位やリソース要求の制限など、Kubernetesには組み込みと見なすことができるいくつかの側面が実際にはこれらのコントローラによって制御されていることがわかります。
これらのアドミッションコントローラは、リソース制御からプロビジョニングおよびセキュリティ面まで、さまざまな役割を果たすことができます。 以下は、Kubernetesでサポートされているアドミッションコントローラの例です。
- PodSecurityPolicy:このアドミッションコントローラは、ポッドの作成および変更に基づいて動作し、要求されたセキュリティコンテキストと利用可能なポッドセキュリティポリシーに基づいて承認するかどうかを決定します。
- PersistentVolumeClaimResize:このアドミッションコントローラは、リスエストされるPersistentVolumeClaimサイズ変更要求をチェックするための追加の検証を実装します。
- ValidatingAdmissionWebhook:このアドミッションコントローラは、リクエストに一致するすべての検証Webフックを呼び出します。 一致するWebフックは並列で呼び出されます。 いずれかがリスエストを拒否した場合、リスエストは失敗します。 カスタム・セキュリティ・ポリシーを実装するためにこれらのウェブフックを簡単に実装する事ができます。
理論を十分に理解したと思いますので、実際のKubernetesセキュリティユースケースを見ていきましょう。
ユースケース:Kubernetesアドミッションコントローラーの1つとしてSysdig Secureイメージスキャンを統合する
Sysdig Secureは、KubernetesクラスタをSysdig Secure Image ScanningおよびKubernetesコンプライアンスに統合するためのエレガントな方法を提供しています。ワークフローの概要図は以下の通りです。
このケースでは、WebhookプロバイダーはKubernetesクラスターのポッドになります。 このポッドは、自分自身をValidatingAdmissionWebhookとして登録し、APIリクエストを解析し、イメージ定義をSysdig Secureに転送します。
Sysdig Secureはその後イメージを取得し、定義されたセキュリティポリシーに準拠していることを確認します。 このセキュリティ検証の決定はAPIに伝播され、元のリクエスタに応答して、イメージがチェックに合格した場合にのみオブジェクトをetcdデータベースに保持します。
Sysdig Secure Image Scanningを上記のワークフローに統合するために必要な手順は非常にシンプルです。
ステップ1:Sysdig Secureを使ってイメージスキャンポリシーを作成する
Sysdig Secureは、オープンソースのスキャンエンジンであるanchoreを活用して、実行環境、レジストリ、またはCI / CDパイプラインにおけるイメージの内容を分析します。 Kubernetesアドミッションコントローラによってトリガーされるポリシーを作成する場合、最初のステップはイメージ内の脆弱性をチェックすることですが、Sysdig Secureポリシーが提供するさまざまなゲートを使用して実施できることはそれだけではありません。 ほんの数例ですが、Dockerfileのルールからソフトウェアのライセンス、ファイル、ファイルの許可、許可された有効なユーザー、言語固有のパッケージ、そしてメタデータ属性など、Sysdig Secureイメージスキャンポリシーゲートと、設定できるトリガーの詳細な説明もあります。
セキュリティゲートを定義したら、それが停止条件(この場合、アドミッションコントローラがデプロイメントを拒否する)か、それともイメージレポートに反映されるセキュリティ警告のみかを決定します。
上記イメージで設定したポリシーの例では、次のことを確認しています。
- このイメージの脆弱性フィードデータは1週間以内のものです
- イメージに脆弱性はありません(HighまたはCriticalを考慮)
- ポート22はDockerfileで公開されていません
- このイメージの有効ユーザーはrootではありません
ステップ2:Webhookを設定し、アドミッションコントローラをデプロイする
Kubernetesクラスタにこのインテグレーションをデプロイするのは非常にシンプルです。 まず、kubectlがインストールされ、ターゲットクラスタを指すように設定されていることを確認します。
次に、プロジェクトリポジトリをチェックアウトして、新しいディレクトリに移動します。
git clone git@github.com:sysdiglabs/image-scanning-admission-controller.git
次に、2つの環境変数を宣言する必要があります。
export ANCHORE_CLI_URL="https://api.sysdigcloud.com/api/scanning/v1/anchore"
export ANCHORE_CLI_USER="xxxxxxx-xxxx-xxxxxx-xxxxxx-xxxxx"
エンドポイントURLおよびAPIアクセストークンについては、SaaSバージョンのSysdig Secureを使用している場合は上記のURLを使用できます。それ以外の場合は、そのアドレスのホストセクションを置き換える必要があります。 Sysdig Secureプロファイルの[設定]メニューにアクセスしているAPIアクセストークンを見つけることができます。
デプロイするには、make deployを実行します。
$ make deploy
+ deploy
./scripts/deploy.sh
namespace/image-scan-k8s-webhook-system created
clusterrole.rbac.authorization.k8s.io/image-scan-k8s-webhook-manager-role created
clusterrolebinding.rbac.authorization.k8s.io/image-scan-k8s-webhook-manager-rolebinding created
secret/image-scan-k8s-webhook-webhook-server-secret created
secret/sysdig-secure-token created
service/image-scan-k8s-webhook-controller-manager-service created
statefulset.apps/image-scan-k8s-webhook-controller-manager created
+ sleep 3
+ kubectl get all -n image-scan-k8s-webhook-system
NAME READY STATUS RESTARTS AGE
pod/image-scan-k8s-webhook-controller-manager-0 0/1 ContainerCreating 0 3s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/image-scan-k8s-webhook-controller-manager-service ClusterIP 10.104.71.12 <none> 443/TCP 3s
NAME READY AGE
statefulset.apps/image-scan-k8s-webhook-controller-manager 0/1 3s
Step 3: 設定確認
最後のステップでは、image-scan-k8s-webhook-systemを作成しました。 Webhookプロバイダが起動して稼働中であることを確認しましょう。
$ kubectl get pods -n image-scan-k8s-webhook-system
NAME READY STATUS RESTARTS AGE
image-scan-k8s-webhook-controller-manager-0 1/1 Running 1 25m
ValidatingWebhookConfigurationがKubernetes APIに登録されていることを確認することもできます。
$ kubectl get ValidatingWebhookConfiguration
NAME CREATED AT
validating-webhook-configuration 2019-05-29T10:45:10Z
このオブジェクトをさらに詳しく調べると、(他の多くの属性の中でも)Webhookサービスの設定を見ることができます。
$ kubectl describe ValidatingWebhookConfiguration
...
Service:
Name: webhook-server-service
Namespace: image-scan-k8s-webhook-system
Path: /validating-create-pods
...
Step 4: Sysdig Secureの統合をテストする
これで、アドミッションコントローラが実行され、クラスターに生成した新しいイメージを調べる準備が整いました。 すぐに、任意のイメージでこの統合を試すことができますが、テストを容易にするために、2つのデフォルトデプロイメントを提供しています。 (セキュリティフィルタを通過するテストケースと通過しないテストケース)
下記を実行します:
$ make test
少しして、
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
apache-struts2 1 0 0 0 5m
nginx 1 1 1 1 5m
Nginxのデプロイメントがポリシー評価チェックにパスしたため、AVAILABLE状態に示すようにポッドが実行されています。 デプロイメントapache-struts2に重大度の高い脆弱性cve-2017-5638が含まれているため、実行に失敗しました。 Kubernetesのログを調べてリクエストのレスポンスを取得することができます。
$ kubectl get events
LAST SEEN TYPE REASON OBJECT MESSAGE
67s Warning FailedCreate replicaset/apache-struts2-8bb7bd7b Error creating: admission webhook "validating-create-pods.k8s.io" denied the request: Image failed policy check: kaizheh/apache-struts2-cve-2017-5638
さらに、Sysdig Secureインターフェースにアクセスするだけで、このWebhookがクラスター内で構成されている間に、生成したすべてのイメージについての完全なスキャンレポートが作成されます。 インターフェースを開いて[イメージスキャン、リポジトリ]タブに移動すると、検索ボックスが表示されます。 セキュリティレポートを表示するために送信したインメージの名前とタグを探します。
注:Webフックの検証にはKubernetes APIによる30秒のタイムアウトがあります。特定のイメージを初めてデプロイする場合、このタイムアウト以内にAPIからの応答がないと、アドミッションコントローラはリクエストを拒否します。 image-scanning-admission-controller.yamlファイルで環境変数REJECT_IF_TIMEOUTでデフォルトのタイムアウトを調整できます。
結論
KubernetesアドミッションコントローラとSysdig APIはどちらも、Webhookの呼び出しをサポートするサードパーティと統合するためのシンプルで安全なメカニズムを提供します。 この統合をクラスタに導入することで、スケジュールされる前であっても、クラスタで要求されているポッドに対してSysdig Secureイメージスキャンポリシーとセキュリティゲートを最大限に適用できます。 デフォルトで必須のセキュリティはセキュリティを考慮する上で最良な方式の1つであり、それはKubernetesオペレータとしてのあなたの安心感を大いに高めるでしょう。
こちらからwebhookプロバイダーのためのソースコードを入手できます。