これまでにSysdig Secureのレジストリスキャンとして下記をご紹介してきました。今回はAzure Container Registry(ACR)に対するレジストリスキャンの設定方法をご紹介します。
Sysdig SecureでACRに対するレジストリスキャンを実施する方法として、レジストリトークンを使用する方法とサービスプリンシパルを使用する2つの方法があります。
(オプション1) レジストリトークンの作成
レジストリトークンは _repositories_admin
のスコープマップを使用する必要があります。詳細はAzure ACRのドキュメントをご参照ください。
Azureコンソールで自身のレジストリのTokens画面に移動します。Add ボタンをクリックしてトークンを新規作成します。
トークン名を入力し、Scope mapとして_repositories_admin
を選択します。
トークンが作成されたことを確認します。
作成されたトークン名をクリックして詳細画面に移動し、password1 をクリックします。
Generate をクリックします。
Passwordが生成されるので、後で使用するためにコピーしておきます。
(オプション2) サービスプリンシパルの作成
ACRに対してサービスプリンシパルを使ったレジストリスキャンを実施するためには、Azure ACRのドキュメントの指示にしたがってacrpull
ロールを持ち、スコープを自身のレジストリに設定したサービスプリンシパルを作成する必要があります。
以下のCLIコマンドでサービルプリンシパルを作成します。
az ad sp create-for-rbac --name yoSP --role acrpull --scopes /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/RegistryRG
LinuxサーバへのAzure CLIのインストール
Azure Cloud ShellにDockerはインストールできないので注意。
すでにDockerをインストール済みのLinuxサーバにログインし、以下のコマンドを実行します。
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
ACRへのイメージプッシュ
Azureにログインします。
az login
ACRにログインします。
az acr login --name yoregistry
イメージをプルしてタグを付けます。
古すぎるイメージはレジストリスキャンがスキップされるので使用しないでください(デフォルトではスキャン対象は作成から90日間までに設定されています)。
docker pull nginx
docker tag docker.io/library/nginx yoregistry.azurecr.io/samples/nginx
レジストリトークンを使用してACRにdocker login
します。
docker login -u yoRegistryToken -p <REGISTRY_TOKEN> yoregistry.azurecr.io
イメージをACRにプッシュします。
docker push yoregistry.azurecr.io/samples/nginx
Azureコンソールでイメージがプッシュされたことを確認します。
レジストリスキャナーのデプロイ
レジストリスキャナーはAzure Kubernetes Service (AKS)などのKubernetes上にデプロイする必要があります。
Helmコマンドを使ってKubernetes上にレジストリスキャナーをデプロイします。
(オプション1)レジストリトークンを認証に使用する場合
helm upgrade --install registry-scanner sysdig/registry-scanner --version=1 \
--set config.secureBaseURL=<SYSDIG_SECURE_URL> \
--set config.secureAPIToken=<SYSDIG_SECURE_API_TOKEN> \
--set config.registryType=acr \
--set config.registryURL=<ACR_REGISTRY_URL> \
--set config.registryUser=<ACR_TOKEN_NAME> \
--set config.registryPassword=<ACR_TOKEN_PASSWORD>
(オプション2)サービスプリンシパルを認証に使用する場合
$ helm upgrade --install registry-scanner sysdig/registry-scanner --version=1 \
--set config.secureBaseURL=<SYSDIG_SECURE_URL> \
--set config.secureAPIToken=<SYSDIG_SECURE_API_TOKEN> \
--set config.registryType=acr \
--set config.registryURL=<ACR_REGISTRY_URL> \
--set config.registryUser=<SP_ID> \
--set config.registryPassword=<SP_PASSWORD>
SYSDIG_SECURE_URLの値はご利用のSysdig SaaSリージョンにより異なります。詳細は下記ドキュメントをご参照ください。
https://docs.sysdig.com/en/docs/administration/saas-regions-and-ip-ranges
インストールログは以下のようになります。
Release "registry-scanner" does not exist. Installing it now.
NAME: registry-scanner
LAST DEPLOYED: Sun Jan 21 03:15:16 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
# ============================================================================================
# Info: Chart version 1.1.28 has been installed with Registry Scanner 0.2.63.
#
# The chart version follows SemVer (https://semver.org/), you can pin
# the chart version with --version=1, --version=1.0, --version=1.0.0, etc.
# Using --version=1 will ensure that you get the latest 1.x.x version, but
# you don't get any breaking changes when updating.
#
# For more information, or you are still using the legacy scanning engine,
# please check the documentation:
# > https://docs.sysdig.com/en/docs/installation/container-registry-scanner/
# ============================================================================================
#
# Cronjob 'registry-scanner' with schedule: "0 6 * * 6" has been created to perform a periodical scan.
# For troubleshooting, check the status of the jobs and logs of the 'registry-scanner' pods that are created on every execution.
#
下記コマンドで、Cronjobとして登録されていることを確認します。
デフォルトでは毎週土曜日の午前6時にスキャンが実行される設定で登録されています。
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
registry-scanner 0 6 * * 6 False 0 <none> 112s
レジストリスキャンの実行
1度だけ手動でレジストリスキャンを実行するにはCronjobからjobを作成します。
kubectl create job --from=cronjob/registry-scanner registry-scanner-manual
jobとして作成されたPod名を確認します。
kubectl get po
スキャンログを確認します。
$ kubectl logs registry-scanner-manual-xtsrs -f
{"level":"info","component":"main","time":"2024-01-21T03:27:38Z","message":"Starting registry-scanner version v0.2.63-2024-01-19T09:31:20Z"}
{"level":"info","component":"config","time":"2024-01-21T03:27:38Z","message":"reading config from: /config.yaml"}
{"level":"info","component":"main","time":"2024-01-21T03:27:38Z","message":"################## configuration ######################"}
{"level":"info","component":"main","time":"2024-01-21T03:27:38Z","message":"Sysdig secure config, Secure URL: https://us2.app.sysdig.com"}
{"level":"info","component":"main","time":"2024-01-21T03:27:38Z","message":"scanner config, with workers: 5"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:38Z","message":"credentials provider type: 'acr'"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:38Z","message":"using ACR credentials provider"}
{"level":"info","component":"init-newvmscanner-k8s-job","time":"2024-01-21T03:27:38Z","message":"Creating new vulnerability-management scanner (K8s job)"}
{"level":"info","component":"init-newvmscanner-k8s-job","time":"2024-01-21T03:27:38Z","message":"Scanner Options: map[disableplatformscanning:false jobs:map[resources:map[limits:map[memory:2Gi] requests:map[cpu:500m memory:500Mi]] serviceaccountname:registry-scanner temporaryvolumesizelimit:2Gi ttlsecondsafterfinished:600] k8sincluster:true labels:map[] namespace:default runner:new-vm-scanner-k8s-job securitycontext:map[] workers:5] "}
{"level":"info","component":"init-newvmscanner-k8s-job","time":"2024-01-21T03:27:39Z","message":"Backend scanning is enabled: will scan on backend"}
{"level":"info","component":"init-newvmscanner-k8s-job","time":"2024-01-21T03:27:39Z","message":"Schedule expression provided: 0 6 * * 6"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry client type: 'acr'"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"using ACR registry client"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry url: 'yoregistry.azurecr.io'"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry api: 'yoregistry.azurecr.io'"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry user: 'yoRegistryToken'"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry password: <redacted>"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"registry skip tls errors: false"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"warning, could not parse ClientPageSize value "}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"general filter, include: []"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"general filter, exclude: []"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"general filter, max age days: 90 "}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"general filter, max tags per repository: 5"}
{"level":"info","component":"factory","time":"2024-01-21T03:27:39Z","message":"general filter, max repositories per registry: 500"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:39Z","message":"############## metadata fetching phase #################"}
{"level":"info","component":"google-client","time":"2024-01-21T03:27:39Z","message":"Limiting to 500 repositories (filter.maxRepositoriesPerRegistry setting)"}
{"level":"info","component":"google-client","time":"2024-01-21T03:27:39Z","message":"discovered total number of repositories: 1"}
{"level":"info","component":"google-client","time":"2024-01-21T03:27:39Z","message":"parallelized. 1/1, getting tags concurrently from repository samples/nginx"}
{"level":"info","component":"repo-retriever-info-filler","time":"2024-01-21T03:27:40Z","message":"1 images found"}
{"level":"info","component":"repo-retriever-info-filler","time":"2024-01-21T03:27:40Z","message":"fetching found images configuration in parallel (this may take a while)"}
{"level":"info","component":"image-retriever-repos","time":"2024-01-21T03:27:41Z","message":"after filters were applied, 1 images are going to be scanned"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"metadata fetching phase finished. took 1 second 782 milliseconds 943 microseconds"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"Total images with errors in metadata phase: 0"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"After metadata phase, from 1 images, 1 will be scanned"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"################ scanning phase ######################"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"Creating registry report. Num. of workers: 5"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"Total selected images to be scanned: 1"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"progression status | 0.00% completed | completed images: 0/1 | Elapsed: 35.319µs | ETA: ?"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"progression status | processed 0/1 images (0 errors)"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"returning due to queue is closed"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"returning due to queue is closed"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"returning due to queue is closed"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:41Z","message":"returning due to queue is closed"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:51Z","message":"yoregistry.azurecr.io/samples/nginx:latest, (job registry-scanner-worker-w24t4-1) scan completed with status: success"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:51Z","message":"returning due to queue is closed"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:51Z","message":"scanning phase finished. Total selected images to be scanned: 1 = Success: 1 + Failed: 0 + Skipped: 0. took 10 seconds 557 milliseconds 276 microseconds"}
{"level":"info","component":"report-builder","time":"2024-01-21T03:27:51Z","message":"################ registry image scanning finished ######################"}
Sysdig UIでレジストスキャンのスキャン結果を確認できます。
Vulnerabilities > Registry に移動します。
まとめ
registry-scannerを使って、Azure Container Registryのレジストリスキャンを簡単に実行できることが確認できました。