Skip to content

Commit e66a6f8

Browse files
authored
Merge pull request #14 from pjbgf-forks/fixes
Add support for OBS signed images
2 parents 6c0550e + b05e311 commit e66a6f8

File tree

10 files changed

+158
-20
lines changed

10 files changed

+158
-20
lines changed

.github/workflows/release.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ jobs:
2727
with:
2828
go-version: stable
2929

30-
- uses: anchore/sbom-action/download-syft@55dc4ee22412511ee8c3142cbea40418e6cec693 # v0.17.8
3130
- uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
3231

3332
- name: Run GoReleaser

.github/workflows/tests.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ name: Tests
22

33
on:
44
push:
5+
pull_request:
6+
workflow_dispatch:
57

6-
permissions:
7-
contents: read
8+
permissions: {}
89

910
jobs:
1011
test:
@@ -20,3 +21,21 @@ jobs:
2021

2122
- run: make test
2223
- run: make verify
24+
25+
e2e:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4
30+
31+
- uses: ./actions/install-slsactl
32+
- run: make e2e
33+
34+
test-verify-action:
35+
runs-on: ubuntu-latest
36+
steps:
37+
- name: Checkout code
38+
uses: actions/checkout@v4
39+
- uses: ./actions/verify
40+
with:
41+
image: ghcr.io/kubewarden/policy-server:v1.19.0

.goreleaser.yaml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,6 @@ source:
4040
enabled: true
4141
name_template: '{{ .ProjectName }}_{{ .Version }}_source'
4242

43-
sboms:
44-
- id: source
45-
artifacts: source
46-
documents:
47-
- '{{ .ProjectName }}_{{ .Version }}_sbom.spdx.json'
48-
4943
release:
5044
extra_files:
5145
- glob: ./**/*.bundle

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ build:
88
test:
99
go test -race ./...
1010

11+
e2e:
12+
./hack/e2e.sh
13+
1114
verify: verify-lint verify-dirty ## Run verification checks.
1215

1316
verify-lint: $(GOLANGCI)

actions/install-slsactl/action.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This GitHub action install the slsactl CLI, making it available for
2+
# other steps within an GitHub workflow to refer to it.
3+
#
4+
# Reference usage:
5+
# steps:
6+
# ...
7+
# - uses: rancherlabs/slsactl/actions/install-slsactl@main
8+
# with:
9+
# version: latest
10+
11+
name: install-slsactl
12+
13+
inputs:
14+
version:
15+
description: |
16+
The slsactl version to be installed.
17+
required: false
18+
default: latest
19+
type: string
20+
21+
runs:
22+
using: composite
23+
24+
steps:
25+
- uses: actions/setup-go@v5
26+
with:
27+
go-version: 'stable'
28+
29+
- name: Install slsactl
30+
shell:
31+
run: |
32+
go install github.com/rancherlabs/slsactl@${{ inputs.version }}

actions/verify/action.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@ runs:
2929
with:
3030
go-version: 'stable'
3131

32-
- name: Install slsactl
33-
shell:
34-
run: |
35-
go install github.com/rancherlabs/slsactl@latest
32+
- uses: ./actions/install-slsactl
3633

3734
- name: Verify image
3835
shell: bash

hack/e2e.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
set -eox pipefail
4+
5+
IMAGE=${IMAGE:-ghcr.io/kubewarden/policy-server:v1.19.0}
6+
7+
slsactl verify "${IMAGE}"
8+
slsactl download provenance "${IMAGE}"
9+
slsactl download provenance --format=slsav1 "${IMAGE}"
10+
slsactl download sbom "${IMAGE}"
11+
slsactl download sbom -format cyclonedxjson "${IMAGE}"
12+
slsactl version

pkg/verify/mapping.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
package verify
22

3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
38
// imageRepo holds the mappings between container image and source code repositories.
49
var imageRepo = map[string]string{
510
"rancher/rke2-runtime": "rancher/rke2",
@@ -20,3 +25,25 @@ var imageRepo = map[string]string{
2025
"rancher/nginx-ingress-controller": "rancher/ingress-nginx",
2126
"rancher/rancher": "rancher/rancher-prime",
2227
}
28+
29+
var obs = map[string]struct{}{
30+
"rancher/elemental-operator": {},
31+
"rancher/seedimage-builder": {},
32+
"rancher/elemental-channel/sl-micro": {},
33+
"rancher/elemental-operator-crds-chart": {},
34+
"rancher/elemental-operator-chart": {},
35+
}
36+
37+
func obsSigned(image string) bool {
38+
bef, after, _ := strings.Cut(image, "/")
39+
if strings.Contains(bef, ".") {
40+
image = after
41+
}
42+
43+
bef, _, _ = strings.Cut(image, ":")
44+
image = bef
45+
fmt.Println(image)
46+
47+
_, ok := obs[image]
48+
return ok
49+
}

pkg/verify/verify.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto"
66
"fmt"
7+
"log/slog"
78
"os"
89
"strings"
910
"time"
@@ -13,7 +14,12 @@ import (
1314
"github.com/sigstore/cosign/v2/cmd/cosign/cli/verify"
1415
)
1516

16-
const timeout = 45 * time.Second
17+
const (
18+
timeout = 45 * time.Second
19+
maxWorkers = 5
20+
hashAlgo = crypto.SHA256
21+
obsKey = "https://ftp.suse.com/pub/projects/security/keys/container-key.pem"
22+
)
1723

1824
var archSuffixes = []string{
1925
"-linux-amd64",
@@ -30,11 +36,38 @@ var archSuffixes = []string{
3036
//
3137
// Upstream documentation:
3238
// https://github.com/sigstore/cosign/blob/main/specs/SIGNATURE_SPEC.md
33-
func Verify(imageName string) error {
39+
func Verify(image string) error {
3440
ctx, cancel := context.WithTimeout(context.Background(), timeout)
3541
defer cancel()
3642

37-
certIdentity, err := certIdentity(imageName)
43+
if obsSigned(image) {
44+
return verifyObs(ctx, image)
45+
}
46+
47+
return verifyKeyless(ctx, image)
48+
}
49+
50+
func verifyObs(ctx context.Context, image string) error {
51+
slog.Debug("OBS verification")
52+
v := &verify.VerifyCommand{
53+
KeyRef: obsKey,
54+
RekorURL: options.DefaultRekorURL,
55+
CertRef: obsKey,
56+
CheckClaims: true,
57+
HashAlgorithm: hashAlgo,
58+
MaxWorkers: maxWorkers,
59+
}
60+
61+
if strings.EqualFold(os.Getenv("DEBUG"), "true") {
62+
logs.Debug.SetOutput(os.Stderr)
63+
}
64+
65+
return v.Exec(ctx, []string{image})
66+
}
67+
68+
func verifyKeyless(ctx context.Context, image string) error {
69+
slog.Info("GHA keyless verification")
70+
certIdentity, err := certIdentity(image)
3871
if err != nil {
3972
return err
4073
}
@@ -47,15 +80,15 @@ func Verify(imageName string) error {
4780
CertOidcIssuer: "https://token.actions.githubusercontent.com",
4881
},
4982
CheckClaims: true,
50-
HashAlgorithm: crypto.SHA256,
51-
MaxWorkers: 5,
83+
HashAlgorithm: hashAlgo,
84+
MaxWorkers: maxWorkers,
5285
}
5386

5487
if strings.EqualFold(os.Getenv("DEBUG"), "true") {
5588
logs.Debug.SetOutput(os.Stderr)
5689
}
5790

58-
return v.Exec(ctx, []string{imageName})
91+
return v.Exec(ctx, []string{image})
5992
}
6093

6194
func certIdentity(imageName string) (string, error) {

pkg/verify/verify_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ func TestCertificateIdentity(t *testing.T) {
9393
}
9494

9595
for _, tc := range tests {
96-
tc := tc
9796
t.Run(tc.image, func(t *testing.T) {
9897
t.Parallel()
9998

@@ -109,3 +108,26 @@ func TestCertificateIdentity(t *testing.T) {
109108
})
110109
}
111110
}
111+
112+
func TestObsSigned(t *testing.T) {
113+
t.Parallel()
114+
115+
tests := []struct {
116+
image string
117+
want bool
118+
}{
119+
{image: "rancher/elemental-operator", want: true},
120+
{image: "rancher/seedimage-builder", want: true},
121+
{image: "rancher/elemental-channel/sl-micro", want: true},
122+
{image: "rancher/elemental-operator-crds-chart", want: true},
123+
{image: "rancher/elemental-operator-chart", want: true},
124+
{image: "rancher/rancher"},
125+
{image: "ghcr.io/kubewarden/policy-server"},
126+
{image: "fuzz/bar"},
127+
}
128+
129+
for _, tc := range tests {
130+
got := obsSigned(tc.image)
131+
assert.Equal(t, tc.want, got)
132+
}
133+
}

0 commit comments

Comments
 (0)