Skip to content

Commit

Permalink
Abstract and test getting authority keys
Browse files Browse the repository at this point in the history
Signed-off-by: Denny Hoang <dhoang@vmware.com>
  • Loading branch information
DennyHoang committed Mar 17, 2022
1 parent db8c7a7 commit 12f0c6b
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 19 deletions.
2 changes: 1 addition & 1 deletion pkg/cosign/kubernetes/webhook/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func getKeys(ctx context.Context, cfg map[string][]byte) ([]*ecdsa.PublicKey, *a
return keys, nil
}

func getAuthorityKeys(ctx context.Context, pubKey string) ([]*ecdsa.PublicKey, *apis.FieldError) {
func parseAuthorityKeys(ctx context.Context, pubKey string) ([]*ecdsa.PublicKey, *apis.FieldError) {
keys := []*ecdsa.PublicKey{}
errs := []error{}

Expand Down
43 changes: 25 additions & 18 deletions pkg/cosign/kubernetes/webhook/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package webhook

import (
"context"
"crypto/ecdsa"
"fmt"

"github.com/google/go-containerregistry/pkg/authn/k8schain"
Expand Down Expand Up @@ -142,24 +143,7 @@ func (v *Validator) validatePodSpec(ctx context.Context, ps *corev1.PodSpec, opt
tempKeys := keys
config := config.FromContext(ctx)
if config != nil {
authorities, err := config.ImagePolicyConfig.GetAuthorities(ref.Name())
if err != nil {
logging.FromContext(ctx).Errorf("Failed to fetch authorities for %s : %v", ref.Name(), err)
} else {
logging.FromContext(ctx).Infof("Successfully fetch authorities for %s", ref.Name())

for _, authority := range authorities {
if authority.Key != nil {
// Get the key from authority data
if authorityKeys, err := getAuthorityKeys(ctx, authority.Key.Data); err != nil {
logging.FromContext(ctx).Errorf("Failed to fetch keys from the authorities for %s : %v", ref.Name(), err)
} else {
logging.FromContext(ctx).Infof("Successfully added authority keys %s", ref.Name())
tempKeys = append(keys, authorityKeys...)
}
}
}
}
tempKeys = append(tempKeys, getAuthorityKeys(ctx, ref, config)...)
}

if err := valid(ctx, ref, tempKeys, ociremote.WithRemoteOptions(remote.WithAuthFromKeychain(kc))); err != nil {
Expand All @@ -177,6 +161,29 @@ func (v *Validator) validatePodSpec(ctx context.Context, ps *corev1.PodSpec, opt
return errs
}

func getAuthorityKeys(ctx context.Context, ref name.Reference, config *config.Config) []*ecdsa.PublicKey {
keys := make([]*ecdsa.PublicKey, 0)
authorities, err := config.ImagePolicyConfig.GetAuthorities(ref.Name())
if err != nil {
logging.FromContext(ctx).Errorf("Failed to fetch authorities for %s : %v", ref.Name(), err)
} else {
logging.FromContext(ctx).Infof("Successfully fetch authorities for %s", ref.Name())
for _, authority := range authorities {
if authority.Key != nil {
// Get the key from authority data
if authorityKeys, err := parseAuthorityKeys(ctx, authority.Key.Data); err != nil {
logging.FromContext(ctx).Errorf("Failed to fetch keys from the authorities for %s : %v", ref.Name(), err)
} else {
logging.FromContext(ctx).Infof("Successfully added authority keys %s", ref.Name())
keys = append(keys, authorityKeys...)
}
}
}
}

return keys
}

// ResolvePodSpecable implements duckv1.PodSpecValidator
func (v *Validator) ResolvePodSpecable(ctx context.Context, wp *duckv1.WithPod) {
if wp.DeletionTimestamp != nil {
Expand Down
53 changes: 53 additions & 0 deletions pkg/cosign/kubernetes/webhook/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/google/go-containerregistry/pkg/authn/k8schain"
"github.com/google/go-containerregistry/pkg/name"
"github.com/sigstore/cosign/pkg/apis/config"
"github.com/sigstore/cosign/pkg/apis/cosigned/v1alpha1"
"github.com/sigstore/cosign/pkg/cosign"
"github.com/sigstore/cosign/pkg/oci"
"github.com/sigstore/cosign/pkg/oci/remote"
"github.com/sigstore/cosign/pkg/oci/static"
"github.com/stretchr/testify/assert"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -40,6 +43,56 @@ import (
"knative.dev/pkg/system"
)

func TestGetAuthorityKeys(t *testing.T) {
refName := name.MustParseReference("gcr.io/distroless/static:nonroot")

validPublicKey := "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEapTW568kniCbL0OXBFIhuhOboeox\nUoJou2P8sbDxpLiE/v3yLw1/jyOrCPWYHWFXnyyeGlkgSVefG54tNoK7Uw==\n-----END PUBLIC KEY-----"

tests := []struct {
name string
imagePatterns []v1alpha1.ImagePattern
authorities []v1alpha1.Authority
wantKeyLength int
}{
{
name: "no authorities",
wantKeyLength: 0,
}, {
name: "wildcard glob and one key",
imagePatterns: []v1alpha1.ImagePattern{{
Glob: "*",
}},
authorities: []v1alpha1.Authority{
{
Key: &v1alpha1.KeyRef{
Data: validPublicKey,
},
},
},
wantKeyLength: 1,
},
}

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

config := config.Config{
ImagePolicyConfig: &config.ImagePolicyConfig{
Policies: map[string]v1alpha1.ClusterImagePolicySpec{
"cluster-image-policy": {
Images: test.imagePatterns,
Authorities: test.authorities,
},
},
},
}

keys := getAuthorityKeys(context.Background(), refName, &config)
assert.Equal(t, len(keys), test.wantKeyLength)
})
}
}

func TestValidatePodSpec(t *testing.T) {
tag := name.MustParseReference("gcr.io/distroless/static:nonroot")
// Resolved via crane digest on 2021/09/25
Expand Down

0 comments on commit 12f0c6b

Please sign in to comment.