Skip to content

Commit

Permalink
feat: Validating cached binaries (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
IAreKyleW00t authored Sep 18, 2024
1 parent 8a6b9f6 commit 0371370
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 145 deletions.
40 changes: 7 additions & 33 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,6 @@ on:
- main

jobs:
test-cosign:
name: Test cosign
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
os: [macos, ubuntu, windows]
verify: [true, false]
permissions:
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Install Cosign
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0

- name: Setup regctl
id: regctl
uses: ./
with:
verify: ${{ matrix.verify }}
cache: false

- name: Test regctl
shell: bash
run: |
if ! which regctl ; then
echo "::error::regctl not found in PATH"
exit 1
fi
test-version:
name: Test version
runs-on: ${{ matrix.os }}-latest
Expand Down Expand Up @@ -159,19 +127,24 @@ jobs:
fi
test-cache:
name: Test cache
name: Test cache & cosign
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
os: [macos, ubuntu, windows]
cache: [true, false]
verify: [true, false]
permissions:
contents: read
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Install Cosign
if: matrix.verify
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0

- name: Setup regctl (cache)
if: matrix.cache == true
uses: ./
Expand All @@ -181,6 +154,7 @@ jobs:
uses: ./
with:
cache: ${{ matrix.cache }}
verify: ${{ matrix.verify }}

- name: Test regctl
shell: bash
Expand Down
91 changes: 48 additions & 43 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

34 changes: 13 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

101 changes: 54 additions & 47 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,70 +60,77 @@ export async function run(): Promise<void> {
// Check if regctl is already in the tool-cache
const cache = core.getInput('cache')
core.debug('Checking regctl cache')
let mainCachePath = tc.find('regctl', version.substring(1))
core.setOutput('cache-hit', cache && !!mainCachePath)
if (!mainCachePath || !cache) {
let mainPath = tc.find('regctl', version.substring(1))
core.setOutput('cache-hit', cache && !!mainPath)

let mainBin
if (!mainPath || !cache) {
// Download regctl into tmpDir
core.info('⏬ Downloading regctl')
const mainBin = await utils.downloadReleaseArtifact(
mainBin = await utils.downloadReleaseArtifact(
version,
ARTIFACT_NAME,
path.join(tmpDir, BIN_NAME)
)
fs.chmodSync(mainBin, 0o755)
} else {
core.info('📥 Loaded from runner cache')
mainBin = path.join(mainPath, BIN_NAME)
}

// Verify regctl if cosign is in the PATH (unless told to skip)
const cosign = await io.which('cosign')
if (core.getBooleanInput('verify') && cosign) {
// Download release metadata into tmpDir
core.info('🔏 Downloading signature metadata')
const metadataTar = await utils.downloadReleaseArtifact(
version,
'metadata.tgz',
path.join(tmpDir, 'metadata.tgz')
)
// Verify regctl if cosign is in the PATH (unless told to skip)
const cosign = await io.which('cosign')
if (core.getBooleanInput('verify') && cosign) {
// Download release metadata into tmpDir
core.info('🔏 Downloading signature metadata')
const metadataTar = await utils.downloadReleaseArtifact(
version,
'metadata.tgz',
path.join(tmpDir, 'metadata.tgz')
)

// Extract metadata
const metadataDir = await tc.extractTar(
metadataTar,
path.join(tmpDir, 'metadata')
)
// Extract metadata
const metadataDir = await tc.extractTar(
metadataTar,
path.join(tmpDir, 'metadata')
)

// Validate binary against downloaded signature
// This will display stdout and stderr automatically
core.info('🔍 Verifying signature')
try {
// This will exit 1 on error and display stdout and stderr automatically
await exec.getExecOutput(cosign, [
'verify-blob',
'--certificate-oidc-issuer',
'https://token.actions.githubusercontent.com',
'--certificate-identity-regexp',
'https://github.com/regclient/regclient/.github/workflows/',
'--certificate',
path.join(metadataDir, `regctl-${OS}-${ARCH}.pem`),
'--signature',
path.join(metadataDir, `regctl-${OS}-${ARCH}.sig`),
mainBin
])
} catch (error) {
core.debug(error instanceof Error ? error.message : (error as string))
throw Error('regctl signature verification failed')
}
core.info('✅ Signature verified')
} else core.info('⏭️ Skipped signature verification')
// Validate binary against downloaded signature
// This will display stdout and stderr automatically
core.info('🔍 Verifying signature')
try {
// This will exit 1 on error and display stdout and stderr automatically
await exec.getExecOutput(cosign, [
'verify-blob',
'--certificate-oidc-issuer',
'https://token.actions.githubusercontent.com',
'--certificate-identity-regexp',
'https://github.com/regclient/regclient/.github/workflows/',
'--certificate',
path.join(metadataDir, `regctl-${OS}-${ARCH}.pem`),
'--signature',
path.join(metadataDir, `regctl-${OS}-${ARCH}.sig`),
mainBin
])
} catch (error) {
core.debug(error instanceof Error ? error.message : (error as string))
throw Error('regctl signature verification failed')
}
core.info('✅ Signature verified')
} else core.info('⏭️ Skipped signature verification')

// Cache the regctl download
mainCachePath = await tc.cacheFile(
// Cache the regctl download if it was not already in the cache
if (!mainPath) {
mainPath = await tc.cacheFile(
mainBin,
BIN_NAME,
'regctl',
version.substring(1) // remove leading 'v'
)
} else core.info('📥 Loaded from runner cache')
}

// Add the cached regctl to our PATH
core.addPath(mainCachePath)
// Add regctl to our PATH
core.addPath(mainPath)
core.info('🎉 regctl is ready')
} catch (error) {
if (error instanceof Error) core.setFailed(error.message)
Expand Down

0 comments on commit 0371370

Please sign in to comment.