DuckDBを用いたAWS Inspector生成SBOMの分析例

## **導入**

- 本記事は[Japan AWS Ambassadors Advent Calendar 2024](https://qiita.com/advent-calendar/2024/japan-aws-ambassador)向けに執筆しています。
- [Japan AWS Top Engineers Advent Calendar 2024](https://qiita.com/advent-calendar/2024/aws-top-engineers)にも[AWS環境でのBFFパターンによるセキュアな認証認可の実装例](https://zenn.dev/acntechjp/articles/585749b7b0b8d9)を投稿しているので、良ければご覧になってください。

### **背景・目的**

- 最近TLでよく見かけるDuckDBが気になったので、キャッチアップを兼ねて遊んでみます。
- Inspectorで生成したCycloneDX形式のSBOMファイルをDuckDBで分析してみます。

### **環境構成**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562653/2a4b0402-c9a1-3857-065a-1b967766171d.png)

## **DuckDB概要**

- DuckDBとはOSSの列志向RDBMSです。
- SQLiteのように組み込み構成であり、オンライン分析処理(OLAP)向けに設計されています。
- S3上のデータをロードして分析することもできます。

## **InspectorでのSBOM生成機能概要**

- InspectorとはAWSの脆弱性管理サービスです。
- サービスの一機能として、SBOM生成機能を具備しています。
    - SBOM生成対象サービスはECR、Lambda、EC2です。
    - CycloneDX若しくはSPDX2.3形式で生成されたSBOMファイルはS3に配置されます。(本記事ではCycloneDX形式で生成します。)
- CycloneDX形式のSBOMファイルは、コンポーネントや脆弱性情報等を内包しています。

以下、[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/inspector/latest/user/sbom-export.html#sbom-formats) よりサンプルを抜粋
<details>

```json
{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-06-02T01:17:46Z",
    "component": null,
    "properties": [
      {
        "name": "imageId",
        "value": "sha256:c8ee97f7052776ef223080741f61fcdf6a3a9107810ea9649f904aa4269fdac6"
      },
      {
        "name": "architecture",
        "value": "arm64"
      },
      {
        "name": "accountId",
        "value": "111122223333"
      },
      {
        "name": "resourceType",
        "value": "AWS_ECR_CONTAINER_IMAGE"
      }
    ]
  },
  "components": [
    {
      "type": "library",
      "name": "pip",
      "purl": "pkg:pypi/pip@22.0.4?path=usr/local/lib/python3.8/site-packages/pip-22.0.4.dist-info/METADATA",
      "bom-ref": "98dc550d1e9a0b24161daaa0d535c699"
    },
    {
      "type": "application",
      "name": "libss2",
      "purl": "pkg:dpkg/libss2@1.44.5-1+deb10u3?arch=ARM64&epoch=0&upstream=libss2-1.44.5-1+deb10u3.src.dpkg",
      "bom-ref": "2f4d199d4ef9e2ae639b4f8d04a813a2"
    },
    {
      "type": "application",
      "name": "liblz4-1",
      "purl": "pkg:dpkg/liblz4-1@1.8.3-1+deb10u1?arch=ARM64&epoch=0&upstream=liblz4-1-1.8.3-1+deb10u1.src.dpkg",
      "bom-ref": "9a6be8907ead891b070e60f5a7b7aa9a"
    },
    {
      "type": "application",
      "name": "mawk",
      "purl": "pkg:dpkg/mawk@1.3.3-17+b3?arch=ARM64&epoch=0&upstream=mawk-1.3.3-17+b3.src.dpkg",
      "bom-ref": "c2015852a729f97fde924e62a16f78a5"
    },
    {
      "type": "application",
      "name": "libgmp10",
      "purl": "pkg:dpkg/libgmp10@6.1.2+dfsg-4+deb10u1?arch=ARM64&epoch=2&upstream=libgmp10-6.1.2+dfsg-4+deb10u1.src.dpkg",
      "bom-ref": "52907290f5beef00dff8da77901b1085"
    },
    {
      "type": "application",
      "name": "ncurses-bin",
      "purl": "pkg:dpkg/ncurses-bin@6.1+20181013-2+deb10u3?arch=ARM64&epoch=0&upstream=ncurses-bin-6.1+20181013-2+deb10u3.src.dpkg",
      "bom-ref": "cd20cfb9ebeeadba3809764376f43bce"
    }
  ],
  "vulnerabilities": [
    {
      "id": "CVE-2022-40897",
      "affects": [
        {
          "ref": "a74a4862cc654a2520ec56da0c81cdb3"
        },
        {
          "ref": "0119eb286405d780dc437e7dbf2f9d9d"
        }
      ]
    }
  ]
}        
```
</details>

## **実際に動かしてみた**

### **[再掲]環境構成**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562653/e13f70c0-ac20-f740-adda-0c04f83613d8.png)

- InspectorコマンドやDuckDBクエリはCloudShell上で実行します。
- また、SBOM生成対象となるECRには事前に`python:3.9-slim`イメージを格納しておきます。

### **InspectorでSBOM生成**

- CloudShellを起動し、SBOM生成用コマンドを実行します。

```bash
aws inspector2 create-sbom-export --report-format CYCLONEDX_1_4 \
  --resource-filter-criteria 'ecrRepositoryName=[{comparison="EQUALS",value="base-python"}]' \
  --s3-destination bucketName=xxx,keyPrefix=xxx,kmsKeyArn=arn:aws:kms:ap-northeast-1:xxx:key/xxx
```

- コマンド実行後しばらく経つと、S3にCycloneDX形式のSBOMファイルが配置されていることが確認できます。

### **DuckDBでS3上のSBOMファイル分析**

上述のSBOMファイルを対象に、DuckDBで分析してみます。

まずは、DuckDBをインストールして起動します。

```bash
# Install and Run DuckDB
wget https://github.com/duckdb/duckdb/releases/download/v1.1.3/duckdb_cli-linux-amd64.zip && unzip duckdb_cli-linux-amd64.zip && ./duckdb
```

クレデンシャル設定した上で、S3上のSBOMをテーブルにインポートします。

今回は、デフォルトの認証情報プロバイダチェーンを利用します。

```sql
-- Create Config
CREATE SECRET secret (
    TYPE S3,
    PROVIDER CREDENTIAL_CHAIN
);

-- Import SBOM Json file from S3
CREATE TABLE
  sbom_data AS
SELECT
  *
FROM
  read_json ('s3://xxx.json');
```

無事インポートできたので、クエリ実行してみます。

配列となっている`components`や`vulnerabilities`をUNNESTしているのがポイントです。

また、一時的な分析用のためテンポラリテーブルを作成しています。

```sql
-- List Components
CREATE TEMP TABLE
  components AS (
    SELECT
      component.*
    FROM
      (
        SELECT
          UNNEST (sbom_data.components) AS component
        FROM
          sbom_data
      )
  );
SELECT
  *
FROM
  components;

-- List Vulnerabilities
CREATE TEMP TABLE
  vulnerabilities AS (
    SELECT
      vulnerability.id AS cve,
      UNNEST (vulnerability.affects).ref AS ref
    FROM
      (
        SELECT
          UNNEST (sbom_data.vulnerabilities) AS vulnerability
        FROM
          sbom_data
      )
  );
SELECT
  *
FROM
  vulnerabilities;

-- JOIN components and vulnerabilities
SELECT
  *
FROM
  components
  INNER JOIN vulnerabilities ON components."bom-ref" = vulnerabilities.ref;
```

クエリを実行すると、期待した結果表示を確認できました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562653/b66089c7-d48d-1516-e661-874706164dda.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562653/4dc9a41a-b453-13d8-ab62-dbfe9cc8eb1e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562653/9bf39657-6cc1-5d4c-ce17-180c2080ce6a.png)

## 参考

https://duckdb.org/docs/extensions/httpfs/s3api.html

https://duckdb.org/docs/sql/query_syntax/unnest.html

https://docs.aws.amazon.com/cli/latest/reference/inspector2/create-sbom-export.html

https://docs.aws.amazon.com/ja_jp/inspector/latest/user/sbom-export.html
## 注意事項
- 本記事は万全を期して作成していますが、お気づきの点がありましたら、ご連絡よろしくお願いします。
- なお、本記事の内容を利用した結果及び影響について、筆者は一切の責任を負いませんので、予めご了承ください。