diff --git a/.github/actions/publish/action.yml b/.github/actions/publish/action.yml index 0780cf2..6ae0445 100644 --- a/.github/actions/publish/action.yml +++ b/.github/actions/publish/action.yml @@ -4,11 +4,6 @@ inputs: dry_run: description: 'Is this a dry run. If so no package will be published.' required: true -outputs: - hashes: - description: sha256sum hashes of built artifacts - value: ${{ steps.hash.outputs.hashes }} - runs: using: composite steps: @@ -33,13 +28,6 @@ runs: echo "published ${pkg}" done - - name: Hash nuget packages - id: hash - if: ${{ inputs.dry_run == 'false' }} - shell: bash - run: | - echo "hashes=$(sha256sum ./nupkgs/*.nupkg ./nupkgs/*.snupkg | base64 -w0)" >> "$GITHUB_OUTPUT" - - name: Dry Run Publish if: ${{ inputs.dry_run == 'true' }} shell: bash diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9b164d9..c8cc9ef 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,10 +7,6 @@ on: description: 'Is this a dry run. If so no package will be published.' type: boolean required: true - tag: - description: 'Tag for provenance. For a dry run the value does not matter.' - type: string - required: true workflow_call: inputs: @@ -18,10 +14,6 @@ on: description: 'Is this a dry run. If so no package will be published.' type: boolean required: true - tag: - description: 'Tag for provenance' - type: string - required: true jobs: publish: @@ -30,6 +22,7 @@ jobs: id-token: write # Needed if using OIDC to get release secrets. contents: write # Contents and pull-requests are for release-please to make releases. pull-requests: write + attestations: write steps: - uses: actions/checkout@v4 @@ -46,7 +39,6 @@ jobs: /production/common/releasing/nuget/api_key = NUGET_API_KEY' s3_path_pairs: 'launchdarkly-releaser/dotnet/LaunchDarkly.Logging.snk = LaunchDarkly.Logging.snk' - - name: Build Release uses: ./.github/actions/release-build @@ -71,16 +63,8 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} dry_run: ${{ inputs.dry_run }} - provenance: - permissions: - actions: read - id-token: write - contents: write - if: ${{ inputs.dry_run == 'false' }} - needs: ['publish'] - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 - with: - base64-subjects: "${{ needs.publish.outputs.hashes }}" - upload-assets: true - upload-tag-name: ${{ inputs.tag }} - provenance-name: ${{ format('LaunchDarkly.Logging-{0}_provenance.intoto.jsonl', inputs.tag) }} + - name: Attest build provenance + if: ${{ format('{0}', inputs.dry_run) == 'false' }} + uses: actions/attest@v4 + with: + subject-path: 'nupkgs/*' diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index da32471..e24992b 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -9,7 +9,6 @@ jobs: release-please: outputs: releases_created: ${{ steps.release.outputs.releases_created }} - tag_name: ${{ steps.release.outputs.tag_name }} runs-on: ubuntu-latest permissions: id-token: write # Needed if using OIDC to get release secrets. @@ -33,4 +32,3 @@ jobs: uses: ./.github/workflows/publish.yml with: dry_run: false - tag: ${{ needs.release-please.outputs.tag_name }} diff --git a/PROVENANCE.md b/PROVENANCE.md new file mode 100644 index 0000000..ad6d235 --- /dev/null +++ b/PROVENANCE.md @@ -0,0 +1,49 @@ +## Verifying SDK build provenance with GitHub artifact attestations + +LaunchDarkly uses [GitHub artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) to help developers make their supply chain more secure by ensuring the authenticity and build integrity of our published SDK packages. + +LaunchDarkly publishes provenance about our SDK package builds using [GitHub's `actions/attest` action](https://github.com/actions/attest). These attestations are stored in GitHub's attestation API and can be verified using the [GitHub CLI](https://cli.github.com/). + +To verify build provenance attestations, we recommend using the [GitHub CLI `attestation verify` command](https://cli.github.com/manual/gh_attestation_verify). Example usage for verifying SDK packages is included below: + + +``` +# Set the version of the SDK to verify +SDK_VERSION=2.0.0 +``` + + +``` +# Download the nupkg from NuGet +$ nuget install LaunchDarkly.Logging -Version $SDK_VERSION -OutputDirectory ./packages + +# Verify provenance using the GitHub CLI +$ gh attestation verify ./packages/LaunchDarkly.Logging.${SDK_VERSION}/LaunchDarkly.Logging.${SDK_VERSION}.nupkg --owner launchdarkly +``` + +Below is a sample of expected output. + +``` +Loaded digest sha256:... for file://LaunchDarkly.Logging.2.0.0.nupkg +Loaded 1 attestation from GitHub API + +The following policy criteria will be enforced: +- Predicate type must match:................ https://slsa.dev/provenance/v1 +- Source Repository Owner URI must match:... https://github.com/launchdarkly +- Subject Alternative Name must match regex: (?i)^https://github.com/launchdarkly/ +- OIDC Issuer must match:................... https://token.actions.githubusercontent.com + +✓ Verification succeeded! + +The following 1 attestation matched the policy criteria + +- Attestation #1 + - Build repo:..... launchdarkly/dotnet-logging + - Build workflow:. .github/workflows/release-please.yml + - Signer repo:.... launchdarkly/dotnet-logging + - Signer workflow: .github/workflows/release-please.yml +``` + +For more information, see [GitHub's documentation on verifying artifact attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds#verifying-artifact-attestations-with-the-github-cli). + +**Note:** These instructions do not apply when building our SDKs from source. diff --git a/README.md b/README.md index 668c91c..510c634 100644 --- a/README.md +++ b/README.md @@ -37,13 +37,17 @@ a8a17f69f1bef56e253fc9166096c907514ab74b812d041faa04712e2bcb243d Public Key Token: d9182e4b0afd33e7 ``` +## Verifying build provenance with the SLSA framework + +LaunchDarkly uses the [SLSA framework](https://slsa.dev/spec/v1.0/about) (Supply-chain Levels for Software Artifacts) to help developers make their supply chain more secure by ensuring the authenticity and build integrity of our published packages. To learn more, see the [provenance guide](PROVENANCE.md). + ## About LaunchDarkly * LaunchDarkly is a continuous delivery platform that provides feature flags as a service and allows developers to iterate quickly and safely. We allow you to easily flag your features and manage them from the LaunchDarkly dashboard. With LaunchDarkly, you can: * Roll out a new feature to a subset of your users (like a group of users who opt-in to a beta tester group), gathering feedback and bug reports from real-world use cases. * Gradually roll out a feature to an increasing percentage of users, and track the effect that the feature has on key metrics (for instance, how likely is a user to complete a purchase if they have feature A versus feature B?). * Turn off a feature that you realize is causing performance problems in production, without needing to re-deploy, or even restart the application with a changed configuration file. - * Grant access to certain features based on user attributes, like payment plan (eg: users on the ‘gold’ plan get access to more features than users in the ‘silver’ plan). Disable parts of your application to facilitate maintenance, without taking everything offline. + * Grant access to certain features based on user attributes, like payment plan (eg: users on the 'gold' plan get access to more features than users in the 'silver' plan). Disable parts of your application to facilitate maintenance, without taking everything offline. * LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Check out [our documentation](https://docs.launchdarkly.com/docs) for a complete list. * Explore LaunchDarkly * [launchdarkly.com](https://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information diff --git a/release-please-config.json b/release-please-config.json index e89297f..2b29245 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -4,7 +4,10 @@ "release-type": "simple", "bootstrap-sha": "b4600d1c993afecd737dad1c85da34908c7d7e50", "include-v-in-tag": false, - "include-component-in-tag": false + "include-component-in-tag": false, + "extra-files": [ + "PROVENANCE.md" + ] } } }