diff --git a/internal/controller/supervisorconfig/generator/generator.go b/internal/controller/supervisorconfig/generator/generator.go new file mode 100644 index 00000000..bed18e36 --- /dev/null +++ b/internal/controller/supervisorconfig/generator/generator.go @@ -0,0 +1,92 @@ +// Copyright 2020 the Pinniped contributors. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package generator + +import ( + "crypto/rand" + + appsv1 "k8s.io/api/apps/v1" + 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/1.19/apis/supervisor/config/v1alpha1" +) + +const ( + symmetricKeySecretType = "secrets.pinniped.dev/symmetric" + symmetricKeySecretDataKey = "key" + + symmetricKeySize = 32 + + opKind = "OIDCProvider" +) + +func generateSymmetricKey() ([]byte, error) { + b := make([]byte, symmetricKeySize) + if _, err := rand.Read(b); err != nil { + return nil, err + } + return b, nil +} + +func isValid(secret *corev1.Secret) bool { + if secret.Type != symmetricKeySecretType { + return false + } + + data, ok := secret.Data[symmetricKeySecretDataKey] + if !ok { + return false + } + if len(data) != symmetricKeySize { + return false + } + + return true +} + +func secretDataFunc() (map[string][]byte, error) { + symmetricKey, err := generateKey() + if err != nil { + return nil, err + } + + return map[string][]byte{ + symmetricKeySecretDataKey: symmetricKey, + }, nil +} + +func generateSecret(namespace, name string, labels map[string]string, secretDataFunc func() (map[string][]byte, error), owner metav1.Object) (*corev1.Secret, error) { + secretData, err := secretDataFunc() + if err != nil { + return nil, err + } + + deploymentGVK := schema.GroupVersionKind{ + Group: appsv1.SchemeGroupVersion.Group, + Version: appsv1.SchemeGroupVersion.Version, + Kind: "Deployment", + } + return &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(owner, deploymentGVK), + }, + Labels: labels, + }, + Type: symmetricKeySecretType, + Data: secretData, + }, nil +} + +// isOPCControlle returns whether the provided obj is controlled by an OPC. +func isOPControllee(obj metav1.Object) bool { + controller := metav1.GetControllerOf(obj) + return controller != nil && + controller.APIVersion == configv1alpha1.SchemeGroupVersion.String() && + controller.Kind == opKind +} diff --git a/internal/controller/supervisorconfig/generator/oidc_provider_secrets.go b/internal/controller/supervisorconfig/generator/oidc_provider_secrets.go index 36c79c26..4069e200 100644 --- a/internal/controller/supervisorconfig/generator/oidc_provider_secrets.go +++ b/internal/controller/supervisorconfig/generator/oidc_provider_secrets.go @@ -22,11 +22,6 @@ import ( "go.pinniped.dev/internal/plog" ) -const ( - // TODO should this live on `provider.OIDCProvider` ? - opcKind = "OIDCProvider" // TODO: deduplicate - internal/controller/supervisorconfig/jwks_writer.go -) - // SecretHelper describes an object that can Generate() a Secret and determine whether a Secret // IsValid(). It can also be Notify()'d about a Secret being persisted. // @@ -70,8 +65,8 @@ func NewOIDCProviderSecretsController( // TODO: de-dup me (jwks_writer.go). withInformer( secretInformer, - pinnipedcontroller.SimpleFilter(isOPCControllee, func(obj metav1.Object) controllerlib.Key { - if isOPCControllee(obj) { + pinnipedcontroller.SimpleFilter(isOPControllee, func(obj metav1.Object) controllerlib.Key { + if isOPControllee(obj) { controller := metav1.GetControllerOf(obj) return controllerlib.Key{ Name: controller.Name, @@ -211,11 +206,3 @@ func (c *oidcProviderSecretsController) createOrUpdateSecret( return err }) } - -// isOPCControlle returns whether the provided obj is controlled by an OPC. -func isOPCControllee(obj metav1.Object) bool { // TODO: deduplicate - internal/controller/supervisorconfig/jwks_writer.go - controller := metav1.GetControllerOf(obj) - return controller != nil && - controller.APIVersion == configv1alpha1.SchemeGroupVersion.String() && - controller.Kind == opcKind -} diff --git a/internal/controller/supervisorconfig/generator/supervisor_secrets.go b/internal/controller/supervisorconfig/generator/supervisor_secrets.go index f95379ce..61fb0140 100644 --- a/internal/controller/supervisorconfig/generator/supervisor_secrets.go +++ b/internal/controller/supervisorconfig/generator/supervisor_secrets.go @@ -6,14 +6,12 @@ package generator import ( "context" - "crypto/rand" "fmt" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" corev1informers "k8s.io/client-go/informers/core/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/retry" @@ -24,26 +22,10 @@ import ( "go.pinniped.dev/internal/plog" ) -// TODO: de-dup me when we abstract these controllers. -const ( - symmetricKeySecretType = "secrets.pinniped.dev/symmetric" - symmetricKeySecretDataKey = "key" - - symmetricKeySize = 32 // TODO: what should this be? -) - // generateKey is stubbed out for the purpose of testing. The default behavior is to generate a symmetric key. //nolint:gochecknoglobals var generateKey = generateSymmetricKey -func generateSymmetricKey() ([]byte, error) { - b := make([]byte, symmetricKeySize) - if _, err := rand.Read(b); err != nil { - return nil, err - } - return b, nil -} - type supervisorSecretsController struct { owner *appsv1.Deployment labels map[string]string @@ -116,58 +98,6 @@ func (c *supervisorSecretsController) Sync(ctx controllerlib.Context) error { return nil } -func isValid(secret *corev1.Secret) bool { - if secret.Type != symmetricKeySecretType { - return false - } - - data, ok := secret.Data[symmetricKeySecretDataKey] - if !ok { - return false - } - if len(data) != symmetricKeySize { - return false - } - - return true -} - -func secretDataFunc() (map[string][]byte, error) { - symmetricKey, err := generateKey() - if err != nil { - return nil, err - } - - return map[string][]byte{ - symmetricKeySecretDataKey: symmetricKey, - }, nil -} - -func generateSecret(namespace, name string, labels map[string]string, secretDataFunc func() (map[string][]byte, error), owner metav1.Object) (*corev1.Secret, error) { - secretData, err := secretDataFunc() - if err != nil { - return nil, err - } - - deploymentGVK := schema.GroupVersionKind{ - Group: appsv1.SchemeGroupVersion.Group, - Version: appsv1.SchemeGroupVersion.Version, - Kind: "Deployment", - } - return &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - OwnerReferences: []metav1.OwnerReference{ - *metav1.NewControllerRef(owner, deploymentGVK), - }, - Labels: labels, - }, - Type: symmetricKeySecretType, - Data: secretData, - }, nil -} - func (c *supervisorSecretsController) createSecret(ctx context.Context, newSecret *corev1.Secret) error { _, err := c.client.CoreV1().Secrets(newSecret.Namespace).Create(ctx, newSecret, metav1.CreateOptions{}) return err