mirror of
https://github.com/arx-research/libhalo.git
synced 2026-01-09 13:18:04 -05:00
CI: Compare released package hashes (#101)
This commit is contained in:
committed by
GitHub
parent
e4114e54bd
commit
0cc6ad243f
2
.github/workflows/prod_build_cli.yml
vendored
2
.github/workflows/prod_build_cli.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
Release contents:
|
||||
* `halocli-linux-x64.zip` - Linux x64 build (elf; zipped)
|
||||
* `halocli-win-x64.zip` - Windows 64 build (exe; zipped)
|
||||
* `halocli-macos-x64.pkg` - MacOS x64 build (installer; signed)
|
||||
* `halocli-macos-x64.pkg` - Mac OS x64 build (installer; signed)
|
||||
|
||||
**Note:** The files `*-keyless.sig` and `*-keyless.pem` constitute a part of [build audit trail](https://github.com/arx-research/libhalo/blob/master/docs/build-audit-trail.md).
|
||||
- name: Store release upload URL
|
||||
|
||||
14
.github/workflows/prod_build_lib.yml
vendored
14
.github/workflows/prod_build_lib.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
Release contents:
|
||||
* `libhalo.js` - standalone JavaScript library for inclusion in classic HTML applications;
|
||||
* `libhalo.js.LICENSE` - license information;
|
||||
* `libhalo.cosign.zip` - build audit trail;
|
||||
* `libhalo-npm-hash.txt` - integrity hash of the package released to npmjs.com and GitHub Packages;
|
||||
|
||||
**Note:** The files `*-keyless.sig` and `*-keyless.pem` constitute a part of [build audit trail](https://github.com/arx-research/libhalo/blob/master/docs/build-audit-trail.md).
|
||||
- name: Store release upload URL
|
||||
@@ -149,13 +149,13 @@ jobs:
|
||||
run: npm ci
|
||||
- name: Get package integrity hash
|
||||
run: |
|
||||
PKG_HASH=$(npm publish --dry-run --json 2>/dev/null | jq --raw-output '.integrity')
|
||||
PKG_HASH=$(npm publish --dry-run --json 2>/dev/null | jq --raw-output '.integrity' | tr -d '\n')
|
||||
echo "Package hash: ${PKG_HASH}"
|
||||
echo -n "${PKG_HASH}" > "${RUNNER_TEMP}/libhalo-npm-hash.txt"
|
||||
echo y | cosign sign-blob "${RUNNER_TEMP}/libhalo-npm-hash.txt" --output-certificate "${RUNNER_TEMP}/libhalo-npm-hash.txt-keyless.pem" --output-signature "${RUNNER_TEMP}/libhalo-npm-hash.txt-keyless.sig"
|
||||
cosign verify-blob --cert "${RUNNER_TEMP}/libhalo-npm-hash.txt-keyless.pem" --signature "${RUNNER_TEMP}/libhalo-npm-hash.txt-keyless.sig" --certificate-identity "https://github.com/arx-research/libhalo/.github/workflows/prod_build_lib.yml@${GITHUB_REF}" --certificate-oidc-issuer https://token.actions.githubusercontent.com "${RUNNER_TEMP}/libhalo-npm-hash.txt"
|
||||
- name: Publish package to npmjs
|
||||
run: npm publish --json
|
||||
run: npm publish --json | tee "${RUNNER_TEMP}/npmjs-publish.json"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.RELEASE_NPM_TOKEN }}
|
||||
- name: Re-setup Node.JS with GitHub pkg
|
||||
@@ -164,9 +164,15 @@ jobs:
|
||||
node-version: '16.x'
|
||||
registry-url: https://npm.pkg.github.com/
|
||||
- name: Publish package to GitHub
|
||||
run: npm publish --json
|
||||
run: npm publish --json | tee "${RUNNER_TEMP}/gh-publish.json"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Compare released hashes
|
||||
run: |
|
||||
( cat "${RUNNER_TEMP}/npmjs-publish.json" | jq --raw-output '.integrity' | tr -d '\n' ) > "${RUNNER_TEMP}/npmjs-hash.txt"
|
||||
( cat "${RUNNER_TEMP}/gh-publish.json" | jq --raw-output '.integrity' | tr -d '\n' ) > "${RUNNER_TEMP}/gh-hash.txt"
|
||||
cmp -s "${RUNNER_TEMP}/libhalo-npm-hash.txt" "${RUNNER_TEMP}/npmjs-hash.txt"
|
||||
cmp -s "${RUNNER_TEMP}/libhalo-npm-hash.txt" "${RUNNER_TEMP}/gh-hash.txt"
|
||||
- name: Upload release asset (npm hash)
|
||||
id: upload-release-asset-license
|
||||
uses: actions/upload-release-asset@v1
|
||||
|
||||
@@ -1 +1,128 @@
|
||||
# LibHaLo Build Audit Trail
|
||||
|
||||
> **Note:** This article is solely about verifying additional build signatures. If you are not concerned that much about the build process security, please feel free to skip that read.
|
||||
|
||||
Each workflow that gets executed on a GitHub-hosted runner has a short-lived [OpenID Connect (OIDC) token](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect) assigned by GitHub.
|
||||
This token contains essential information about the exact job that was run (commit identifier, git tag, name of the workflow, and other).
|
||||
|
||||
During the build process, we are using the tool which validates that OIDC token against the [Fulcio CA](https://www.chainguard.dev/unchained/a-fulcio-deep-dive).
|
||||
In turn, the CA is issuing an ephemeral X.509 certificate. Practically, the CA is just rewriting the information from the original OIDC token into the newly issued certificate.
|
||||
|
||||
Finally, we use that ephemeral certificates in order to additionally sign all release assets that are contained in the [arx-research/libhalo](https://github.com/arx-research/libhalo) repository. This technique is so-called as ["keyless signing"](https://www.chainguard.dev/unchained/zero-friction-keyless-signing-with-github-actions), and the exact tool that we are using is `cosign` (a part of "sigstore" project by The Linux Foundation).
|
||||
|
||||
## What does ephemeral certificate contain?
|
||||
|
||||
The ephemeral X.509 certificate has the following information asserted by the Fulcio CA:
|
||||
|
||||
* The base URL of the OIDC token, so that you can verify that the original OIDC token really came from GitHub-hosted runner (OID: `1.3.6.1.4.1.57264.1.1`);
|
||||
* Name of the GitHub repository (OID: `1.3.6.1.4.1.57264.1.5`);
|
||||
* The URL of the exact GitHub Actions workflow file that produced the artifact, together with the target tag name (X509v3 Subject Alternative Name);
|
||||
* Exact git commit hash for which the build was triggered (OID: `1.3.6.1.4.1.57264.1.3`);
|
||||
|
||||
Please note that the above list is not exhaustive, but we have listed the most essential components.
|
||||
|
||||
## Why does it matter?
|
||||
|
||||
Signatures made with ephemeral certificates consistute a proof of trust, which relies on GitHub and Fulcio CA (run by The Linux Foundation)
|
||||
that the build was produced by the automated process. Moreover, the real commit ID is cryptographically associated with
|
||||
the produced release assets, so you are able to review the accurate code snapshot and all the pipeline scripts as they were
|
||||
at the moment when the build was created. Thus, the builds are more reliable.
|
||||
|
||||
## File asset signatures
|
||||
|
||||
For each version, the build process will produce the following release assets, which could be downloaded
|
||||
using the "Releases" sub-page of this repository:
|
||||
|
||||
* `halocli-x64-win.zip` - HaLo Command Line Interface Tool (Windows x64)
|
||||
* `halocli-x64-linux.zip` - HaLo Command Line Interface Tool (Linux x64)
|
||||
* `halocli-x64-macos.pkg` - HaLo Command Line Interface Tool (Mac OS x64)
|
||||
* `libhalo.js` - standalone JavaScript library for usage with classic HTML applications;
|
||||
|
||||
Each of these assets is accompanied by the signature and certificate files in the format:
|
||||
|
||||
* `<asset name>-keyless.pem` - the ephemeral certificate produced by `cosign` tool;
|
||||
* `<asset name>-keyless.sig` - the signature made with that ephemeral certificate;
|
||||
|
||||
### Script: Verifying `halocli` build
|
||||
```bash
|
||||
|
||||
|
||||
cosign verify-blob \
|
||||
--signature "${BIN_NAME}-keyless.sig" \
|
||||
--certificate "${BIN_NAME}-keyless.sig" \
|
||||
--certificate-identity "https://github.com/arx-research/libhalo/.github/workflows/prod_build_cli.yml@refs/tags/${TAG_NAME}" \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
"${BIN_NAME}"
|
||||
```
|
||||
|
||||
### Script: Verifying `libhalo.js` build
|
||||
```
|
||||
prod_build_lib
|
||||
```
|
||||
|
||||
### Example
|
||||
Verifying `halocli-x64-win.zip` against automated build of version `libhalo-v1.1.1`:
|
||||
```bash
|
||||
cosign verify-blob \
|
||||
--signature halocli-x64-win.zip-keyless.sig \
|
||||
--certificate halocli-x64-win.zip-keyless.sig \
|
||||
--certificate-identity "https://github.com/arx-research/libhalo/.github/workflows/prod_build_cli.yml@refs/tags/libhalo-v1.1.1" \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
halocli-x64-win.zip
|
||||
```
|
||||
|
||||
## NPM package signatures
|
||||
|
||||
* `@arx-research/libhalo` package on npmjs.com
|
||||
* `@arx-research/libhalo` package on GitHub Packages
|
||||
|
||||
The published package semantic versions correspond to the releases marked `libhalo-v<semver>` on the "Releases" sub-page of this GitHub repository.
|
||||
Each corresponding release contains `libhalo-npm-hash.txt` file, which is an integrity hash (SHA512) of the published NPM package. This file also contains corresponding
|
||||
signature made with `cosign`:
|
||||
|
||||
* `libhalo-npm-hash.txt-keyless.pem` - the ephemeral certificate for the hash file;
|
||||
* `libhalo-npm-hash.txt-keyless.sig` - the signature made with that ephemeral certificate;
|
||||
|
||||
## Verification script
|
||||
In order to verify the keyless signatures, you will need to [install cosign tool](https://docs.sigstore.dev/cosign/installation/).
|
||||
|
||||
Please store the following example bash script:
|
||||
|
||||
**verify.sh**
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
WORKFLOW_NAME="$1"
|
||||
BIN_NAME="$2"
|
||||
TAG_NAME="$3"
|
||||
|
||||
cosign verify-blob \
|
||||
--signature "${BIN_NAME}-keyless.sig" \
|
||||
--certificate "${BIN_NAME}-keyless.sig" \
|
||||
--certificate-identity "https://github.com/arx-research/libhalo/.github/workflows/${WORKFLOW_NAME}.yml@refs/tags/${TAG_NAME}" \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
|
||||
"${BIN_NAME}"
|
||||
```
|
||||
|
||||
### Usage examples
|
||||
Verify `halocli-x64-win.zip` build against the automated build of version `libhalo-v1.1.1`:
|
||||
```
|
||||
./verify.sh prod_build_cli halocli-x64-win.zip libhalo-v1.1.1
|
||||
```
|
||||
|
||||
Verify `libhalo.js` build against the automated build of version `libhalo-v1.1.1`:
|
||||
```
|
||||
./verify.sh prod_build_lib libhalo.js libhalo-v1.1.1
|
||||
```
|
||||
|
||||
Verify the published NPM package hash against the automated build of version `libhalo-v1.1.1`:
|
||||
```
|
||||
# (1) get the integrity hash of your installed version
|
||||
npm view @arx-research/libhalo | grep integrity
|
||||
# (2) verify the hash file from "Releases" sub-page
|
||||
./verify.sh prod_build_lib libhalo-npm-hash.txt libhalo-v1.1.1
|
||||
# (3) compare if `libhalo-npm-hash.txt` is the same as (1)
|
||||
cat libhalo-npm-hash.txt
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user