Skip to content

Commit fa17fab

Browse files
authored
Refactor KMS E2E tests (#3684)
* Move KMS tests from shell script to Go test suite Signed-off-by: Colleen Murphy <[email protected]> * Make KMS E2E tests hermetic Use the scaffolding setup action to set up a local sigstore cluster and run the KMS tests against the local rekor instance instead of the public, production instance. Signed-off-by: Colleen Murphy <[email protected]> * Move KMS E2E workflow into main e2e-tests file Condense the E2E tests into fewer workflow files. There are no unique conditions that require them to be in separate files. Condensing them makes them easier to discover, and makes the Actions tab in GitHub cleaner because there are fewer workflows to sort through. Signed-off-by: Colleen Murphy <[email protected]> --------- Signed-off-by: Colleen Murphy <[email protected]>
1 parent e9a3739 commit fa17fab

File tree

5 files changed

+189
-110
lines changed

5 files changed

+189
-110
lines changed

.github/workflows/e2e-tests-kms.yml

Lines changed: 0 additions & 72 deletions
This file was deleted.

.github/workflows/e2e-tests.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,49 @@ jobs:
6161
- name: Run pkcs11 end-to-end tests
6262
shell: bash
6363
run: ./test/e2e_test_pkcs11.sh
64+
65+
e2e-kms:
66+
runs-on: ubuntu-latest
67+
services:
68+
vault:
69+
image: hashicorp/vault:latest
70+
env:
71+
VAULT_DEV_ROOT_TOKEN_ID: root
72+
options: >-
73+
--health-cmd "VAULT_ADDR=http://127.0.0.1:8200 vault status"
74+
--health-interval 1s
75+
--health-timeout 5s
76+
--health-retries 5
77+
--restart always
78+
ports:
79+
- 8200:8200
80+
81+
env:
82+
VAULT_TOKEN: "root"
83+
VAULT_ADDR: "http://localhost:8200"
84+
COSIGN_YES: "true"
85+
SCAFFOLDING_RELEASE_VERSION: "v0.6.17"
86+
steps:
87+
- name: Checkout
88+
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
89+
- uses: cpanato/vault-installer@ac6d910a90d64f78ef773afe83887a35c95245c6 # v1.0.3
90+
with:
91+
vault-release: '1.14.1'
92+
93+
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
94+
with:
95+
go-version: '1.21'
96+
check-latest: true
97+
98+
- uses: imjasonh/setup-crane@00c9e93efa4e1138c9a7a5c594acd6c75a2fbf0c # v0.3
99+
100+
- name: Install cluster + sigstore
101+
uses: sigstore/scaffolding/actions/setup@main
102+
with:
103+
version: ${{ env.SCAFFOLDING_RELEASE_VERSION }}
104+
105+
- name: enable vault transit
106+
run: vault secrets enable transit
107+
108+
- name: Acceptance Tests
109+
run: go test -tags=e2e,kms -v ./test/...

test/e2e_kms_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2024 The Sigstore Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build e2e && kms
16+
17+
package test
18+
19+
import (
20+
"context"
21+
"os"
22+
"path"
23+
"testing"
24+
25+
"github.com/sigstore/cosign/v2/cmd/cosign/cli/generate"
26+
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
27+
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
28+
"github.com/sigstore/cosign/v2/pkg/cosign/env"
29+
_ "github.com/sigstore/sigstore/pkg/signature/kms/hashivault"
30+
)
31+
32+
const (
33+
rekorURLVar = "REKOR_URL"
34+
testKMSVar = "TEST_KMS"
35+
defaultKMS = "hashivault://transit"
36+
)
37+
38+
func TestSecretsKMS(t *testing.T) {
39+
ctx := context.Background()
40+
41+
repo, stop := reg(t)
42+
defer stop()
43+
td := t.TempDir()
44+
45+
imgName := path.Join(repo, "cosign-attach-e2e")
46+
_, _, cleanup := mkimage(t, imgName)
47+
defer cleanup()
48+
49+
kms := os.Getenv(testKMSVar)
50+
if kms == "" {
51+
kms = defaultKMS
52+
}
53+
54+
prefix := path.Join(td, "test-kms")
55+
56+
must(generate.GenerateKeyPairCmd(ctx, kms, prefix, nil), t)
57+
58+
pubKey := prefix + ".pub"
59+
privKey := kms
60+
61+
// Verify should fail at first
62+
mustErr(verify(pubKey, imgName, true, nil, "", false), t)
63+
64+
rekorURL := os.Getenv(rekorURLVar)
65+
66+
must(downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), td), t)
67+
68+
// Now sign and verify with the KMS key
69+
ko := options.KeyOpts{
70+
KeyRef: privKey,
71+
RekorURL: rekorURL,
72+
SkipConfirmation: true,
73+
}
74+
so := options.SignOptions{
75+
Upload: true,
76+
TlogUpload: true,
77+
}
78+
must(sign.SignCmd(ro, ko, so, []string{imgName}), t)
79+
must(verify(pubKey, imgName, true, nil, "", false), t)
80+
81+
// Sign and verify with annotations
82+
mustErr(verify(pubKey, imgName, true, map[string]any{"foo": "bar"}, "", false), t)
83+
soAnno := options.SignOptions{
84+
Upload: true,
85+
TlogUpload: true,
86+
AnnotationOptions: options.AnnotationOptions{
87+
Annotations: []string{"foo=bar"},
88+
},
89+
}
90+
must(sign.SignCmd(ro, ko, soAnno, []string{imgName}), t)
91+
must(verify(pubKey, imgName, true, map[string]any{"foo": "bar"}, "", false), t)
92+
93+
// Store signatures in a different repo
94+
t.Setenv("COSIGN_REPOSITORY", path.Join(repo, "subbedrepo"))
95+
must(sign.SignCmd(ro, ko, so, []string{imgName}), t)
96+
must(verify(pubKey, imgName, true, nil, "", false), t)
97+
os.Unsetenv("COSIGN_REPOSITORY")
98+
}

test/e2e_test.go

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
//go:build e2e && !cross
16+
//go:build e2e && !cross && !kms
1717

1818
package test
1919

@@ -2201,40 +2201,3 @@ func getOIDCToken() (string, error) {
22012201
}
22022202
return string(body), nil
22032203
}
2204-
2205-
func setLocalEnv(t *testing.T, dir string) error {
2206-
// fulcio repo is downloaded to the user's home directory by e2e_test.sh
2207-
home, err := os.UserHomeDir()
2208-
if err != nil {
2209-
return fmt.Errorf("error getting home directory: %w", err)
2210-
}
2211-
t.Setenv(env.VariableSigstoreCTLogPublicKeyFile.String(), path.Join(home, "fulcio/config/ctfe/pubkey.pem"))
2212-
err = downloadAndSetEnv(t, fulcioURL+"/api/v1/rootCert", env.VariableSigstoreRootFile.String(), dir)
2213-
if err != nil {
2214-
return fmt.Errorf("error setting %s env var: %w", env.VariableSigstoreRootFile.String(), err)
2215-
}
2216-
err = downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), dir)
2217-
if err != nil {
2218-
return fmt.Errorf("error setting %s env var: %w", env.VariableSigstoreRekorPublicKey.String(), err)
2219-
}
2220-
return nil
2221-
}
2222-
2223-
func downloadAndSetEnv(t *testing.T, url, envVar, dir string) error {
2224-
resp, err := http.Get(url)
2225-
if err != nil {
2226-
return fmt.Errorf("error downloading file: %w", err)
2227-
}
2228-
defer resp.Body.Close()
2229-
f, err := os.CreateTemp(dir, "")
2230-
if err != nil {
2231-
return fmt.Errorf("error creating temp file: %w", err)
2232-
}
2233-
defer f.Close()
2234-
_, err = io.Copy(f, resp.Body)
2235-
if err != nil {
2236-
return fmt.Errorf("error writing to file: %w", err)
2237-
}
2238-
t.Setenv(envVar, f.Name())
2239-
return nil
2240-
}

test/helpers.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ package test
2020
import (
2121
"context"
2222
"crypto"
23+
"fmt"
24+
"io"
25+
"net/http"
2326
"net/http/httptest"
2427
"net/url"
2528
"os"
29+
"path"
2630
"path/filepath"
2731
"testing"
2832

@@ -39,6 +43,7 @@ import (
3943
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
4044
cliverify "github.com/sigstore/cosign/v2/cmd/cosign/cli/verify"
4145
"github.com/sigstore/cosign/v2/pkg/cosign"
46+
"github.com/sigstore/cosign/v2/pkg/cosign/env"
4247
ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote"
4348
sigs "github.com/sigstore/cosign/v2/pkg/signature"
4449
)
@@ -372,3 +377,42 @@ func registryClientOpts(ctx context.Context) []remote.Option {
372377
remote.WithContext(ctx),
373378
}
374379
}
380+
381+
// setLocalEnv sets SIGSTORE_CT_LOG_PUBLIC_KEY_FILE, SIGSTORE_ROOT_FILE, and SIGSTORE_REKOR_PUBLIC_KEY for the locally running sigstore deployment.
382+
func setLocalEnv(t *testing.T, dir string) error {
383+
// fulcio repo is downloaded to the user's home directory by e2e_test.sh
384+
home, err := os.UserHomeDir()
385+
if err != nil {
386+
return fmt.Errorf("error getting home directory: %w", err)
387+
}
388+
t.Setenv(env.VariableSigstoreCTLogPublicKeyFile.String(), path.Join(home, "fulcio/config/ctfe/pubkey.pem"))
389+
err = downloadAndSetEnv(t, fulcioURL+"/api/v1/rootCert", env.VariableSigstoreRootFile.String(), dir)
390+
if err != nil {
391+
return fmt.Errorf("error setting %s env var: %w", env.VariableSigstoreRootFile.String(), err)
392+
}
393+
err = downloadAndSetEnv(t, rekorURL+"/api/v1/log/publicKey", env.VariableSigstoreRekorPublicKey.String(), dir)
394+
if err != nil {
395+
return fmt.Errorf("error setting %s env var: %w", env.VariableSigstoreRekorPublicKey.String(), err)
396+
}
397+
return nil
398+
}
399+
400+
// downloadAndSetEnv fetches a URL and sets the given environment variable to point to the downloaded file path.
401+
func downloadAndSetEnv(t *testing.T, url, envVar, dir string) error {
402+
resp, err := http.Get(url)
403+
if err != nil {
404+
return fmt.Errorf("error downloading file: %w", err)
405+
}
406+
defer resp.Body.Close()
407+
f, err := os.CreateTemp(dir, "")
408+
if err != nil {
409+
return fmt.Errorf("error creating temp file: %w", err)
410+
}
411+
defer f.Close()
412+
_, err = io.Copy(f, resp.Body)
413+
if err != nil {
414+
return fmt.Errorf("error writing to file: %w", err)
415+
}
416+
t.Setenv(envVar, f.Name())
417+
return nil
418+
}

0 commit comments

Comments
 (0)