Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add provenance for Haskell #608

Merged
merged 1 commit into from
Jul 21, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 115 additions & 9 deletions internal/builders/generic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ project simply generates provenance as a separate step in an existing workflow.
- [Provenance for Bazel](#provenance-for-bazel)
- [Provenance for Java](#provenance-for-java)
- [Provenance for Rust](#provenance-for-rust)
- [Provenance for Haskell](#provenance-for-haskell)

---

Expand Down Expand Up @@ -403,7 +404,7 @@ jobs:
run: |
# Your normal build workflow targets here
bazel build //path/to/target_binary //path/to_another/binary

# Copy the binaries.
cp bazel-bin/path/to/target_binary .
cp bazel-bin/path/to/another/binary .
Expand All @@ -425,7 +426,7 @@ jobs:
```

4. Call the generic workflow to generate provenance by declaring the job below:

```yaml
provenance:
needs: [build]
Expand Down Expand Up @@ -456,7 +457,7 @@ jobs:
run: |
# Your normal build workflow targets here
bazel build //path/to/target_binary //path/to_another/binary

# Copy the binaries.
cp bazel-bin/path/to/target_binary .
cp bazel-bin/path/to/another/binary .
Expand Down Expand Up @@ -512,7 +513,7 @@ jobs:
run: |
# Your normal build workflow targets here
mvn clean package

# Save the location of the maven output files for easier reference
ARTIFACT_PATTERN=./target/$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)*.jar
echo "::set-output name=artifact_pattern::$ARTIFACT_PATTERN"
Expand Down Expand Up @@ -563,7 +564,7 @@ jobs:
run: |
# Your normal build workflow targets here
mvn clean package

# Save the location of the maven output files for easier reference
ARTIFACT_PATTERN=./target/$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)*.jar
echo "::set-output name=artifact_pattern::$ARTIFACT_PATTERN"
Expand All @@ -572,7 +573,7 @@ jobs:
id: hash
run: |
echo "::set-output name=hashes::$(sha256sum ${{ steps.build.outputs.artifact_pattern }} | base64 -w0)"

- name: Upload build artifacts
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
Expand Down Expand Up @@ -606,7 +607,7 @@ jobs:
```

2. Add an `id: build` field to your gradle build ste:

```yaml
steps:
[...]
Expand Down Expand Up @@ -665,7 +666,7 @@ jobs:
id: hash
run: |
echo "::set-output name=hashes::$(sha256sum ./build/libs/* | base64 -w0)"

- name: Upload build artifacts
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3
with:
Expand Down Expand Up @@ -778,4 +779,109 @@ jobs:
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: true # Optional: Upload to a new release

```
```

### Provenance for Haskell

If you use [Haskell](https://www.haskell.org/) (either via
[`cabal`](https://www.haskell.org/cabal/) or
[`stack`](https://docs.haskellstack.org/en/stable/README/)) to generate your
artifacts, you can easily generate SLSA3 provenance by updating your existing
workflow with the steps indicated in the workflow below.

1. Declare an `outputs` for the hashes:

```yaml
jobs:
build:
outputs:
hashes: ${{ steps.hash.outputs.hashes }}

```

2. Build your binaries. Then add a step to generate the provenance subjects as shown below. Update the sha256 sum arguments to include all binaries that you generate provenance for:

```yaml
steps:
[...]
- name: Build using Haskell
run: |
# Your normal build workflow targets here.
cabal build # or stack build

# Copy the binary to the root directory for easier reference
# For Cabal, use the following command
cp $(cabal list-bin .) .
# For Stack, use the following command instead
# cp $(stack path --local-install-root)/bin/target_binary .

# Generate the subject.
- name: Generate subject
id: hash
run: |
set -euo pipefail

echo "::set-output name=hashes::$(sha256sum target_binary | base64 -w0)"

```

3. Call the generic workflow to generate provenance by declaring the job below:

```yaml
provenance:
needs: [build]
permissions:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0
with:
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: true # Optional: Upload to a new release

```

All in all, it will look as the following:

```yaml
jobs:
build:
outputs:
hashes: ${{ steps.hash.outputs.hashes }}

steps:
- name: Checkout repository
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3
- name: Setup Haskell
uses: haskell/actions/setup@745062a754c3c4b70b87cb93937ad443096cc94d # tag=v1

- name: Build using Haskell
run: |
# Your normal build workflow targets here.
cabal build # or stack build

# Copy the binary to the root directory for easier reference
# For Cabal, use the following command
cp $(cabal list-bin .) .
# For Stack, use the following command instead
# cp $(stack path --local-install-root)/bin/target_binary .

# Generate the subject.
- name: Generate subject
id: hash
run: |
set -euo pipefail

echo "::set-output name=hashes::$(sha256sum target_binary | base64 -w0)"

provenance:
needs: [build]
permissions:
actions: read # To read the workflow path.
id-token: write # To sign the provenance.
contents: write # To add assets to a release.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0
with:
base64-subjects: "${{ needs.build.outputs.hashes }}"
upload-assets: true # Optional: Upload to a new release
```