ContainerImage.Pinniped/internal/controller/supervisorconfig/generator/secret_helper.go

117 lines
3.4 KiB
Go
Raw Normal View History

// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package generator
import (
"fmt"
"io"
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"
)
// 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.
//
// A SecretHelper has a Name() that can be used to identify it from other SecretHelper instances.
type SecretHelper interface {
Name() string
Generate(*configv1alpha1.OIDCProvider) (*corev1.Secret, error)
IsValid(*configv1alpha1.OIDCProvider, *corev1.Secret) bool
Notify(*configv1alpha1.OIDCProvider, *corev1.Secret)
}
const (
2020-12-15 00:23:17 +00:00
// SymmetricSecretType is corev1.Secret.Type of all corev1.Secret's generated by this helper.
SymmetricSecretType = "secrets.pinniped.dev/symmetric"
// SymmetricSecretDataKey is the corev1.Secret.Data key for the symmetric key value generated by this helper.
SymmetricSecretDataKey = "key"
2020-12-15 00:23:17 +00:00
// symmetricKeySize is the default length, in bytes, of generated keys. It is set to 32 since this
// seems like reasonable entropy for our keys, and a 32-byte key will allow for AES-256
// to be used in our codecs (see dynamiccodec.Codec).
2020-12-15 00:23:17 +00:00
symmetricKeySize = 32
)
// New returns a SecretHelper that has been parameterized with common symmetric secret generation
// knobs.
func NewSymmetricSecretHelper(
namePrefix string,
labels map[string]string,
rand io.Reader,
notifyFunc func(parent *configv1alpha1.OIDCProvider, child *corev1.Secret),
) SecretHelper {
return &symmetricSecretHelper{
namePrefix: namePrefix,
labels: labels,
rand: rand,
notifyFunc: notifyFunc,
}
}
type symmetricSecretHelper struct {
namePrefix string
labels map[string]string
rand io.Reader
notifyFunc func(parent *configv1alpha1.OIDCProvider, child *corev1.Secret)
}
func (s *symmetricSecretHelper) Name() string { return s.namePrefix }
// Generate implements SecretHelper.Generate().
func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.OIDCProvider) (*corev1.Secret, error) {
2020-12-15 00:23:17 +00:00
key := make([]byte, symmetricKeySize)
if _, err := s.rand.Read(key); err != nil {
return nil, err
}
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s%s", s.namePrefix, parent.UID),
Namespace: parent.Namespace,
Labels: s.labels,
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(parent, schema.GroupVersionKind{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Kind: "OIDCProvider",
}),
},
},
2020-12-15 00:23:17 +00:00
Type: SymmetricSecretType,
Data: map[string][]byte{
2020-12-15 00:23:17 +00:00
SymmetricSecretDataKey: key,
},
}, nil
}
// IsValid implements SecretHelper.IsValid().
func (s *symmetricSecretHelper) IsValid(parent *configv1alpha1.OIDCProvider, child *corev1.Secret) bool {
if !metav1.IsControlledBy(child, parent) {
return false
}
2020-12-15 00:23:17 +00:00
if child.Type != SymmetricSecretType {
return false
}
2020-12-15 00:23:17 +00:00
key, ok := child.Data[SymmetricSecretDataKey]
if !ok {
return false
}
2020-12-15 00:23:17 +00:00
if len(key) != symmetricKeySize {
return false
}
return true
}
// Notify implements SecretHelper.Notify().
func (s *symmetricSecretHelper) Notify(parent *configv1alpha1.OIDCProvider, child *corev1.Secret) {
s.notifyFunc(parent, child)
}