diff --git a/.github/workflows/cve-scan.yml b/.github/workflows/cve-scan.yml new file mode 100644 index 000000000000..a255104013d2 --- /dev/null +++ b/.github/workflows/cve-scan.yml @@ -0,0 +1,168 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +name: "CVE Scan" +on: + push: + branches: + - 'main' + - '0.*' + - '1.*' + - '2.*' + tags: + - 'apache-iceberg-**' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +jobs: + + # ------------------------------------------------------------------ + # Trivy CVE scan — scans bundled jars for known vulnerabilities. + # + # Runs on push to main/release branches only (not PRs). Results are + # uploaded as SARIF to the GitHub Security tab for ongoing tracking. + # The scan is informational and does not block the build. + # ------------------------------------------------------------------ + cve-scan: + runs-on: ubuntu-24.04 + permissions: + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + include: + - distribution: kafka-connect-runtime + build-task: >- + -DkafkaVersions=3 + :iceberg-kafka-connect:iceberg-kafka-connect-runtime:distZip + scan-path: kafka-connect/kafka-connect-runtime/build/distributions + unpack: true + - distribution: aws-bundle + build-task: :iceberg-aws-bundle:shadowJar + scan-path: aws-bundle/build/libs + unpack: false + - distribution: azure-bundle + build-task: :iceberg-azure-bundle:shadowJar + scan-path: azure-bundle/build/libs + unpack: false + - distribution: gcp-bundle + build-task: :iceberg-gcp-bundle:shadowJar + scan-path: gcp-bundle/build/libs + unpack: false + - distribution: spark-runtime-3.4_2.12 + build-task: >- + -DsparkVersions=3.4 + :iceberg-spark:iceberg-spark-runtime-3.4_2.12:shadowJar + scan-path: spark/v3.4/spark-runtime/build/libs + unpack: false + - distribution: spark-runtime-3.5_2.12 + build-task: >- + -DsparkVersions=3.5 + :iceberg-spark:iceberg-spark-runtime-3.5_2.12:shadowJar + scan-path: spark/v3.5/spark-runtime/build/libs + unpack: false + - distribution: spark-runtime-4.0_2.13 + build-task: >- + -DsparkVersions=4.0 + :iceberg-spark:iceberg-spark-runtime-4.0_2.13:shadowJar + scan-path: spark/v4.0/spark-runtime/build/libs + unpack: false + - distribution: spark-runtime-4.1_2.13 + build-task: >- + -DsparkVersions=4.1 + :iceberg-spark:iceberg-spark-runtime-4.1_2.13:shadowJar + scan-path: spark/v4.1/spark-runtime/build/libs + unpack: false + - distribution: flink-runtime-1.20 + build-task: >- + -DflinkVersions=1.20 + :iceberg-flink:iceberg-flink-runtime-1.20:shadowJar + scan-path: flink/v1.20/flink-runtime/build/libs + unpack: false + - distribution: flink-runtime-2.0 + build-task: >- + -DflinkVersions=2.0 + :iceberg-flink:iceberg-flink-runtime-2.0:shadowJar + scan-path: flink/v2.0/flink-runtime/build/libs + unpack: false + - distribution: flink-runtime-2.1 + build-task: >- + -DflinkVersions=2.1 + :iceberg-flink:iceberg-flink-runtime-2.1:shadowJar + scan-path: flink/v2.1/flink-runtime/build/libs + unpack: false + - distribution: open-api-test-fixtures-runtime + build-task: :iceberg-open-api:shadowJar + scan-path: open-api/build/libs + unpack: false + name: ${{ matrix.distribution }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: zulu + java-version: 21 + - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2 # zizmor: ignore[cache-poisoning] -- cache writes are restricted to the default branch by setup-gradle + - name: Build ${{ matrix.distribution }} + run: | + ./gradlew -DsparkVersions= -DflinkVersions= \ + ${{ matrix.build-task }} \ + -Pquick=true -x test -x javadoc + - name: Prepare scan directory + run: | + mkdir -p /tmp/cve-scan + if [ "${{ matrix.unpack }}" = "true" ]; then + unzip ${{ matrix.scan-path }}/*.zip -d /tmp/cve-scan + else + cp ${{ matrix.scan-path }}/iceberg-${{ matrix.distribution }}-*.jar /tmp/cve-scan/ + fi + - name: Run Trivy vulnerability scan + uses: lhotari/sandboxed-trivy-action@f01374b6cc3bf7264ab238293e94f6db7ada6dd0 # v1.0.2 + with: + scan-type: 'rootfs' + scan-ref: '/tmp/cve-scan' + scanners: 'vuln' + severity: 'HIGH,CRITICAL' + limit-severities-for-sarif: true + exit-code: '0' + format: 'sarif' + output: 'trivy-results.sarif' + - name: Print Trivy scan results + if: always() + run: | + if [ -f trivy-results.sarif ]; then + echo "## Trivy CVE Scan Results — ${{ matrix.distribution }}" + jq -r '.runs[].results[] | "- \(.ruleId): \(.message.text)"' trivy-results.sarif 2>/dev/null || echo "No findings or unable to parse SARIF." + else + echo "No SARIF file found — scan may have failed to install." + fi + - name: Upload Trivy results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + with: + sarif_file: 'trivy-results.sarif' + category: ${{ matrix.distribution }} diff --git a/.github/workflows/delta-conversion-ci.yml b/.github/workflows/delta-conversion-ci.yml index 520772f5c2f1..c98be4c0ea0e 100644 --- a/.github/workflows/delta-conversion-ci.yml +++ b/.github/workflows/delta-conversion-ci.yml @@ -37,7 +37,7 @@ on: - '.github/workflows/java-ci.yml' - '.github/workflows/jmh-benchmarks-ci.yml' - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/labeler.yml' - '.github/workflows/license-check.yml' - '.github/workflows/open-api.yml' diff --git a/.github/workflows/flink-ci.yml b/.github/workflows/flink-ci.yml index 1a815eb5b396..6164863775e7 100644 --- a/.github/workflows/flink-ci.yml +++ b/.github/workflows/flink-ci.yml @@ -37,7 +37,7 @@ on: - '.github/workflows/java-ci.yml' - '.github/workflows/jmh-benchmarks-ci.yml' - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/labeler.yml' - '.github/workflows/license-check.yml' - '.github/workflows/open-api.yml' diff --git a/.github/workflows/hive-ci.yml b/.github/workflows/hive-ci.yml index ae5ab0501407..1c754691ef3e 100644 --- a/.github/workflows/hive-ci.yml +++ b/.github/workflows/hive-ci.yml @@ -37,7 +37,7 @@ on: - '.github/workflows/java-ci.yml' - '.github/workflows/jmh-benchmarks-ci.yml' - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/labeler.yml' - '.github/workflows/license-check.yml' - '.github/workflows/open-api.yml' diff --git a/.github/workflows/java-ci.yml b/.github/workflows/java-ci.yml index f99d19d7d867..be97c14d0c4e 100644 --- a/.github/workflows/java-ci.yml +++ b/.github/workflows/java-ci.yml @@ -37,7 +37,7 @@ on: - '.github/workflows/hive-ci.yml' - '.github/workflows/jmh-benchmarks-ci.yml' - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/labeler.yml' - '.github/workflows/license-check.yml' - '.github/workflows/open-api.yml' diff --git a/.github/workflows/kafka-connect-ci.yml b/.github/workflows/kafka-connect-ci.yml index 59f0190d3353..a2e8c6043d58 100644 --- a/.github/workflows/kafka-connect-ci.yml +++ b/.github/workflows/kafka-connect-ci.yml @@ -43,7 +43,7 @@ on: - '.github/workflows/publish-snapshot.yml' - '.github/workflows/recurring-jmh-benchmarks.yml' - '.github/workflows/site-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/spark-ci.yml' - '.github/workflows/stale.yml' - '.gitignore' diff --git a/.github/workflows/kafka-connect-cve-scan.yml b/.github/workflows/kafka-connect-cve-scan.yml deleted file mode 100644 index 5781ed601163..000000000000 --- a/.github/workflows/kafka-connect-cve-scan.yml +++ /dev/null @@ -1,136 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -name: "Kafka Connect CVE Scan" -on: - push: - branches: - - 'main' - - '0.*' - - '1.*' - - '2.*' - tags: - - 'apache-iceberg-**' - pull_request: - paths-ignore: - - '.github/ISSUE_TEMPLATE/**' - - '.github/workflows/api-binary-compatibility.yml' - - '.github/workflows/delta-conversion-ci.yml' - - '.github/workflows/docs-ci.yml' - - '.github/workflows/flink-ci.yml' - - '.github/workflows/hive-ci.yml' - - '.github/workflows/java-ci.yml' - - '.github/workflows/jmh-benchmarks-ci.yml' - - '.github/workflows/labeler.yml' - - '.github/workflows/license-check.yml' - - '.github/workflows/open-api.yml' - - '.github/workflows/publish-snapshot.yml' - - '.github/workflows/recurring-jmh-benchmarks.yml' - - '.github/workflows/site-ci.yml' - - '.github/workflows/spark-ci.yml' - - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/stale.yml' - - '.gitignore' - - '.asf.yaml' - - 'dev/**' - - 'docker/**' - - 'mr/**' - - 'flink/**' - - 'spark/**' - - 'docs/**' - - 'site/**' - - 'open-api/**' - - 'format/**' - - '.gitattributes' - - '**/README.md' - - 'CONTRIBUTING.md' - - '**/LICENSE' - - '**/NOTICE' - - 'doap.rdf' - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - - # ------------------------------------------------------------------ - # Trivy CVE scan — scans bundled jars for known vulnerabilities. - # - # Behaviour: - # - If a CVE is found, the step will fail. However, since this job - # is not a required check, it will not block merging. - # - On push to main/release branches: results are uploaded as - # SARIF to the GitHub Security tab for ongoing tracking. - # - On PRs: SARIF upload is skipped because GitHub's Security - # tab only accepts results from default/protected branches. - # CVE findings are visible in the CI log output instead. - # ------------------------------------------------------------------ - kafka-connect-cve-scan: - runs-on: ubuntu-24.04 - permissions: - contents: read - security-events: write - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - persist-credentials: false - - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 - with: - distribution: zulu - java-version: 21 - - uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5 # zizmor: ignore[cache-poisoning] -- cache writes are restricted to the default branch by setup-gradle - - name: Build Kafka Connect distribution for scanning - run: | - ./gradlew -DsparkVersions= -DflinkVersions= -DkafkaVersions=3 \ - :iceberg-kafka-connect:iceberg-kafka-connect-runtime:distZip \ - -Pquick=true -x test -x javadoc - - name: Unpack distribution for scanning - run: | - mkdir -p /tmp/kafka-connect-scan - unzip kafka-connect/kafka-connect-runtime/build/distributions/iceberg-kafka-connect-runtime-*.zip \ - -d /tmp/kafka-connect-scan - - name: Run Trivy vulnerability scan - uses: lhotari/sandboxed-trivy-action@f01374b6cc3bf7264ab238293e94f6db7ada6dd0 # v1.0.2 - with: - scan-type: 'rootfs' - scan-ref: '/tmp/kafka-connect-scan' - scanners: 'vuln' - severity: 'HIGH,CRITICAL' - limit-severities-for-sarif: true - exit-code: '1' - format: 'sarif' - output: 'trivy-results.sarif' - - name: Print Trivy scan results - if: always() - run: | - if [ -f trivy-results.sarif ]; then - echo "## Trivy CVE Scan Results" - jq -r '.runs[].results[] | "- \(.ruleId): \(.message.text)"' trivy-results.sarif 2>/dev/null || echo "No findings or unable to parse SARIF." - else - echo "No SARIF file found — scan may have failed to install." - fi - - name: Upload Trivy results to GitHub Security tab - if: always() && github.event_name == 'push' - uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 - with: - sarif_file: 'trivy-results.sarif' diff --git a/.github/workflows/spark-ci.yml b/.github/workflows/spark-ci.yml index 566b7524e488..f04e397dc1ad 100644 --- a/.github/workflows/spark-ci.yml +++ b/.github/workflows/spark-ci.yml @@ -38,7 +38,7 @@ on: - '.github/workflows/java-ci.yml' - '.github/workflows/jmh-benchmarks-ci.yml' - '.github/workflows/kafka-connect-ci.yml' - - '.github/workflows/kafka-connect-cve-scan.yml' + - '.github/workflows/cve-scan.yml' - '.github/workflows/labeler.yml' - '.github/workflows/license-check.yml' - '.github/workflows/open-api.yml'