Skip to content

Commit

Permalink
feat: Add Maven BYOB publisher (#2242)
Browse files Browse the repository at this point in the history
Adds a publisher for the Maven builder.

It is missing a few bits here and there, but I am keeping it open as a
draft to track progress.

The main things to fix are:

1. ~~Keep the built artifacts without modifying the delegator.~~ Done
2. ~~Use the safe downloaders and uploaders.~~ Done

We have made a Maven plugin to replace `collect_release_artifacts.sh`.
This plugin currently exist in the test projects source tree but should
ideally exist in Maven Central.

Example usage:
https://github.com/AdamKorcz/test-java-project/blob/main/.github/workflows/byob.yml
Example action:
https://github.com/AdamKorcz/test-java-project/actions/runs/5380001938

Sample release: Browse v0.1.17 here:
https://central.sonatype.com/artifact/io.github.adamkorcz/test-java-project/0.1.17/versions

---------

Signed-off-by: AdamKorcz <44787359+AdamKorcz@users.noreply.github.com>
Signed-off-by: AdamKorcz <adam@adalogics.com>
  • Loading branch information
AdamKorcz committed Jul 5, 2023
1 parent 014d7a8 commit ffbc1e5
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 67 deletions.
32 changes: 23 additions & 9 deletions .github/workflows/builder_maven_slsa3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,56 @@ on:
required: false
type: boolean
default: false
artifact-list:
description: "Comma-separated list of paths to artifacts to be released. Use PROJECT_VERSION for the release version, for example: 'artifact-PROJECT_VERSION-sources.jar'"
type: string
required: true
jdk-version:
description: "The JDK version"
required: false
default: 17
type: number

outputs:
provenance-name:
description: "The file name of the attestation upload artifact."
# NOTE: This is an "untrusted" value returned from the build.
value: "${{ fromJSON(jobs.slsa-run.outputs.build-artifacts-outputs).attestation-name }}"

provenance-download-name:
description: "The name of the provenance attestation uploaded to the workflow run."
value: "${{ jobs.slsa-run.outputs.attestations-download-name }}"

provenance-download-sha256:
description: "The sha256 of the provenance attestation uploaded to the workflow run."
value: "${{ jobs.slsa-run.outputs.attestations-download-sha256 }}"

target-download-sha256:
description: "The sha256 of the target uploaded to the workflow run."
value: "${{ fromJSON(jobs.slsa-run.outputs.build-artifacts-outputs).target-download-sha256 }}"
jobs:
slsa-setup:
permissions:
id-token: write # For token creation.
outputs:
slsa-token: ${{ steps.generate.outputs.slsa-token }}
slsa-token: "${{ steps.generate.outputs.slsa-token }}"
runs-on: ubuntu-latest
steps:
- name: Generate the token
id: generate
uses: slsa-framework/slsa-github-generator/actions/delegator/setup-generic@main
with:
slsa-workflow-recipient: "delegator_lowperms-generic_slsa3.yml"
slsa-rekor-log-public: ${{ inputs.rekor-log-public }}
slsa-rekor-log-public: "${{ inputs.rekor-log-public }}"
slsa-runner-label: "ubuntu-latest"
slsa-build-action-path: "./internal/builders/maven"
slsa-workflow-inputs: ${{ toJson(inputs) }}
slsa-workflow-inputs: "${{ toJson(inputs) }}"

slsa-run:
needs: [slsa-setup]
needs: slsa-setup
permissions:
id-token: write # For signing.
contents: read # For asset uploads.
actions: read # For the entrypoint.
packages: write # To publish to GitHub packages.
uses: slsa-framework/slsa-github-generator/.github/workflows/delegator_lowperms-generic_slsa3.yml@main
with:
slsa-token: ${{ needs.slsa-setup.outputs.slsa-token }}
slsa-token: "${{ needs.slsa-setup.outputs.slsa-token }}"

# TODO(#2154): need to add support for uploading provenance and artifact to registry
127 changes: 127 additions & 0 deletions .github/workflows/publish_maven.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Copyright 2023 SLSA Authors

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 11, 2023

Member

IIUC this was an example workflow. Maybe we can consider putting this file somewhere else? like in an examples/ directory?

#
# Licensed 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.

on:
workflow_call:
inputs:
provenance-download-name:
description: "The artifact name for the package provenance."
required: true
type: string
provenance-download-sha256:
description: "The sha256 of the package provenance artifact."
required: false
type: string
target-download-sha256:
description: "The sha256 of the target directory."
required: true
type: string
secrets:
maven-username:
description: "Maven username"
required: false
maven-password:
description: "Maven password"
required: false
gpg-key-pass:
description: "gpg-key-pass"
required: false
gpg-private-key:
description: "gpg-key-pass"
required: false

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 11, 2023

Member

Add top level permissions

jobs:
setup-java:

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 10, 2023

Member

@AdamKorcz Consider renaming this job name.

runs-on: ubuntu-latest
steps:
- name: Checkout the project repository
uses: slsa-framework/slsa-github-generator/.github/actions/secure-project-checkout@main
- name: Set up Java for publishing to Maven Central Repository
uses: actions/setup-java@v3
env:
MAVEN_USERNAME: ${{ secrets.maven-username }}
MAVEN_PASSWORD: ${{ secrets.maven-password }}
GPG_KEY_PASS: ${{ secrets.gpg-key-pass }}
with:
java-version: '11'
distribution: 'temurin'
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.gpg-private-key }}
gpg-passphrase: GPG_KEY_PASS

- name: Download the slsa attestation
uses: slsa-framework/slsa-github-generator/.github/actions/secure-download-folder@main
with:
name: "${{ inputs.provenance-download-name }}"
path: slsa-attestations
sha256: "${{ inputs.provenance-download-sha256 }}"

- name: Download the target dir
uses: slsa-framework/slsa-github-generator/.github/actions/secure-download-folder@main
with:
name: target
path: ./
sha256: "${{ inputs.target-download-sha256 }}"

- name: Publish to the Maven Central Repository
shell: bash
env:
MAVEN_USERNAME: "${{ secrets.maven-username }}"
MAVEN_PASSWORD: "${{ secrets.maven-password }}"
GPG_KEY_PASS: "${{ secrets.gpg-key-pass }}"
SLSA_DIR: "${{ inputs.provenance-download-name }}"
PROVENANCE_FILES: "${{ inputs.provenance-download-name }}"
run: |
# Build and run custom plugin
cd plugin && mvn clean install && cd ..
# Re-indexing the secondary jar files for deploy
mvn javadoc:jar source:jar
echo "find javadoc"
find . -name "*javadoc*"
echo "end find javadoc"
# Retrieve project version
VERSION=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout)

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 10, 2023

Member

@AdamKorcz In the future consider using lowercase variable names for (script-)local variables.

ARTIFACTID=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.artifactId -q -DforceStdout)
# Reset the environment variables add in the base provenance
FILES="slsa-attestations/${PROVENANCE_FILES}/${ARTIFACTID}-${VERSION}.jar.intoto.build.slsa"
TYPES=slsa
CLASSIFIERS=jar.intoto.build
# Find all necessary built jar files and attach them to the environment variable deploy
# shellcheck disable=SC2044 # We don't spawn a new sub shell since we are appending to global env vars
for name in $(find ./ -name "$ARTIFACTID-$VERSION-*.jar")
do
# shellcheck disable=SC1001 # shellcheck complains over \- but the line does what it should.
TARGET=$(echo "${name}" | rev | cut -d\- -f1 | rev)
FILES=$FILES,$name
TYPES=$TYPES,${TARGET##*.}
CLASSIFIERS=$CLASSIFIERS,${TARGET%.*}
echo "FILESSS: ${FILES}"
done
echo "find ./ -name {ARTIFACTID}-{VERSION}-*.jar"
find ./ -name "${ARTIFACTID}-${VERSION}-*.jar"
# Find all generated provenance files and attach them the the environment variable for deploy
# shellcheck disable=SC2044 # We don't spawn a new sub shell since we are appending to global env vars
for name in $(find ./ -name "$ARTIFACTID-$VERSION-*.jar.intoto.build.slsa")

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 10, 2023

Member

@AdamKorcz I noticed some of the files are named .intoto.b.slsa in the test package. is that intentional? I expected them to be .intoto.builde.slsa.
https://repo1.maven.org/maven2/io/github/adamkorcz/test-java-project/0.1.19/

@laurentsimon Did we decide on .build.slsa or .intoto.build.slsa for the file extension? I thought we decided on removing the intoto part.

This comment has been minimized.

Copy link
@laurentsimon

laurentsimon Jul 10, 2023

Collaborator

You're correct. We will use .build.slsa going forward. intoto can be removed. @AdamKorcz can you send a PR?

do
# shellcheck disable=SC1001 # shellcheck complains over \- but the line does what it should.
TARGET=$(echo "${name}" | rev | cut -d\- -f1 | rev)

This comment has been minimized.

Copy link
@ianlewis

ianlewis Jul 10, 2023

Member

@AdamKorcz Did cut -d- -f1 not work for some reason?

FILES=$FILES,$name
TYPES=$TYPES",slsa"
CLASSIFIERS=$CLASSIFIERS,${TARGET::-9}
done
# Sign and deploy the files to the ossrh remote repository
mvn validate jar:jar -Dfile=target/"${ARTIFACTID}"-"${VERSION}".jar -Durl=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=ossrh -Dfiles="${FILES}" -Dtypes="${TYPES}" -Dclassifiers="${CLASSIFIERS}" -DpomFile=pom.xml gpg:sign-and-deploy-file
27 changes: 13 additions & 14 deletions internal/builders/maven/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ inputs:
slsa-workflow-secret13: {}
slsa-workflow-secret14: {}
slsa-workflow-secret15: {}
outputs:
target-download-sha256:
description: >
The sha256 digest of the "target" directory.
Users should verify the download against this digest to prevent tampering.
value: ${{ steps.upload-target.outputs.sha256 }}

on:
workflow_call:
Expand All @@ -52,21 +59,13 @@ runs:
distribution: temurin
java-version: ${{ fromJson(inputs.slsa-workflow-inputs).jdk-version }}
- name: Run mvn package
shell: bash
run: mvn package
- name: Put release artifacts in one directory
shell: bash
env:
SLSA_OUTPUTS_ARTIFACTS_FILE: ${{ inputs.slsa-layout-file }}
ARTIFACT_LIST: ${{ fromJson(inputs.slsa-workflow-inputs).artifact-list }}
run: ./../__TOOL_ACTION_DIR__/collect_release_artifacts.sh
- name: Upload built artifacts
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
run: cd plugin && mvn clean install && cd .. && mvn package
- name: Upload target
id: upload-target
uses: slsa-framework/slsa-github-generator/.github/actions/secure-upload-folder@main
with:
path: ./release-files-for-slsa/*
- name: Make outputs
id: make-outputs
shell: bash
env:
SLSA_OUTPUTS_ARTIFACTS_FILE: ${{ inputs.slsa-layout-file }}
run: ./../__TOOL_CHECKOUT_DIR__/internal/builders/gradle/create_attestation.sh
name: target
path: target
44 changes: 0 additions & 44 deletions internal/builders/maven/collect_release_artifacts.sh

This file was deleted.

0 comments on commit ffbc1e5

Please sign in to comment.