# ClickBOM **Repository Path**: mirrors_ClickHouse/ClickBOM ## Basic Information - **Project Name**: ClickBOM - **Description**: Downloads SBOMs from GitHub, Mend, and Wiz. Uploads to S3 and ClickHouse. - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-12 - **Last Updated**: 2026-10-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README [![💣 ClickBOM Tests](https://github.com/ClickHouse/ClickBOM/actions/workflows/tests.yml/badge.svg)](https://github.com/ClickHouse/ClickBOM/actions/workflows/tests.yml) [![🐳 Docker Security Scan](https://github.com/ClickHouse/ClickBOM/actions/workflows/docker-security.yml/badge.svg)](https://github.com/ClickHouse/ClickBOM/actions/workflows/docker-security.yml) # ClickBOM Downloads SBOMs from GitHub, Mend, and Wiz, or generates them from container images with Trivy. Normalizes between CycloneDX and SPDX, optionally merges SBOMs stored in S3, uploads the result to S3 and ClickHouse, and can report the outcome of each run to Slack. > **Versioning.** `v1.0.x` tags are the retired bash implementation. The Go implementation is released as `v2.x` tags (`v2.0.0` and later); pin a tag, for example `ClickHouse/ClickBOM@v2.0.0`, and bump it to pick up fixes. Never pin to a feature branch — branches are deleted after merge and the workflow fails with `Unable to resolve action`. - [Inputs](#inputs) - [GitHub](#github) - [Mend](#mend) - [Wiz](#wiz) - [Trivy](#trivy) - [AWS](#aws) - [ClickHouse](#clickhouse) - [General](#general) - [Slack](#slack) - [Usage](#usage) - [Same Repository](#same-repository) - [Same Repository with ClickHouse](#same-repository-with-clickhouse) - [Same Repository with GitHub App](#same-repository-with-github-app) - [Multiple Repositories](#multiple-repositories) - [Merging SBOMs Stored In S3](#merging-sboms-stored-in-s3) - [Merging SBOMs with Include/Exclude Filters](#merging-sboms-with-includeexclude-filters) - [Downloading an SBOM from Mend](#downloading-an-sbom-from-mend) - [Downloading an SBOM from Wiz](#downloading-an-sbom-from-wiz) - [Generating an SBOM from a Container Image with Trivy](#generating-an-sbom-from-a-container-image-with-trivy) - [Posting Results to Slack](#posting-results-to-slack) - [Runtime Image](#runtime-image) - [Creating a GitHub App](#creating-a-github-app) ## Inputs ### GitHub | Name | Description | Default | Required | Sensitive | | --------------------- | ----------------------------------- | -------------- | -------- | --------- | | github-token | GitHub Token | | false | true | | repository | Repository to download SBOM from | | false | false | - `github-token` can be the built-in `${{ secrets.GITHUB_TOKEN }}` or a token generated by a GitHub App. If you use a GitHub App, see [Creating a GitHub App](#creating-a-github-app). - ClickBOM obtains the SBOM through GitHub's [asynchronous SBOM export](https://docs.github.com/en/rest/dependency-graph/sboms): it requests a report, polls until GitHub has generated it, then downloads the document. The token needs `contents: read` on the repository, and the repository must have the dependency graph enabled. Large repositories take longer to generate; ClickBOM waits up to 10 minutes per report and makes up to 3 attempts when GitHub fails transiently. GitHub is removing the older synchronous export on 2026-11-13; ClickBOM releases up to v2.0.0 use that endpoint and will stop working with `sbom-source: github` on that date, so upgrade to a newer release. ### Mend | Name | Description | Default | Required | Sensitive | | ------------------- | ------------------------------------------------------------- | ------------------------ | -------- | --------- | | mend-email | Mend user email address | | false | true | | mend-org-uuid | Mend organization UUID | | false | true | | mend-user-key | Mend user key | | false | true | | mend-base-url | Mend base URL | https://api-saas.mend.io | false | false | | mend-product-uuid | Mend product UUID for product-scoped SBOM | | false | true | | mend-project-uuid | Mend project UUID for project-scoped SBOM | | false | true | | mend-org-scope-uuid | Deprecated / no-op (Mend API 3.0 has no org-level SBOM export) | | false | true | | mend-project-uuids | Comma-separated list of specific project UUIDs to include | | false | true | | mend-max-wait-time | Maximum time to wait for Mend report generation (seconds) | 1800 | false | false | | mend-poll-interval | Polling interval for Mend report status (seconds) | 30 | false | false | - Scope precedence: if `mend-project-uuid` is set the export is project-scoped (`/api/v3.0/projects/{uuid}/dependencies/reports/SBOM`); otherwise `mend-product-uuid` gives a product-scoped export (`/api/v3.0/applications/{uuid}/dependencies/reports/SBOM`, optionally narrowed to `mend-project-uuids`). One of the two is required. - `mend-org-scope-uuid` is accepted for backward compatibility but cannot be used on its own: Mend API 3.0 offers dependency SBOM exports only at project and application (product) scope. - ClickBOM only supports downloading SBOMs from Mend in the CycloneDX v1.5 format. If you need to convert the SBOM to SPDX, you can use the `sbom-format` input. ### Wiz | Name | Description | Default | Required | Sensitive | | ----------------- | ----------------- | ------- | -------- | --------- | | wiz-auth-endpoint | Wiz Auth Endpoint | | false | true | | wiz-api-endpoint | Wiz API Endpoint | | false | true | | wiz-client-id | Wiz Client ID | | false | true | | wiz-client-secret | Wiz Client Secret | | false | true | | wiz-report-id | Wiz Report ID | | false | true | ### Trivy | Name | Description | Default | Required | Sensitive | | -------------------- | --------------------------------------------------------------------------- | --------- | -------- | --------- | | trivy-image | Container image to scan (`registry/repo:tag` or an ECR URI) | | false | false | | trivy-ecr-account-id | AWS account ID that owns the ECR repository (enables ECR auth handling) | | false | false | | trivy-ecr-region | AWS region of the ECR repository | us-east-1 | false | false | | trivy-ecr-role-arn | IAM role to assume for cross-account ECR access | | false | false | | trivy-ecr-external-id | External ID to present when assuming `trivy-ecr-role-arn` (only if its trust policy requires one) | | false | true | | trivy-format | SBOM format Trivy emits: `cyclonedx` or `spdxjson` | cyclonedx | false | false | - Images are scanned at the registry (`--image-src remote`); nothing is pulled through Docker. - For ECR images set `trivy-ecr-account-id`; when the repository lives in another account also set `trivy-ecr-role-arn` and ClickBOM assumes it via STS before invoking Trivy. ### AWS | Name | Description | Default | Required | Sensitive | | --------------------- | --------------------------------------------------------------------------- | --------- | -------- | --------- | | aws-access-key-id | AWS Access Key ID. **Deprecated — prefer OIDC** (see examples below). | | false | true | | aws-secret-access-key | AWS Secret Access Key. **Deprecated — prefer OIDC** (see examples below). | | false | true | | aws-region | AWS Region. **Deprecated — prefer OIDC** (set via configure-aws-credentials). | us-east-1 | false | false | | s3-bucket | S3 Bucket Name (always required, even when ClickHouse output is the goal) | | true | false | | s3-key | S3 object key of the uploaded SBOM (in merge mode: the merged output object) | sbom.json | false | false | - It is recommended that an S3 bucket be created for the purposes of ClickBOM. - The `aws-*` inputs are kept for backward compatibility with the bash version of this action. The recommended path is to use [`aws-actions/configure-aws-credentials`](https://github.com/aws-actions/configure-aws-credentials) with GitHub OIDC; that action exports `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_SESSION_TOKEN` / `AWS_REGION` as job-level env vars, and the Actions runner passes job env through to the ClickBOM container unchanged, so nothing needs to be passed as an input. (Do not pass `steps..outputs.aws-access-key-id`: those outputs are empty unless `output-credentials: true` is set.) - The bucket does not have to be in the job's `aws-region`. ClickBOM resolves each bucket's home region up front (via `HeadBucket`'s `x-amz-bucket-region` header) and talks to the right regional endpoint, so a mismatch no longer fails with `301 PermanentRedirect`. - Setting `AWS_ENDPOINT_URL` (e.g. to RustFS, MinIO or another S3-compatible store) switches the client to path-style addressing and disables region discovery. ### ClickHouse | Name | Description | Default | Required | Sensitive | | ------------------- | ----------------------------------- | -------------- | -------- | --------- | | clickhouse-url | ClickHouse URL | | false | true | | clickhouse-database | ClickHouse Database Name | default | false | false | | clickhouse-username | ClickHouse Username | default | false | false | | clickhouse-password | ClickHouse Password | (empty) | false | true | | truncate-table | Truncate table before insert | false | false | false | - At the moment, ClickHouse ingestion is only supported over HTTP. ### General | Name | Description | Default | Required | Sensitive | | ----------- | --------------------------------------------------------------------- | --------- | -------- | --------- | | sbom-source | Source of SBOM (github, mend, wiz, trivy) | github | false | false | | sbom-format | SBOM format (spdxjson or cyclonedx) | cyclonedx | false | false | | merge | Merge SBOMs stored in S3 | false | false | false | | include | Comma-separated list of filenames or patterns to include when merging | (empty) | false | false | | exclude | Comma-separated list of filenames or patterns to exclude when merging | (empty) | false | false | | debug | Enable debug logging | false | false | false | - `sbom-format` specifies the format you want the final SBOM to be in. For example, GitHub only supports SPDX, settings this input to `cyclonedx` will convert the SBOM to CycloneDX format. - `include` and `exclude` are only used when `merge` is set to `true`. They allow you to filter which files from the S3 bucket should be included in the merge operation. - Both `include` and `exclude` support exact filename matching and wildcard patterns (e.g., `file*.json`, `*-prod.json`). - If `include` is specified, only files matching the include patterns will be processed. - If `exclude` is specified, files matching the exclude patterns will be skipped. - `exclude` is applied after `include`, so a file that matches **both** an include and exclude pattern will be *excluded*. ### Slack | Name | Description | Default | Required | Sensitive | | ----------------- | ------------------------------------------------------------------------------------ | ------------------------- | -------- | --------- | | slack-webhook-url | Slack incoming webhook that receives one success or failure message per run | | false | true | | slack-notify-on | Which outcomes to post: `always` (every run) or `failure` (failed runs only) | `always` | false | false | | job-check-run-id | Id of the running job, used only to link the message to the job. Leave the default. | `${{ job.check_run_id }}` | false | false | - When set, ClickBOM posts one message per run to whichever Slack workspace owns the webhook: whether the run succeeded or failed, the repository, workflow, job and step that ran it, what triggered it (event, branch, short commit, actor), the SBOM source, the S3 object written, the ClickHouse database and table when configured, the duration, and a link. On failure the first line of the error is included. - `slack-notify-on: failure` posts failed runs only, for channels where one message per successful run is too noisy. A run that fails configuration validation is still posted, as long as the webhook itself is valid. The value is case-insensitive; anything other than `always` or `failure` is rejected at start-up. - The link opens the job itself. `job.check_run_id` is evaluated as the default of `job-check-run-id` and handed to the container, so no workflow change is needed; it also tells matrix legs apart, which share a job key. On a GitHub Enterprise Server release without `job.check_run_id` the value is empty and the link opens the workflow run instead (the specific attempt when re-run). - **Job** is the job's key in the workflow file (`GITHUB_JOB`), not its `name:`. **Step** is the step's `id:` (`GITHUB_ACTION`); give the ClickBOM step an `id` for a readable label, otherwise GitHub generates one such as `__ClickHouse_ClickBOM`. - Only Slack *incoming webhook* URLs are accepted: `https://hooks.slack.com/services/...` (or `hooks.slack-gov.com` for GovSlack). Workflow Builder webhook triggers (`/triggers/...`, `/workflows/...`) are rejected at start-up because they only take flat key/value payloads. The URL is a credential: pass it from a secret. ClickBOM never logs it, and a rejected value is not echoed in the error. - Nothing marked Sensitive in this document reaches Slack. For Mend and Wiz the message names the scope (`project scope`, `product scope`, `report`) rather than the identifier and omits the ClickHouse table name, which embeds that identifier. The error text is redacted before posting: URL query strings and credentials are removed, every Sensitive input value (including the table-name spelling of Mend and Wiz identifiers), bearer and basic-auth headers, socket addresses, AWS access key ids and GitHub tokens are replaced with `***`, and only the first line is sent. - Notification failures are logged as warnings and never change the outcome of the job; delivery is bounded to about two minutes (three attempts). A run that fails configuration validation is reported too, as long as the webhook itself is valid. A retry after a timed-out delivery can produce a duplicate message. - `slack-webhook-url` and `job-check-run-id` first ship in `v2.1.0` and `slack-notify-on` in `v2.2.0`; consumers pinned to an older tag need a ref bump to use them. ## Usage ### Same Repository Simple example of downloading the SBOM from the same repository and uploading it to S3. Converts the SBOM to CycloneDX format. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ secrets.GITHUB_TOKEN }} s3-bucket: my-sbom-bucket s3-key: clickbom.json repository: ${{ github.repository }} ``` ### Same Repository with ClickHouse Downloads the SBOM from the same repository and uploads it to S3. Converts the SBOM to CycloneDX format. Also uploads the SBOM to ClickHouse. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ secrets.GITHUB_TOKEN }} s3-bucket: my-sbom-bucket s3-key: clickbom.json repository: ${{ github.repository }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Same Repository with GitHub App Downloads the SBOM from the same repository and uploads it to S3. Keeps the SBOM in SPDX format. Authenticates using a GitHub App. See [Creating a GitHub App](#creating-a-github-app). ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Generate Token id: generate-token uses: actions/create-github-app-token@v3 with: app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }} private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }} - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ steps.generate-token.outputs.token }} sbom-format: spdxjson s3-bucket: my-sbom-bucket s3-key: clickbom.json repository: ${{ github.repository }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Multiple Repositories Downloads SBOMs from multiple repositories (must have GitHub App installed), Converts SBOMs to CycloneDX format, and uploads them to S3 and ClickHouse. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: strategy: fail-fast: false matrix: repository: [ "repository-one", "repository-two", "repository-three" ] name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Generate Token id: generate-token uses: actions/create-github-app-token@v3 with: app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }} private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: ${{ matrix.repository }} - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ steps.generate-token.outputs.token }} s3-bucket: my-sbom-bucket s3-key: ${{ matrix.repository }}.json repository: ${{ github.repository_owner }}/${{ matrix.repository }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Merging SBOMs Stored In S3 This example adds to the previous one by merging SBOMs stored in S3. It downloads the SBOMs from S3, merges them, and uploads the merged SBOM back to S3 and ClickHouse. Only the CycloneDX format is supported for merging. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: strategy: fail-fast: false matrix: repository: [ "repository-one", "repository-two", "repository-three" ] name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Generate Token id: generate-token uses: actions/create-github-app-token@v3 with: app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }} private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }} owner: ${{ github.repository_owner }} repositories: ${{ matrix.repository }} - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ steps.generate-token.outputs.token }} s3-bucket: my-sbom-bucket s3-key: ${{ matrix.repository }}.json repository: ${{ github.repository_owner }}/${{ matrix.repository }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} clickbom_merge: needs: clickbom name: ClickBOM Merge runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Generate Token id: generate-token uses: actions/create-github-app-token@v3 with: app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }} private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }} - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM uses: ClickHouse/ClickBOM@main with: github-token: ${{ steps.generate-token.outputs.token }} s3-bucket: my-sbom-bucket s3-key: clickbom.json clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} merge: true ``` ### Merging SBOMs with Include/Exclude Filters This example shows how to use the `include` and `exclude` filters when merging SBOMs. This is useful when you want to merge only specific files from your S3 bucket. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom_merge: name: ClickBOM Merge with Filters runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Generate Token id: generate-token uses: actions/create-github-app-token@v3 with: app-id: ${{ secrets.CLICKBOM_AUTH_APP_ID }} private-key: ${{ secrets.CLICKBOM_AUTH_PRIVATE_KEY }} - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Merge Production SBOMs Only uses: ClickHouse/ClickBOM@main with: github-token: ${{ steps.generate-token.outputs.token }} s3-bucket: my-sbom-bucket s3-key: production-merged.json clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} merge: true include: "*-prod.json,production-*.json" exclude: "*-test.json,*-dev.json" ``` In this example: - `include: "*-prod.json,production-*.json"` will only process files that match these patterns - `exclude: "*-test.json,*-dev.json"` will skip any files that match these patterns - The result is that only production-related SBOMs will be merged, excluding test and development SBOMs ### Downloading an SBOM from Mend If you want to download an SBOM from Mend, you can use the following example. This example assumes you have the necessary Mend credentials set up in your GitHub Secrets. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM from Mend uses: ClickHouse/ClickBOM@main with: s3-bucket: my-sbom-bucket s3-key: clickbom.json sbom-source: mend mend-email: ${{ secrets.CLICKBOM_MEND_EMAIL }} mend-org-uuid: ${{ secrets.CLICKBOM_MEND_ORG_UUID }} mend-user-key: ${{ secrets.CLICKBOM_MEND_USER_KEY }} mend-product-uuid: ${{ secrets.CLICKBOM_MEND_PRODUCT_UUID }} mend-project-uuid: ${{ secrets.CLICKBOM_MEND_PROJECT_UUID }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Downloading an SBOM from Wiz If you want to download an SBOM from Wiz, you can use the following example. This example assumes you have the necessary Wiz credentials set up in your GitHub Secrets. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout repository uses: actions/checkout@v6 - name: Configure AWS Credentials id: aws-creds uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM from Wiz uses: ClickHouse/ClickBOM@main with: s3-bucket: my-sbom-bucket s3-key: clickbom.json sbom-source: wiz wiz-auth-endpoint: ${{ secrets.CLICKBOM_WIZ_AUTH_ENDPOINT }} wiz-api-endpoint: ${{ secrets.CLICKBOM_WIZ_API_ENDPOINT }} wiz-client-id: ${{ secrets.CLICKBOM_WIZ_CLIENT_ID }} wiz-client-secret: ${{ secrets.CLICKBOM_WIZ_CLIENT_SECRET }} wiz-report-id: ${{ secrets.CLICKBOM_WIZ_REPORT_ID }} clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Generating an SBOM from a Container Image with Trivy Scans an image in a (possibly cross-account) ECR repository with Trivy, uploads the CycloneDX SBOM to S3 and ClickHouse. The job's OIDC role must be allowed to assume `trivy-ecr-role-arn`. ```yaml name: Upload SBOM on: push: branches: - main jobs: clickbom: name: ClickBOM runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole role-session-name: clickbom-session aws-region: us-east-1 - name: Upload SBOM from Container Image uses: ClickHouse/ClickBOM@main with: s3-bucket: my-sbom-bucket s3-key: clickhouse-keeper.json sbom-source: trivy trivy-image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/clickhouse-keeper:25.2.1.30176 trivy-ecr-account-id: "123456789012" trivy-ecr-region: us-east-1 trivy-ecr-role-arn: arn:aws:iam::123456789012:role/ECRPullRole trivy-format: cyclonedx clickhouse-url: ${{ secrets.CLICKHOUSE_URL }} clickhouse-database: ${{ secrets.CLICKHOUSE_DATABASE }} clickhouse-username: ${{ secrets.CLICKHOUSE_USERNAME }} clickhouse-password: ${{ secrets.CLICKHOUSE_PASSWORD }} ``` ### Posting Results to Slack Any of the examples above can report to Slack by adding `slack-webhook-url`. Create an [incoming webhook](https://api.slack.com/messaging/webhooks) for the channel that should receive the messages, store its URL as a repository or organization secret, and pass it in: ```yaml - name: Upload SBOM id: clickbom uses: ClickHouse/ClickBOM@main with: github-token: ${{ secrets.GITHUB_TOKEN }} s3-bucket: my-sbom-bucket s3-key: clickbom.json repository: ${{ github.repository }} slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} ``` Each run posts one message, for example: > :white_check_mark: **ClickBOM succeeded** in my-org/my-repo · Upload SBOM #42 *(links to the job)* > > **Workflow** Upload SBOM · **Job** clickbom · **Step** clickbom · **Trigger** push on main @ 0123456 by octocat · **Source** github · my-org/my-repo · **Output** s3://my-sbom-bucket/clickbom.json (cyclonedx) · **Duration** 1m23s A failed run is posted the same way, in red, with the first line of the error, so a matrix of many ClickBOM jobs can share one channel. If one message per successful run is too noisy, add `slack-notify-on: failure` next to the webhook and only failed runs are posted: ```yaml slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }} slack-notify-on: failure ``` ## Runtime Image The action runs as a Docker container built from this repository's `Dockerfile`: a static Go binary plus two external tools, `cyclonedx` (format conversion) and `trivy` (image scanning), on `gcr.io/distroless/cc-debian13:nonroot`. The `cc` variant is required because `cyclonedx-cli` is a dynamically linked .NET application; on `distroless/static` it cannot execute at all. CI builds the image and runs a conversion inside it on every push. ## Creating a GitHub App - Follow the instructions [here](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) to create a GitHub App. - Make sure to give the app `Read access` to `Contents` and `Metadata`. - Install the app on the repositories you want to use it with. - Generate a private key for the app and save it somewhere secure, i.e. GitHub Secrets.