// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 package generator import ( "strings" "testing" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1" ) const keyWith32Bytes = "0123456789abcdef0123456789abcdef" func TestSymmetricSecretHelper(t *testing.T) { t.Parallel() tests := []struct { name string secretUsage SecretUsage wantSecretType corev1.SecretType wantSetFederationDomainField func(*configv1alpha1.FederationDomain) string }{ { name: "token signing key", secretUsage: SecretUsageTokenSigningKey, wantSecretType: "secrets.pinniped.dev/federation-domain-token-signing-key", wantSetFederationDomainField: func(federationDomain *configv1alpha1.FederationDomain) string { return federationDomain.Status.Secrets.TokenSigningKey.Name }, }, { name: "state signing key", secretUsage: SecretUsageStateSigningKey, wantSecretType: "secrets.pinniped.dev/federation-domain-state-signing-key", wantSetFederationDomainField: func(federationDomain *configv1alpha1.FederationDomain) string { return federationDomain.Status.Secrets.StateSigningKey.Name }, }, { name: "state encryption key", secretUsage: SecretUsageStateEncryptionKey, wantSecretType: "secrets.pinniped.dev/federation-domain-state-encryption-key", wantSetFederationDomainField: func(federationDomain *configv1alpha1.FederationDomain) string { return federationDomain.Status.Secrets.StateEncryptionKey.Name }, }, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { t.Parallel() labels := map[string]string{ "some-label-key-1": "some-label-value-1", "some-label-key-2": "some-label-value-2", } randSource := strings.NewReader(keyWith32Bytes) var federationDomainIssuerValue string var symmetricKeyValue []byte h := NewSymmetricSecretHelper( "some-name-prefix-", labels, randSource, test.secretUsage, func(federationDomainIssuer string, symmetricKey []byte) { require.True(t, federationDomainIssuer == "" && symmetricKeyValue == nil, "expected notify func not to have been called yet") federationDomainIssuerValue = federationDomainIssuer symmetricKeyValue = symmetricKey }, ) parent := &configv1alpha1.FederationDomain{ ObjectMeta: metav1.ObjectMeta{ UID: "some-uid", Namespace: "some-namespace", }, } child, err := h.Generate(parent) require.NoError(t, err) require.Equal(t, child, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "some-name-prefix-some-uid", Namespace: "some-namespace", Labels: labels, OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(parent, schema.GroupVersionKind{ Group: configv1alpha1.SchemeGroupVersion.Group, Version: configv1alpha1.SchemeGroupVersion.Version, Kind: "FederationDomain", }), }, }, Type: test.wantSecretType, Data: map[string][]byte{ "key": []byte(keyWith32Bytes), }, }) require.True(t, h.IsValid(parent, child)) h.ObserveActiveSecretAndUpdateParentFederationDomain(parent, child) require.Equal(t, parent.Spec.Issuer, federationDomainIssuerValue) require.Equal(t, child.Name, test.wantSetFederationDomainField(parent)) require.Equal(t, child.Data["key"], symmetricKeyValue) require.True(t, h.Handles(child)) wrongTypedChild := child.DeepCopy() wrongTypedChild.Type = "the-wrong-type" require.False(t, h.Handles(wrongTypedChild)) wrongOwnerKindChild := child.DeepCopy() wrongOwnerKindChild.OwnerReferences[0].Kind = "WrongKind" require.False(t, h.Handles(wrongOwnerKindChild)) }) } } func TestSymmetricSecretHelperIsValid(t *testing.T) { tests := []struct { name string secretUsage SecretUsage child func(*corev1.Secret) parent func(*configv1alpha1.FederationDomain) want bool }{ { name: "wrong type", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = "wrong" }, want: false, }, { name: "empty type", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = "" }, want: false, }, { name: "data key is too short", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = FederationDomainTokenSigningKeyType s.Data["key"] = []byte("short") }, want: false, }, { name: "data key does not exist", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = FederationDomainTokenSigningKeyType delete(s.Data, "key") }, want: false, }, { name: "child not owned by parent", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = FederationDomainTokenSigningKeyType }, parent: func(federationDomain *configv1alpha1.FederationDomain) { federationDomain.UID = "wrong" }, want: false, }, { name: "happy path", secretUsage: SecretUsageTokenSigningKey, child: func(s *corev1.Secret) { s.Type = FederationDomainTokenSigningKeyType }, want: true, }, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { h := NewSymmetricSecretHelper("none of these args matter", nil, nil, test.secretUsage, nil) parent := &configv1alpha1.FederationDomain{ ObjectMeta: metav1.ObjectMeta{ Name: "some-parent-name", Namespace: "some-namespace", UID: "some-parent-uid", }, } child := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: "some-name-prefix-some-uid", Namespace: "some-namespace", OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(parent, schema.GroupVersionKind{ Group: configv1alpha1.SchemeGroupVersion.Group, Version: configv1alpha1.SchemeGroupVersion.Version, Kind: "FederationDomain", }), }, }, Type: "invalid default", Data: map[string][]byte{ "key": []byte(keyWith32Bytes), }, } if test.child != nil { test.child(child) } if test.parent != nil { test.parent(parent) } require.Equalf(t, test.want, h.IsValid(parent, child), "child: %#v", child) }) } }