はじめに
IBM Cloud Security and Compliance Center Workload Protection (SCCWP, URL) は、IBM Cloud の CNAPP (Cloud-Native Application Protection Platform) サービスであり、クラウド環境・コンテナ・Kubernetes・OpenShift・仮想マシン・ホストに対するセキュリティ監視、脆弱性管理、コンプライアンス管理、脅威検知を統合的に提供します。Sysdig社のSysdig Secureをベースとした製品でそれに加えてIBM Cloud用の機能を一部追加で備えます。
SCCWPの持つ機能の一つがコンテナイメージの脆弱性検査ですが、ホスト、コンテナオーケストレーション環境にエージェントを導入するだけでは稼働しません。この記事ではIBM Cloud Container Registry上のコンテナイメージを検査するためのスキャナーの構成方法を紹介します。
スキャナーはIBM Cloud Code Engine上のジョブとして稼働させ、Container Registry上に存在するコンテナイメージに対する脆弱性スキャンを行い、その結果をSCCWPに保存するものです。
事前に準備する必要があるもの
- IBM Cloud アカウント(有償サービスが利用できるようクレジットカードの登録もしくはサブスクリプション契約などが必要です。
- IBM Cloud Security and Compliance Center Workload Protection のサービスインスタンス (30日のトライアルプランが各アカウントでは1回利用可能です)
- IBM Cloud Container Registry の名前空間とコンテナイメージ
- IBM Cloud Code Engine のプロジェクト
SCCWPのAPI Tokenの取得
IBM Cloudのコンプライアンス ダッシュボードからSCCWPのサービスインスタンスを選択し、「ダッシュボードを開く」ボタンからSCCWPのコンソールを表示します。コンソールの左メニューから「Settings」を選択し、画面右側に表示される「Sysdig Secure API Token」の値を控えます。
スキャナーアプリがContainer RegistryにアクセスするためのサービスIDとAPI KEYの作成
IAMのサービスID のページで「サービスIDの作成」をクリックします。
IDを指定して「作成」をクリックします。
次に「アクセス権限の割り当て」をクリックします・
アクセス権限の種類として「アクセス・ポリシー」を選択、サービスは「Container Registry」を選択して「次へ」をクリックします。。
リソースは「すべてのリソース」を選択して「次へ」をクリックします。
役割りとアクションは「サービス・アクセス」の「リーダー」にチェックをいれて「次へ」をクリックします。
画面最下部の「追加」をクリックします。
画面右側にのサマリーに「Container Registryサービス」 の「リーダー」が表示されることを確認して「割り当て」をクリックします。
表示された画面で「APIキー」を選択し「作成」をクリックします。
名前を指定して「作成」をクリックします。
作成されると以下のような画面が表示されるので、APIキーの値を「ダウンロード」するか「コピー」して別の場所に控えます。(後ほど<サービスIDのAPI KEY>として参照します)
値を保存できなかった場合にはAPIキーの作成処理(2つ前のステップ)からやり直します。
スキャナーの作成
スキャナーはSysdig社が提供するコンテナイメージをジョブとして稼働させます。IBM Cloud Code Engine上で稼働させますが、ここからはGUIで操作するのが難しいのでIBM Cloud Shell (ブラウザ上で IBM Cloud CLI や Linux コマンドを利用できる、セットアップ不要のクラウド管理用シェル環境) で作業します。IBM Cloud CLIを利用できる方はその環境で実施いただくのでも構いません。適宜読み替えてください。IBM Cloudコンソール右上に表示される「IBM Cloud シェル」起動用のアイコンをクリックすることでシェル画面に切り替わるのでそちらでコマンドを実行していきます。
Container RegistryとSCCWPの接続情報を指定する構成ファイルと認証用のシークレット情報を含むファイルを作成していきます。
ジョブを稼働するための構成ファイルの作成
ファイルを作る作業はローカルPC上での操作になります。以下のテンプレートをベースに
<ICR url> <IBM account if> <region>の値を埋めてファイルとして保存します。
<ICR url> は東京リージョンを使用する場合 private.jp.icr.io、大阪リージョンを使用する場合 private.jp2.icr.ioとなります。
<IBM account id> は Cloud shellで ibmcloud account show コマンドを実行した際に「Account ID:」として表示される32桁の英数字となります。
<region>は東京リージョンの場合には jp-tok、大阪リージョンの場合には jp-osa となります。
作成したファイルを config.yaml として保存します。
テンプレート
# Registry configuration
registry:
url: <ICR url>
user: from-secret
pass: from-secret
type: icr
accountId: <IBM account id>
memberAccountsRoleName: OrganizationAccountAccessRole
secure:
baseUrl: https://<region>.security-compliance-secure.cloud.ibm.com/
apiToken: from-secret
filter:
maxAgeDays: 2000
maxTagsPerRepository: 5
maxRepositoriesPerRegistry: 500
東京リージョン用に構成した例(アカウントIDはマスクしました)
# Registry configuration
registry:
url: private.jp.icr.io
user: from-secret
pass: from-secret
type: icr
accountId: ********************************
memberAccountsRoleName: OrganizationAccountAccessRole
secure:
baseUrl: https://jp-tok.security-compliance-secure.cloud.ibm.com
apiToken: from-secret
filter:
maxAgeDays: 2000
maxTagsPerRepository: 5
maxRepositoriesPerRegistry: 500
続いて認証情報も同様にファイルとして保存します。こちらは secret.envというファイル名で保存してください。API KEYやAPI Tokenは機密度が高い情報なので取り扱いには十分ご注意ください。
テンプレート
REGISTRYSCANNER_REGISTRY_PASSWORD=<サービスIDのAPI KEY>
REGISTRYSCANNER_REGISTRY_USER=iamapikey
SECURE_API_TOKEN=<Sysdig Secure API Token>
実際に構成したものをマスクした例
REGISTRYSCANNER_REGISTRY_PASSWORD=********************************************
REGISTRYSCANNER_REGISTRY_USER=iamapikey
SECURE_API_TOKEN=********-****-****-****-************
構成ファイルをCloud Shell上にアップロードする
作成したファイルをCloud Shell上にアップロードしていきます。
以下のアップロード用ボタンをクリックして、表示されるダイアログで転送したい config.yaml を選択して転送します。
転送が完了するとCloud Shell上にもその状況が表示されます。ファイルはCloud Shell起動時のディレクトリに一時保存されます。Clous Shellのセッションが終了してしまうとこのファイルはなくなってしまいますのでご注意ください。必要に応じて cat config.yaml コマンドなどで中身を確認します。
同様に secret.env もアップロードします。
構成情報をCode Engine上でConfig Map/Secretを作成する
アップロードしたファイルの情報を元にConfig MapとSecretを作成していきます。
- Code Engineプロジェクトが稼働するリージョン/リソールグループを指定した後にプロジェクトをターゲットとして選択します。リソースグループ名
<RESOURCE_GROUP_NAME>やCode Engineのプロジェクト名<CODE_ENGINE_PROJECT_NAME>がわからない場合にはGUIコンソール上のCode Engineプロジェクトのページ でそれぞれの名称を確認してください。
$ ibmcloud target -r jp-tok -g <RESOURCE_GROUP_NAME>
$ ibmcloud ce project select --name <CODE_ENGINE_PROJECT_NAME>
- Config Mapの作成
実行するコマンド
$ ibmcloud ce configmap create --name registry-scanner-config -f config.yaml
期待される実行結果
$ ibmcloud ce configmap create --name registry-scanner-config -f config.yaml
Creating configmap 'registry-scanner-config'...
OK
Run 'ibmcloud ce configmap get -n registry-scanner-config' to see more details.
- Secretの作成
実行するコマンド
$ ibmcloud ce secret create --name registry-scanner-secret --from-env-file secret.env
期待される実行結果
$ ibmcloud ce secret create --name registry-scanner-secret --from-env-file secret.env
Creating generic secret 'registry-scanner-secret'...
OK
スキャナーを稼働するjobを構成する
ジョブの作成を進めます。以下の例で4GBのストレージの容量以外はそのままコピーすれば稼働します。環境に合わせて書き換える必要は特にありません。
参考文献には特に書かれていないのですが、コンテナで利用できるエフェメラルなストレージがデフォルトの400MBではほぼ確実に不足してしまうので、以下の例では4GBを設定しています。コンテナイメージのサイズが大きいとこのサイズでも足りない可能性があります。最大は48GBまで設定できます (docs) が、これでも足りない場合にはもっと大きなストレージ領域を利用できる専用のKubernetes/OpenShiftクラスターなどを用意してあげる必要があります。
実行するコマンド
$ ibmcloud ce job create --name registry-scanner --image quay.io/sysdig/registry-scanner --ephemeral-storage 4G --mount-configmap /config=registry-scanner-config --env-from-secret registry-scanner-secret -a "--config" -a "/config/config.yaml" -a "--scan_runner" -a "new-vm-scanner"
期待される実行結果
$ ibmcloud ce job create --name registry-scanner --image quay.io/sysdig/registry-scanner --ephemeral-storage 4G --mount-configmap /config=registry-scanner-config --env-from-secret registry-scanner-secret -a "--config" -a "/config/config.yaml" -a "--scan_runner" -a "new-vm-scanner"
Creating job 'registry-scanner'...
OK
この先は実際にJobを実行しますが、GUIコンソールのほうが操作が簡単なので、GUIコンソールで操作を進めます。
スキャナーのジョブを実行する
GUIコンソール上のCode Engineプロジェクトのページ にアクセスし、プロジェクトを選択します。
次に、プロジェクトのページが表示されるので、左側のメニューの「ジョブ」を選択します。画面右側に表示されるジョブの一覧から、スキャナーのジョブ(例をそのまま使っている場合には「registry-scanner」)の名前をクリックします。
「対応可能」な場合には「ジョブの実行依頼」をクリックします。
(「対応可能」でない場合には「対応可能」となるのを待ちます。)
表示されたダイアログの内容はそのまま「ジョブの実行依頼」をクリックします。
待機中となりしばらくすると実行が開始されます。
Container Registryに保存されているイメージの数により実行時間は大きく変わります。私の環境ではイメージが39個ありましたが、約30分の時間を要しました。
SCCWPで結果を見てみる
SCCWPの「Attack Surface」-「Vuln - Registry」を選択すると、イメージごとに脆弱性の問題のサマリーが表示されます。CVSSのスコアなどを元に決められた重要度毎の問題数が表示されます。またその右側にはExploit(悪意ある攻撃手法)の数も書かれています。スクリーンショットに含めた4つのイメージはいずれもExploitが存在するイメージで本番稼働する場合にはそれらを修正したほうが良いことがわかります。
また、イメージの名称をクリックするともう少し細かい情報を確認することができます。数が多くて途方にくれてしまうところですが、使用しているパッケージが古いものなどでは大量に問題が検出されるので、まずそのあたりから修正していくのが良いでしょう。
まとめ
IBM Cloud Security and Compliance Center Workload Protection (SCCWP) のコンテナイメージ脆弱性スキャン機能を利用するために、IBM Cloud Container Registry を対象としたレジストリスキャナーを Code Engine 上へ構成する手順を紹介しました。
SCCWP のエージェントを導入するだけでは Container Registry 上のイメージは自動的にスキャンされないため、今回のように専用のスキャナーを構成することで初めてレジストリ内のイメージに対する脆弱性管理を実施できます。
一度構成してしまえば、Container Registry に保管されているイメージの脆弱性情報を SCCWP 上で一元的に確認できるようになり、重大な脆弱性や Exploit の有無を継続的に把握できるようになります。特に Kubernetes や OpenShift へデプロイする前の段階で問題を発見できるため、シフトレフトなセキュリティ対策としても有効です。
今回は手動でジョブを実行しましたが、Code Engine のジョブを定期実行することで継続的な脆弱性監視環境を構築することも可能です。Container Registry を利用している方は、ぜひ SCCWP と組み合わせて活用してみてください。
参考資料