1
0
mirror of https://github.com/siderolabs/kres.git synced 2026-02-05 09:45:35 +01:00

feat: sign with cosign checksums for release

produce signatures for verifying checksums

Signed-off-by: Caleb Woodbine <caleb.woodbine@siderolabs.com>
Signed-off-by: Noel Georgi <git@frezbo.dev>
This commit is contained in:
Caleb Woodbine
2025-05-22 16:23:10 +12:00
committed by Noel Georgi
parent 5128bc12f8
commit 880678f5a4
5 changed files with 97 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2025-06-02T14:41:29Z by kres 9f64b0d-dirty.
# Generated on 2025-07-02T13:16:29Z by kres 43deb91-dirty.
name: default
concurrency:
@@ -22,6 +22,7 @@ jobs:
permissions:
actions: read
contents: write
id-token: write
issues: read
packages: write
pull-requests: read
@@ -112,6 +113,13 @@ jobs:
PUSH: "true"
run: |
make image-kres IMAGE_TAG=latest
- name: Install Cosign
if: startsWith(github.ref, 'refs/tags/')
uses: sigstore/cosign-installer@v3
- name: Sign artifacts
if: startsWith(github.ref, 'refs/tags/')
run: |
find _out -type f -name _out/kres-* -exec cosign sign-blob --yes --output {}.sig {} \;
- name: Generate Checksums
if: startsWith(github.ref, 'refs/tags/')
run: |
@@ -131,3 +139,4 @@ jobs:
files: |-
_out/kres-*
_out/sha*.txt
_out/*.sig

View File

@@ -19,6 +19,10 @@ spec:
PLATFORM: linux/amd64,linux/arm64
entrypointArgs: ['gen']
---
kind: common.Release
spec:
generateSignatures: true
---
kind: golang.Build
spec:
outputs:

View File

@@ -256,6 +256,11 @@ func (o *Output) AddStep(jobName string, steps ...*JobStep) {
o.workflows[ciWorkflow].Jobs[jobName].Steps = append(o.workflows[ciWorkflow].Jobs[jobName].Steps, steps...)
}
// AddJobPermissions adds permissions to the job.
func (o *Output) AddJobPermissions(jobName, permission, value string) {
o.workflows[ciWorkflow].Jobs[jobName].Permissions[permission] = value
}
// AddStepBefore adds step before another step in the job.
func (o *Output) AddStepBefore(jobName, beforeStepID string, steps ...*JobStep) {
job := o.workflows[ciWorkflow].Jobs[jobName]

View File

@@ -79,10 +79,11 @@ type CoverageStep struct {
// ReleaseStep defines options for release steps.
type ReleaseStep struct {
BaseDirectory string `yaml:"baseDirectory"`
ReleaseNotes string `yaml:"releaseNotes"`
Artifacts []string `yaml:"artifacts"`
GenerateChecksums bool `yaml:"generateChecksums"`
BaseDirectory string `yaml:"baseDirectory"`
ReleaseNotes string `yaml:"releaseNotes"`
Artifacts []string `yaml:"artifacts"`
GenerateChecksums bool `yaml:"generateChecksums"`
GenerateSignatures bool `yaml:"generateSignatures"`
}
// RegistryLoginStep defines options for registry login steps.
@@ -281,7 +282,29 @@ func (gh *GHWorkflow) CompileGitHubWorkflow(o *ghworkflow.Output) error {
SetWith("draft", "true").
SetWith("files", strings.Join(artifacts, "\n"))
if step.ReleaseStep.GenerateSignatures {
jobDef.Permissions["id-token"] = "write"
cosignStep := ghworkflow.Step("Install Cosign").
SetUses("sigstore/cosign-installer@" + config.CosignInstallActionVerson)
jobDef.Steps = append(jobDef.Steps, cosignStep)
signCommands := xslices.Map(artifacts, func(artifact string) string {
return fmt.Sprintf("cosign sign-blob --output %s.sig --yes %s", artifact, artifact)
})
signStep := ghworkflow.Step("Sign artifacts").
SetCommand(strings.Join(signCommands, "\n"))
jobDef.Steps = append(jobDef.Steps, signStep)
releaseStep.SetWith("files", strings.Join(artifacts, "\n")+"\n"+filepath.Join(step.ReleaseStep.BaseDirectory, "*.sig"))
}
if step.ReleaseStep.GenerateChecksums {
jobDef.Permissions["id-token"] = "write"
checkSumCommands := []string{
fmt.Sprintf("cd %s", step.ReleaseStep.BaseDirectory),
fmt.Sprintf("sha256sum %s > %s", strings.Join(step.ReleaseStep.Artifacts, " "), "sha256sum.txt"),
@@ -291,10 +314,29 @@ func (gh *GHWorkflow) CompileGitHubWorkflow(o *ghworkflow.Output) error {
checkSumStep := ghworkflow.Step("Generate Checksums").
SetCommand(strings.Join(checkSumCommands, "\n"))
jobDef.Steps = append(jobDef.Steps, checkSumStep)
releaseStep.
SetWith("files", strings.Join(artifacts, "\n")+"\n"+filepath.Join(step.ReleaseStep.BaseDirectory, "sha*.txt"))
jobDef.Steps = append(jobDef.Steps, checkSumStep)
if step.ReleaseStep.GenerateSignatures {
checkSumSignCommands := []string{
"cosign sign-blob --output sha256sum.txt.sig --yes sha256sum.txt",
"cosign sign-blob --output sha512sum.txt.sig --yes sha512sum.txt",
}
signStep := ghworkflow.Step("Sign checksums").
SetCommand(strings.Join(checkSumSignCommands, "\n"))
jobDef.Steps = append(jobDef.Steps, signStep)
releaseStep.SetWith("files",
strings.Join(artifacts, "\n")+
"\n"+
filepath.Join(step.ReleaseStep.BaseDirectory, "sha*.txt")+"\n"+
filepath.Join(step.ReleaseStep.BaseDirectory, "*.sig"),
)
}
}
jobDef.Steps = append(jobDef.Steps, releaseStep)

View File

@@ -27,7 +27,8 @@ type Release struct {
// List of file patterns relative to the ArtifactsPath to include in the release.
//
// If not specified, defaults to the auto-detected commands.
Artifacts []string `yaml:"artifacts"`
Artifacts []string `yaml:"artifacts"`
GenerateSignatures bool `yaml:"generateSignatures,omitempty"`
}
// NewRelease initializes Release.
@@ -88,7 +89,35 @@ func (release *Release) CompileGitHubWorkflow(output *ghworkflow.Output) error {
checkSumStep := ghworkflow.Step("Generate Checksums").
SetCommand(strings.Join(checkSumCommands, "\n"))
releaseStep.SetWith("files", strings.Join(artifacts, "\n")+"\n"+filepath.Join(release.meta.ArtifactsPath, "sha*.txt"))
artifactsToUpload := strings.Join(artifacts, "\n") + "\n" + filepath.Join(release.meta.ArtifactsPath, "sha*.txt")
if release.GenerateSignatures {
output.AddJobPermissions("default", "id-token", "write")
cosignStep := ghworkflow.Step("Install Cosign").
SetUses("sigstore/cosign-installer@" + config.CosignInstallActionVerson)
if err := cosignStep.SetConditions("only-on-tag"); err != nil {
return err
}
signCommands := xslices.Map(artifacts, func(artifact string) string {
return fmt.Sprintf("find %s -type f -name %s -exec cosign sign-blob --yes --output {}.sig {} \\;", release.meta.ArtifactsPath, artifact)
})
signStep := ghworkflow.Step("Sign artifacts").
SetCommand(strings.Join(signCommands, "\n"))
if err := signStep.SetConditions("only-on-tag"); err != nil {
return err
}
steps = append(steps, cosignStep, signStep)
artifactsToUpload += "\n" + filepath.Join(release.meta.ArtifactsPath, "*.sig")
}
releaseStep.SetWith("files", artifactsToUpload)
if err := checkSumStep.SetConditions("only-on-tag"); err != nil {
return err