Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update cosign to v2 #1096

Merged
merged 2 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 54 additions & 98 deletions go.mod

Large diffs are not rendered by default.

975 changes: 123 additions & 852 deletions go.sum

Large diffs are not rendered by default.

43 changes: 23 additions & 20 deletions internal/controller/helmchart_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path"
Expand All @@ -34,9 +33,9 @@ import (
"time"

. "github.com/onsi/gomega"
coptions "github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/pkg/cosign"
coptions "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/v2/pkg/cosign"
hchart "helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
helmreg "helm.sh/helm/v3/pkg/registry"
Expand Down Expand Up @@ -1058,7 +1057,8 @@ func TestHelmChartReconciler_buildFromOCIHelmRepository(t *testing.T) {
)

// Load a test chart
chartData, err := ioutil.ReadFile(chartPath)
chartData, err := os.ReadFile(chartPath)
g.Expect(err).NotTo(HaveOccurred())

// Upload the test chart
metadata, err := loadTestChartToOCI(chartData, chartPath, testRegistryServer)
Expand Down Expand Up @@ -2333,16 +2333,16 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_authStrategy(t *testing.T) {

builder := fakeclient.NewClientBuilder().WithScheme(testEnv.GetScheme())
workspaceDir := t.TempDir()
server, err := setupRegistryServer(ctx, workspaceDir, tt.registryOpts)

server, err := setupRegistryServer(ctx, workspaceDir, tt.registryOpts)
g.Expect(err).NotTo(HaveOccurred())

// Load a test chart
chartData, err := ioutil.ReadFile(chartPath)
chartData, err := os.ReadFile(chartPath)
g.Expect(err).ToNot(HaveOccurred())

// Upload the test chart
metadata, err := loadTestChartToOCI(chartData, chartPath, server)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(err).ToNot(HaveOccurred())

repo := &helmv1.HelmRepository{
Expand Down Expand Up @@ -2452,7 +2452,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
)

// Load a test chart
chartData, err := ioutil.ReadFile(chartPath)
chartData, err := os.ReadFile(chartPath)
g.Expect(err).ToNot(HaveOccurred())

// Upload the test chart
metadata, err := loadTestChartToOCI(chartData, chartPath, server)
Expand Down Expand Up @@ -2504,10 +2505,10 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
},
want: sreconcile.ResultEmpty,
wantErr: true,
wantErrMsg: "chart verification error: failed to verify <url>: no matching signatures:",
wantErrMsg: "chart verification error: failed to verify <url>: no signatures found for image",
assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.BuildFailedCondition, "ChartVerificationError", "chart verification error: failed to verify <url>: no matching signatures:"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "chart verification error: failed to verify <url>: no matching signatures:"),
*conditions.TrueCondition(sourcev1.BuildFailedCondition, "ChartVerificationError", "chart verification error: failed to verify <url>: no signatures found for image"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "chart verification error: failed to verify <url>: no signatures found for image"),
},
},
{
Expand All @@ -2522,8 +2523,8 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
want: sreconcile.ResultEmpty,
wantErr: true,
assertConditions: []metav1.Condition{
*conditions.TrueCondition(sourcev1.BuildFailedCondition, "ChartVerificationError", "chart verification error: failed to verify <url>: no matching signatures:"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "chart verification error: failed to verify <url>: no matching signatures:"),
*conditions.TrueCondition(sourcev1.BuildFailedCondition, "ChartVerificationError", "chart verification error: failed to verify <url>: no signatures found for image"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "chart verification error: failed to verify <url>: no signatures found for image"),
},
},
{
Expand Down Expand Up @@ -2633,11 +2634,13 @@ func TestHelmChartReconciler_reconcileSourceFromOCI_verifySignature(t *testing.T
Timeout: timeout,
}

err = sign.SignCmd(ro, ko, coptions.RegistryOptions{Keychain: oci.Anonymous{}},
nil, []string{fmt.Sprintf("%s/testrepo/%s:%s", server.registryHost, metadata.Name, metadata.Version)}, "",
"", true, "",
"", "", false,
false, "", false)
err = sign.SignCmd(ro, ko, coptions.SignOptions{
Upload: true,
SkipConfirmation: true,
TlogUpload: false,
Registry: coptions.RegistryOptions{Keychain: oci.Anonymous{}, AllowInsecure: true},
},
[]string{fmt.Sprintf("%s/testrepo/%s:%s", server.registryHost, metadata.Name, metadata.Version)})
g.Expect(err).ToNot(HaveOccurred())
}

Expand Down Expand Up @@ -2694,7 +2697,7 @@ func loadTestChartToOCI(chartData []byte, chartPath string, server *registryClie
}

// Load a test chart
chartData, err = ioutil.ReadFile(chartPath)
chartData, err = os.ReadFile(chartPath)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/ocirepository_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"time"

"github.com/Masterminds/semver/v3"
soci "github.com/fluxcd/source-controller/internal/oci"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/authn/k8schain"
"github.com/google/go-containerregistry/pkg/crane"
Expand Down Expand Up @@ -69,6 +68,7 @@ import (
sourcev1 "github.com/fluxcd/source-controller/api/v1"
ociv1 "github.com/fluxcd/source-controller/api/v1beta2"
serror "github.com/fluxcd/source-controller/internal/error"
soci "github.com/fluxcd/source-controller/internal/oci"
sreconcile "github.com/fluxcd/source-controller/internal/reconcile"
"github.com/fluxcd/source-controller/internal/reconcile/summarize"
"github.com/fluxcd/source-controller/internal/util"
Expand Down
23 changes: 14 additions & 9 deletions internal/controller/ocirepository_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ import (
gcrv1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
. "github.com/onsi/gomega"
coptions "github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/pkg/cosign"
coptions "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
"github.com/sigstore/cosign/v2/pkg/cosign"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -1095,7 +1095,7 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
assertConditions: []metav1.Condition{
*conditions.TrueCondition(meta.ReconcilingCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
*conditions.UnknownCondition(meta.ReadyCondition, meta.ProgressingReason, "building artifact: new revision '<revision>' for '<url>'"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no matching signatures"),
*conditions.FalseCondition(sourcev1.SourceVerifiedCondition, sourcev1.VerificationError, "failed to verify the signature using provider '<provider> keyless': no signatures found for image"),
},
},
{
Expand Down Expand Up @@ -1193,6 +1193,8 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

obj := &ociv1.OCIRepository{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "verify-oci-source-signature-",
Expand Down Expand Up @@ -1239,11 +1241,14 @@ func TestOCIRepository_reconcileSource_verifyOCISourceSignature(t *testing.T) {
ro := &coptions.RootOptions{
Timeout: timeout,
}
err = sign.SignCmd(ro, ko, coptions.RegistryOptions{Keychain: keychain},
nil, []string{artifactURL}, "",
"", true, "",
"", "", false,
false, "", true)
err = sign.SignCmd(ro, ko, coptions.SignOptions{
Upload: true,
SkipConfirmation: true,
TlogUpload: false,

Registry: coptions.RegistryOptions{Keychain: keychain, AllowInsecure: true},
}, []string{artifactURL})

g.Expect(err).ToNot(HaveOccurred())
}

Expand Down
4 changes: 1 addition & 3 deletions internal/controller/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"context"
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
Expand Down Expand Up @@ -164,8 +163,7 @@ func setupRegistryServer(ctx context.Context, workspaceDir string, opts registry
}

htpasswdPath := filepath.Join(workspaceDir, testRegistryHtpasswdFileBasename)
err = ioutil.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testRegistryUsername, string(pwBytes))), 0644)
if err != nil {
if err = os.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testRegistryUsername, string(pwBytes))), 0644); err != nil {
return nil, fmt.Errorf("failed to create htpasswd file: %s", err)
}

Expand Down
60 changes: 41 additions & 19 deletions internal/oci/verifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ import (
"crypto"
"fmt"

"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
"github.com/sigstore/cosign/cmd/cosign/cli/rekor"
ociremote "github.com/sigstore/cosign/pkg/oci/remote"

"github.com/google/go-containerregistry/pkg/name"
coptions "github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/oci"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"
coptions "github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/rekor"
"github.com/sigstore/cosign/v2/pkg/cosign"
"github.com/sigstore/cosign/v2/pkg/oci"
ociremote "github.com/sigstore/cosign/v2/pkg/oci/remote"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
)
Expand Down Expand Up @@ -93,6 +92,11 @@ func NewCosignVerifier(ctx context.Context, opts ...Options) (*CosignVerifier, e
// If there is no public key provided, it will try keyless verification.
// https://github.com/sigstore/cosign/blob/main/KEYLESS.md.
if len(o.PublicKey) > 0 {
checkOpts.Offline = true
// TODO(hidde): this is an oversight in our implementation. As it is
// theoretically possible to have a custom PK, without disabling tlog.
checkOpts.IgnoreTlog = true

pubKeyRaw, err := cryptoutils.UnmarshalPEMToPublicKey(o.PublicKey)
if err != nil {
return nil, err
Expand All @@ -103,23 +107,31 @@ func NewCosignVerifier(ctx context.Context, opts ...Options) (*CosignVerifier, e
return nil, err
}
} else {
rcerts, err := fulcio.GetRoots()
checkOpts.RekorClient, err = rekor.NewClient(coptions.DefaultRekorURL)
if err != nil {
return nil, fmt.Errorf("unable to get Fulcio root certs: %w", err)
return nil, fmt.Errorf("unable to create Rekor client: %w", err)
}
checkOpts.RootCerts = rcerts

icerts, err := fulcio.GetIntermediates()
if err != nil {
return nil, fmt.Errorf("unable to get Fulcio intermediate certs: %w", err)
// This performs an online fetch of the Rekor public keys, but this is needed
// for verifying tlog entries (both online and offline).
// TODO(hidde): above note is important to keep in mind when we implement
// "offline" tlog above.
if checkOpts.RekorPubKeys, err = cosign.GetRekorPubs(ctx); err != nil {
return nil, fmt.Errorf("unable to get Rekor public keys: %w", err)
}
checkOpts.IntermediateCerts = icerts

rc, err := rekor.NewClient(coptions.DefaultRekorURL)
checkOpts.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
if err != nil {
return nil, fmt.Errorf("unable to create Rekor client: %w", err)
return nil, fmt.Errorf("unable to get CTLog public keys: %w", err)
}

if checkOpts.RootCerts, err = fulcio.GetRoots(); err != nil {
return nil, fmt.Errorf("unable to get Fulcio root certs: %w", err)
}

if checkOpts.IntermediateCerts, err = fulcio.GetIntermediates(); err != nil {
return nil, fmt.Errorf("unable to get Fulcio intermediate certs: %w", err)
}
checkOpts.RekorClient = rc
}

return &CosignVerifier{
Expand All @@ -129,7 +141,17 @@ func NewCosignVerifier(ctx context.Context, opts ...Options) (*CosignVerifier, e

// VerifyImageSignatures verify the authenticity of the given ref OCI image.
func (v *CosignVerifier) VerifyImageSignatures(ctx context.Context, ref name.Reference) ([]oci.Signature, bool, error) {
return cosign.VerifyImageSignatures(ctx, ref, v.opts)
opts := v.opts

// TODO: expose the match conditions in the CRD
opts.Identities = []cosign.Identity{
{
IssuerRegExp: ".*",
SubjectRegExp: ".*",
},
}

return cosign.VerifyImageSignatures(ctx, ref, opts)
}

// Verify verifies the authenticity of the given ref OCI image.
Expand Down
7 changes: 6 additions & 1 deletion pkg/azure/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"

"github.com/fluxcd/pkg/masktoken"

sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
)

Expand Down Expand Up @@ -422,7 +423,11 @@ func chainCredentialWithSecret(secret *corev1.Secret) (azcore.TokenCredential, e
if file, ok := os.LookupEnv("AZURE_FEDERATED_TOKEN_FILE"); ok {
if _, ok := os.LookupEnv("AZURE_AUTHORITY_HOST"); ok {
if tenantID, ok := os.LookupEnv("AZURE_TENANT_ID"); ok {
if token, _ := azidentity.NewWorkloadIdentityCredential(tenantID, clientID, file, &azidentity.WorkloadIdentityCredentialOptions{}); token != nil {
if token, _ := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{
ClientID: clientID,
TenantID: tenantID,
TokenFilePath: file,
}); token != nil {
creds = append(creds, token)
}
}
Expand Down