From cfac81c952be5d0903818241e427fdde52f5bb48 Mon Sep 17 00:00:00 2001 From: croway Date: Wed, 2 Sep 2026 14:49:24 +0200 Subject: [PATCH] CAMEL-24502: Least privilege for the sync workflows and pin the Maven wrapper downloads The two scheduled workflows, automatic-sync-main.yml and generate-sbom-main.yml, declared no permissions block, so their single job ran with the repository default GITHUB_TOKEN grants. pr-build-main.yml and pr-doc-validation.yml already declare `permissions: contents: read`, so this brings the remaining workflows in line. Each workflow now declares `permissions: {}` at the top and every job opts in to exactly what it needs. The job is also split in two: - `build` (contents: read) checks out and builds apache/camel and then camel-spring-boot, exactly as before, and uploads the regenerated changes as a build artifact. - `create-pull-request` (contents: write, pull-requests: write) checks out camel-spring-boot, applies the artifact and calls peter-evans/create-pull-request. The regenerated tree is handed over as a `git diff --cached --binary` patch rather than a copy of the working tree. A typical sync changes a handful of files out of a repository of well over a hundred thousand, so a patch keeps the transfer small, and unlike a file overlay it also carries deletions, which a regeneration can produce when a component goes away. `git add --all -- ':!camel'` excludes the nested apache/camel checkout, and .gitignore already excludes target directories. The patch is applied with `git apply --3way` so that a main branch that moved while the build was running is merged rather than silently dropped. Every `uses:` reference in these two workflows is pinned to a full commit SHA with the version kept as a trailing comment, so the resolved action code is reproducible and reviewable. .github/dependabot.yml already has a github-actions ecosystem entry, so the pins keep getting bumped. maven-wrapper.properties gained distributionSha256Sum and wrapperSha256Sum, so mvnw and mvnw.cmd verify what they download instead of trusting the URL. The two values were computed from the artifacts at the exact URLs already in the file and cross-checked against the .sha1 files published next to them on repo.maven.apache.org; the distribution was additionally cross-checked against the .sha512 published on archive.apache.org, and the wrapper jar sum matches the maven-wrapper.jar already committed under .mvn/wrapper. Co-Authored-By: Claude Opus 5 --- .github/workflows/automatic-sync-main.yml | 60 ++++++++++++++++++++-- .github/workflows/generate-sbom-main.yml | 61 +++++++++++++++++++++-- .mvn/wrapper/maven-wrapper.properties | 2 + 3 files changed, 114 insertions(+), 9 deletions(-) diff --git a/.github/workflows/automatic-sync-main.yml b/.github/workflows/automatic-sync-main.yml index a59f5094179b..4f6704f2b704 100644 --- a/.github/workflows/automatic-sync-main.yml +++ b/.github/workflows/automatic-sync-main.yml @@ -21,21 +21,28 @@ on: schedule: # Run at midnight every day - cron: '0 0 * * *' + +# No grants by default, every job opts in to exactly what it needs. +permissions: {} + jobs: build: name: Sync Camel Spring Boot Main Branch if: github.repository == 'apache/camel-spring-boot' runs-on: ubuntu-latest + # Builds apache/camel and camel-spring-boot, so it must not hold any write grant. + permissions: + contents: read steps: - name: Checkout Camel project - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: apache/camel persist-credentials: false ref: main path: camel - name: Set up JDK - uses: actions/setup-java@v6 + uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6 with: distribution: 'temurin' java-version: 17 @@ -44,15 +51,60 @@ jobs: run: ./mvnw -V --no-transfer-progress -Dquickly clean install working-directory: ${{ github.workspace }}/camel - name: Checkout Camel-spring-boot project - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: main persist-credentials: false fetch-depth: 0 - name: Build Camel-spring-boot Project run: ./mvnw -V --no-transfer-progress clean install -DskipTests + - name: Collect regenerated sources + # Capture the regenerated tree as a patch: it carries additions, modifications + # and deletions, ignores build output via .gitignore, and excludes the nested + # apache/camel checkout. + run: | + git add --all -- ':!camel' + git diff --cached --binary > "${RUNNER_TEMP}/sync.patch" + git reset --quiet + echo "Patch size: $(wc -c < "${RUNNER_TEMP}/sync.patch") bytes" + - name: Upload regenerated sources + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: regenerated-sources + path: ${{ runner.temp }}/sync.patch + if-no-files-found: error + retention-days: 1 + + create-pull-request: + name: Create Sync Pull Request + needs: build + if: github.repository == 'apache/camel-spring-boot' + runs-on: ubuntu-latest + # Only this job, which runs no third party build, holds the write grants. + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout Camel-spring-boot project + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: main + persist-credentials: false + fetch-depth: 0 + - name: Download regenerated sources + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: regenerated-sources + path: ${{ runner.temp }}/sync + - name: Apply regenerated sources + run: | + if [ -s "${RUNNER_TEMP}/sync/sync.patch" ]; then + git apply --3way --whitespace=nowarn "${RUNNER_TEMP}/sync/sync.patch" + else + echo "Nothing was regenerated, no changes to apply" + fi - name: Create Pull Request - uses: peter-evans/create-pull-request@v8.1.1 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: base: main token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate-sbom-main.yml b/.github/workflows/generate-sbom-main.yml index 07d14e3e8d3d..b24183ed0c54 100644 --- a/.github/workflows/generate-sbom-main.yml +++ b/.github/workflows/generate-sbom-main.yml @@ -22,22 +22,28 @@ on: # Every 24 hours - cron: '30 17 * * 0' workflow_dispatch: - + +# No grants by default, every job opts in to exactly what it needs. +permissions: {} + jobs: build: name: Sync Camel Spring Boot Main Branch if: github.repository == 'apache/camel-spring-boot' runs-on: ubuntu-latest + # Builds apache/camel and camel-spring-boot, so it must not hold any write grant. + permissions: + contents: read steps: - name: Checkout Camel project - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: repository: apache/camel persist-credentials: false ref: main path: camel - name: Set up JDK - uses: actions/setup-java@v6 + uses: actions/setup-java@dd06d9cba3e5552c54d9f8ea23572deb30010f7c # v6 with: distribution: 'temurin' java-version: 17 @@ -46,15 +52,60 @@ jobs: run: ./mvnw -B -V --no-transfer-progress -Dquickly install working-directory: ${{ github.workspace }}/camel - name: Checkout Camel-spring-boot project - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: main persist-credentials: false fetch-depth: 0 - name: Build Camel-spring-boot Project for generating SBOM run: ./mvnw -V --no-transfer-progress clean install -DskipTests -Psbom + - name: Collect generated SBOM + # Capture the regenerated tree as a patch: it carries additions, modifications + # and deletions, ignores build output via .gitignore, and excludes the nested + # apache/camel checkout. + run: | + git add --all -- ':!camel' + git diff --cached --binary > "${RUNNER_TEMP}/sbom.patch" + git reset --quiet + echo "Patch size: $(wc -c < "${RUNNER_TEMP}/sbom.patch") bytes" + - name: Upload generated SBOM + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: generated-sbom + path: ${{ runner.temp }}/sbom.patch + if-no-files-found: error + retention-days: 1 + + create-pull-request: + name: Create SBOM Pull Request + needs: build + if: github.repository == 'apache/camel-spring-boot' + runs-on: ubuntu-latest + # Only this job, which runs no third party build, holds the write grants. + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout Camel-spring-boot project + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + with: + ref: main + persist-credentials: false + fetch-depth: 0 + - name: Download generated SBOM + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: generated-sbom + path: ${{ runner.temp }}/sbom + - name: Apply generated SBOM + run: | + if [ -s "${RUNNER_TEMP}/sbom/sbom.patch" ]; then + git apply --3way --whitespace=nowarn "${RUNNER_TEMP}/sbom/sbom.patch" + else + echo "Nothing was regenerated, no changes to apply" + fi - name: Create Pull Request - uses: peter-evans/create-pull-request@v8.1.1 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: base: main token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index ec95f42f3163..03b0f55107b7 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,4 +1,6 @@ wrapperVersion=3.3.4 distributionType=bin distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip +distributionSha256Sum=0d7125e8c91097b36edb990ea5934e6c68b4440eef4ea96510a0f6815e7eeadb wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.4/maven-wrapper-3.3.4.jar +wrapperSha256Sum=4e2fbf6554bc8a4702cdfdd3bef464f423393d784ddbb037216320ce55d5e4e1