WIP: enable signing with cosign

Signed-off-by: Jason Hall <jason@chainguard.dev>
pull/999/head
Jason Hall 2023-11-09 13:14:40 -05:00
parent fdf7f43ecf
commit 898ec8408f
Failed to extract signature
6 changed files with 98 additions and 3 deletions

View File

@ -28,6 +28,51 @@ env:
BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1 BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1
jobs: jobs:
minimal-sign:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v4
with:
path: action
-
name: Set up Cosign
uses: sigstore/cosign-installer@v3.2.0
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
driver-opts: |
network=host
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
-
name: Build and push
id: docker_build
uses: ./action
with:
file: ./test/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64
push: true
sign: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
minimal: minimal:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -36,6 +81,7 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
path: action path: action
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3

View File

@ -105,6 +105,10 @@ inputs:
description: "GitHub Token used to authenticate against a repository for Git context" description: "GitHub Token used to authenticate against a repository for Git context"
default: ${{ github.token }} default: ${{ github.token }}
required: false required: false
sign:
description: "If true, sign the image with the GitHub Actions identity using Cosign."
default: 'false'
required: false
outputs: outputs:
imageid: imageid:

2
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

View File

@ -38,6 +38,7 @@ export interface Inputs {
target: string; target: string;
ulimit: string[]; ulimit: string[];
githubToken: string; githubToken: string;
sign: boolean;
} }
export async function getInputs(): Promise<Inputs> { export async function getInputs(): Promise<Inputs> {
@ -72,7 +73,8 @@ export async function getInputs(): Promise<Inputs> {
tags: Util.getInputList('tags'), tags: Util.getInputList('tags'),
target: core.getInput('target'), target: core.getInput('target'),
ulimit: Util.getInputList('ulimit', {ignoreComma: true}), ulimit: Util.getInputList('ulimit', {ignoreComma: true}),
githubToken: core.getInput('github-token') githubToken: core.getInput('github-token'),
sign: core.getBooleanInput('sign')
}; };
} }

View File

@ -2,6 +2,7 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as stateHelper from './state-helper'; import * as stateHelper from './state-helper';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as io from '@actions/io';
import * as actionsToolkit from '@docker/actions-toolkit'; import * as actionsToolkit from '@docker/actions-toolkit';
import {Context} from '@docker/actions-toolkit/lib/context'; import {Context} from '@docker/actions-toolkit/lib/context';
import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
@ -104,6 +105,48 @@ actionsToolkit.run(
core.setOutput('metadata', metadata); core.setOutput('metadata', metadata);
}); });
} }
if (inputs.sign) {
// TODO: Check if `id-token: write` is specified and ID token is available.
// Check if cosign is installed.
const cosignAvailable = await io
.which('cosign', true)
.then(res => {
core.debug(`cosignAvailable ok: ${res}`);
return true;
})
.catch(error => {
core.debug(`cosignAvailable error: ${error}`);
return false;
});
if (!cosignAvailable) {
core.setFailed(`Cosign is required to sign. See https://github.com/sigstore/cosign-installer to set up cosign.`);
return;
}
await core.group(`Cosign version`, async () => {
await Exec.getExecOutput('cosign', ['version'], {
ignoreReturnCode: true
}).then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(`cosign version failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
}
});
});
if (!digest) {
throw new Error('Digest is required to sign.');
}
for (const img of inputs.tags) {
const ref = `${img}@${digest}`;
await core.group(`Signing image ${ref}`, async () => {
// TODO: Annotate with workflow run ID, etc, from env vars.
await Exec.exec('cosign', ['sign', ref, '--yes']);
});
}
}
}, },
// post // post
async () => { async () => {