e03e344dcd
This should allow the helper to be more generic so that it can be used with the SupervisorSecretsController
122 lines
3.5 KiB
Go
122 lines
3.5 KiB
Go
// 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 NamePrefix() that can be used to identify it from other SecretHelper instances.
|
|
type SecretHelper interface {
|
|
NamePrefix() string
|
|
Generate(*configv1alpha1.OIDCProvider) (*corev1.Secret, error)
|
|
IsValid(*configv1alpha1.OIDCProvider, *corev1.Secret) bool
|
|
Notify(*configv1alpha1.OIDCProvider, *corev1.Secret)
|
|
}
|
|
|
|
const (
|
|
// 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"
|
|
|
|
// 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).
|
|
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,
|
|
updateCacheFunc func(cacheKey string, cacheValue []byte),
|
|
) SecretHelper {
|
|
return &symmetricSecretHelper{
|
|
namePrefix: namePrefix,
|
|
labels: labels,
|
|
rand: rand,
|
|
updateCacheFunc: updateCacheFunc,
|
|
}
|
|
}
|
|
|
|
type symmetricSecretHelper struct {
|
|
namePrefix string
|
|
labels map[string]string
|
|
rand io.Reader
|
|
updateCacheFunc func(cacheKey string, cacheValue []byte)
|
|
}
|
|
|
|
func (s *symmetricSecretHelper) NamePrefix() string { return s.namePrefix }
|
|
|
|
// Generate implements SecretHelper.Generate().
|
|
func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.OIDCProvider) (*corev1.Secret, error) {
|
|
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",
|
|
}),
|
|
},
|
|
},
|
|
Type: SymmetricSecretType,
|
|
Data: map[string][]byte{
|
|
SymmetricSecretDataKey: key,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
// IsValid implements SecretHelper.IsValid().
|
|
func (s *symmetricSecretHelper) IsValid(parent *configv1alpha1.OIDCProvider, secret *corev1.Secret) bool {
|
|
if !metav1.IsControlledBy(secret, parent) {
|
|
return false
|
|
}
|
|
|
|
if secret.Type != SymmetricSecretType {
|
|
return false
|
|
}
|
|
|
|
key, ok := secret.Data[SymmetricSecretDataKey]
|
|
if !ok {
|
|
return false
|
|
}
|
|
if len(key) != symmetricKeySize {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// Notify implements SecretHelper.Notify().
|
|
func (s *symmetricSecretHelper) Notify(op *configv1alpha1.OIDCProvider, secret *corev1.Secret) {
|
|
var cacheKey string
|
|
if op != nil {
|
|
cacheKey = op.Spec.Issuer
|
|
}
|
|
|
|
s.updateCacheFunc(cacheKey, secret.Data[SymmetricSecretDataKey])
|
|
}
|