Sysdig Secureのレジストリスキャンを試してみた（JFrog Artifactory SaaS/Cloud編）

先日、Sysdig SecureのレジストリスキャンがGAになったので、さっそく試しみてみました。今回はJFrog Artifactory SaaS/Cloudに対するレジストリスキャンの手順をご紹介します。

:::note
JFrog Artifactoryのネーミングは業界の標準とは異なり、「レジストリ」の代わりに「リポジトリ」、「リポジトリ」の代わりに「パッケージ」と命名されています。
:::

# 参照ドキュメント
https://docs.sysdig.com/en/docs/sysdig-secure/vulnerabilities/registry/

https://docs.sysdig.com/en/docs/installation/container-registry-scanner/

# 前提条件
レジストリスキャンを実施するregistry-scannerはKubernetes上でコンテナとして動作します。そのため、__Kubernetes環境が必要__ です。

# JFrog Artifactory環境の準備
JFrog Artifactoryにログインし、nginxイメージをプッシュします。
```
ubuntu@ip-172-31-33-129:~$ docker login -u <USER_NAME> bobo3977.jfrog.io
Password:
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

ubuntu@ip-172-31-33-129:~$ docker pull nginx
ubuntu@ip-172-31-33-129:~$ docker tag nginx bobo3977.jfrog.io/docker/hello-world:1.1.0
ubuntu@ip-172-31-33-129:~$ docker push bobo3977.jfrog.io/docker/hello-world:1.1.0	
```

# Helmによるregistry-scannerのインストール
https://charts.sysdig.com/charts/registry-scanner/

以下のコマンドでregistry-scannerをKubernetes環境にインストールします。

:::note 
SYSDIG_SECURE_URLの値はご利用のSysdig SaaSリージョンにより異なります。下記ドキュメントをご参照ください。
https://docs.sysdig.com/en/docs/administration/saas-regions-and-ip-ranges/
:::

```
helm repo add sysdig https://charts.sysdig.com
helm repo update
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=artifactory \
--set config.registryURL=<JFROG_ARTIFACTORY_REGISTRY_URL> \
--set config.registryApiUrl=<JFROG_ARTIFACTORY_REGISTRY_API_DOCKER_URL> \
--set config.registryUser=<JFROG_ARTIFACTORY_USER> \
--set config.registryPassword=<JFROG_ARTIFACTORY_PASSWORD>
```
私の環境だと以下になります。
```
helm upgrade --install registry-scanner sysdig/registry-scanner --version=1 \
--set config.secureBaseURL=https://app.us4.sysdig.com \
--set config.secureAPIToken=XXXXXXXXXXXXXX \
--set config.registryType=artifactory \
--set config.registryURL=bobo3977.jfrog.io/docker \
--set config.registryApiUrl=bobo3977.jfrog.io/artifactory/api/docker/docker \
--set config.registryUser=XXXXXXXX@gmail.com \
--set config.registryPassword=XXXXXXXXXXXXXX
```
```:Helmのインストールログ
Release "registry-scanner" does not exist. Installing it now.
NAME: registry-scanner
LAST DEPLOYED: Tue Feb 14 14:07:18 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
A cronjob 'registry-scanner' has been created. The cronjob will execute the registry scan on the following schedule:

Schedule: "0 6 * * 6"

For troubleshooting, check the status of the jobs and logs of the 'registry-scanner' pods that are created on every execution.
```
下記コマンドで、Cronjobとして登録されていることを確認します。
```
kubectl get cronjob
```
デフォルトでは毎週土曜日の午前6時にスキャンが実行される設定で登録されています。
```
NAME               SCHEDULE    SUSPEND   ACTIVE   LAST SCHEDULE   AGE
registry-scanner   0 6 * * 6   False     0        <none>          88s
```

# 手動によるレジストリスキャン
レジストリスキャンを手動で実行する場合は、下記コマンドを実行します。
```
kubectl create job --from=cronjob/registry-scanner registry-scanner-manual-test
```
起動したregistry-scannerのPodを確認します。
```
kubectl get pod
```
```
NAME                                    READY   STATUS      RESTARTS   AGE
registry-scanner-manual-test-rb87p      0/1     Completed   0          41s
registry-scanner-worker-dd42x-1-mk8gj   0/1     Completed   0          33s
```
Podのログを確認します。
```
kubectl logs registry-scanner-manual-test-s2xhz
```
```: registry-scanner Podのログ
ubuntu@ip-172-31-33-129:~$ k logs registry-scanner-manual-test-rb87p
Reading config from: /config.yaml
["2023-02-14T14:25:39.143" MSG] Registry type: artifactory
["2023-02-14T14:25:39.144" MSG] Creating new vulnerability-management scanner
["2023-02-14T14:25:39.490" MSG] WARN: maxTagsPerRepository: 0 is higher than maximum allowed retention. Setting to 5

["2023-02-14T14:25:39.490" MSG] Using filter:
  Include: []
  Exclude: []
  Max age days: 0
  Max tags per repository: 5

["2023-02-14T14:25:39.490" MSG] Getting repositories...
["2023-02-14T14:25:39.686" MSG] Getting tags concurrently from repository (2/2) library/hello-world...
["2023-02-14T14:25:39.686" MSG] Getting tags concurrently from repository (1/2) hello-world...
["2023-02-14T14:25:39.830" MSG] Retrieving image information (4/4): hello-world:1.1.0...
["2023-02-14T14:25:39.830" MSG] Retrieving image information (2/4): library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4...
["2023-02-14T14:25:39.830" MSG] Retrieving image information (3/4): hello-world:1.0.0...
["2023-02-14T14:25:39.830" MSG] Retrieving image information (1/4): library/hello-world:latest...
["2023-02-14T14:25:39.896" ERROR] {bobo3977.jfrog.io/docker library/hello-world latest} - Get image config error
Unexpected response code from RetrieveArtifact endpoint: 404
{
  "errors" : [ {
    "status" : 404,
    "message" : "Could not find resource"
  } ]
}
["2023-02-14T14:25:39.902" MSG] Image ID: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412 created 2021-09-23 23:47:57.442225064 +0000 UTC
["2023-02-14T14:25:39.929" MSG] Image ID: sha256:3f8a00f137a0d2c8a2163a09901e28e2471999fde4efc2f9570b91f1c30acf94 created 2023-02-09 04:36:22.393029904 +0000 UTC
["2023-02-14T14:25:39.942" MSG] Image ID: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412 created 2021-09-23 23:47:57.442225064 +0000 UTC
["2023-02-14T14:25:39.942" MSG] Creating registry report. Num. of workers: 1
["2023-02-14T14:25:39.942" MSG] Starting round 1. Pending images: 3
["2023-02-14T14:25:39.942" MSG] 0.00% completed. Completed images: 0/4 . Elapsed: 16.552µs ETA: ?
["2023-02-14T14:25:39.942" MSG] Round 1: Processed 0/3 images (0 errors)
["2023-02-14T14:25:39.943" MSG] Processing image bobo3977.jfrog.io/docker/hello-world:1.1.0. Retries: 0
["2023-02-14T14:25:39.943" MSG] bobo3977.jfrog.io/docker/hello-world:1.1.0 - Checking status...
["2023-02-14T14:25:39.943" MSG] bobo3977.jfrog.io/docker/hello-world:1.1.0 - Scanning...
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:39Z","message":"Getting image bobo3977.jfrog.io/docker/hello-world:1.1.0"}
{"level":"info","component":"vuln-db-downloader","time":"2023-02-14T14:25:44Z","message":"downloading vulnerability database"}
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:45Z","message":"Matching vulnerabilities"}
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:45Z","message":"image bobo3977.jfrog.io/docker/hello-world:1.1.0 scanned in 5.99078168s"}
["2023-02-14T14:25:46.398" MSG] bobo3977.jfrog.io/docker/hello-world:1.1.0 - Scan completed: noPolicy
["2023-02-14T14:25:46.398" MSG] 25.00% completed. Completed images: 1/4 . Elapsed: 6.455118293s ETA: 19.365s
["2023-02-14T14:25:46.398" MSG] Round 1: Processed 1/3 images (0 errors)
["2023-02-14T14:25:46.398" MSG] Processing image bobo3977.jfrog.io/docker/hello-world:1.0.0. Retries: 0
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"Getting image bobo3977.jfrog.io/docker/hello-world:1.0.0"}
["2023-02-14T14:25:46.398" MSG] bobo3977.jfrog.io/docker/hello-world:1.0.0 - Checking status...
["2023-02-14T14:25:46.398" MSG] bobo3977.jfrog.io/docker/hello-world:1.0.0 - Scanning...
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"Matching vulnerabilities"}
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"image bobo3977.jfrog.io/docker/hello-world:1.0.0 scanned in 85.884142ms"}
["2023-02-14T14:25:46.587" MSG] bobo3977.jfrog.io/docker/hello-world:1.0.0 - Scan completed: noPolicy
["2023-02-14T14:25:46.587" MSG] 50.00% completed. Completed images: 2/4 . Elapsed: 6.644958633s ETA: 6.644s
["2023-02-14T14:25:46.587" MSG] Round 1: Processed 2/3 images (0 errors)
["2023-02-14T14:25:46.587" MSG] Processing image bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4. Retries: 0
["2023-02-14T14:25:46.587" MSG] bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 - Checking status...
["2023-02-14T14:25:46.587" MSG] bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 - Scanning...
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"Getting image bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4"}
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"Matching vulnerabilities"}
{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"image bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 scanned in 90.751024ms"}
["2023-02-14T14:25:46.780" MSG] bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 - Scan completed: noPolicy
["2023-02-14T14:25:46.780" MSG] 75.00% completed. Completed images: 3/4 . Elapsed: 6.837135235s ETA: 2.279s
["2023-02-14T14:25:46.780" MSG] Round 1: Processed 3/3 images (0 errors)
["2023-02-14T14:25:46.780" MSG] Finished round 1. Processed: 3. Failed: 0.
["2023-02-14T14:25:46.780" MSG] Scan report:
{
  "Status": "finished",
  "Error": "",
  "Registry": "bobo3977.jfrog.io/docker",
  "Started": "2023-02-14T14:25:39.490916221Z",
  "LastUpdate": "2023-02-14T14:25:46.780105099Z",
  "Finished": "2023-02-14T14:25:46.780105099Z",
  "Images": {
    "bobo3977.jfrog.io/docker/hello-world:1.0.0": {
      "Registry": "bobo3977.jfrog.io/docker",
      "Repository": "hello-world",
      "Tag": "1.0.0",
      "ImageID": "sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412",
      "Created": "2021-09-23T23:47:57.442225064Z",
      "TagNumberInRepo": 1,
      "FullTag": "bobo3977.jfrog.io/docker/hello-world:1.0.0",
      "ScanStatus": "noPolicy",
      "Policies": null,
      "ReportURL": "https://app.us4.sysdig.com/secure/#/scanning/scan-results/bobo3977.jfrog.io%2Fdocker%2Fhello-world%3A1.0.0/id/feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412/summaries",
      "LastErrorMessage": "",
      "NumberOfRetries": 0,
      "StatusChecked": null,
      "StatusRetrieved": null,
      "ScanStarted": "2023-02-14T14:25:46.398076157Z",
      "ScanFinished": "2023-02-14T14:25:46.587879649Z"
    },
    "bobo3977.jfrog.io/docker/hello-world:1.1.0": {
      "Registry": "bobo3977.jfrog.io/docker",
      "Repository": "hello-world",
      "Tag": "1.1.0",
      "ImageID": "sha256:3f8a00f137a0d2c8a2163a09901e28e2471999fde4efc2f9570b91f1c30acf94",
      "Created": "2023-02-09T04:36:22.393029904Z",
      "TagNumberInRepo": 0,
      "FullTag": "bobo3977.jfrog.io/docker/hello-world:1.1.0",
      "ScanStatus": "noPolicy",
      "Policies": null,
      "ReportURL": "https://app.us4.sysdig.com/secure/#/scanning/scan-results/bobo3977.jfrog.io%2Fdocker%2Fhello-world%3A1.1.0/id/3f8a00f137a0d2c8a2163a09901e28e2471999fde4efc2f9570b91f1c30acf94/summaries",
      "LastErrorMessage": "",
      "NumberOfRetries": 0,
      "StatusChecked": null,
      "StatusRetrieved": null,
      "ScanStarted": "2023-02-14T14:25:39.943023777Z",
      "ScanFinished": "2023-02-14T14:25:46.398036775Z"
    },
    "bobo3977.jfrog.io/docker/library/hello-world:latest": {
      "Registry": "bobo3977.jfrog.io/docker",
      "Repository": "library/hello-world",
      "Tag": "latest",
      "ImageID": "",
      "Created": "0001-01-01T00:00:00Z",
      "TagNumberInRepo": 1,
      "FullTag": "bobo3977.jfrog.io/docker/library/hello-world:latest",
      "ScanStatus": "",
      "Policies": null,
      "ReportURL": "",
      "LastErrorMessage": "Unexpected response code from RetrieveArtifact endpoint: 404\n{\n  \"errors\" : [ {\n    \"status\" : 404,\n    \"message\" : \"Could not find resource\"\n  } ]\n}",
      "NumberOfRetries": 0,
      "StatusChecked": null,
      "StatusRetrieved": null,
      "ScanStarted": null,
      "ScanFinished": null
    },
    "bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4": {
      "Registry": "bobo3977.jfrog.io/docker",
      "Repository": "library/hello-world",
      "Tag": "sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4",
      "ImageID": "sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412",
      "Created": "2021-09-23T23:47:57.442225064Z",
      "TagNumberInRepo": 0,
      "FullTag": "bobo3977.jfrog.io/docker/library/hello-world:sha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4",
      "ScanStatus": "noPolicy",
      "Policies": null,
      "ReportURL": "https://app.us4.sysdig.com/secure/#/scanning/scan-results/bobo3977.jfrog.io%2Fdocker%2Flibrary%2Fhello-world%3Asha256__f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4/id/feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412/summaries",
      "LastErrorMessage": "",
      "NumberOfRetries": 0,
      "StatusChecked": null,
      "StatusRetrieved": null,
      "ScanStarted": "2023-02-14T14:25:46.587917743Z",
      "ScanFinished": "2023-02-14T14:25:46.780064276Z"
    }
  }
}

{"level":"info","component":"image-scanner","time":"2023-02-14T14:25:46Z","message":"Closing image analyzer DB"}
```

# スキャン結果のSysdig UIでの確認
Sysdig UIにログインし、<b>Vulnerabilities > Registry</b> に移動します。
レジストリ内のイメージのスキャン結果が表示されていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2802821/b1c0005f-3b5f-66f5-efc5-d74fb8bc63a5.png)

# クリーンアップ
registry-scannerをアンインストールするには以下のコマンドを実行します。
```
kubectl delete job registry-scanner-manual-test
```
```
sudo helm uninstall registry-scanner
```

# まとめ
registry-scannerを使って、JFrog Artifactory SaaS/Cloudのレジストリスキャンを簡単に実行できることが確認できました。