Rename off of main

Signed-off-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
Margo Crawford
2020-12-16 14:27:09 -08:00
committed by Ryan Richard
parent fbe1a202c2
commit 196e43aa48
149 changed files with 4525 additions and 4523 deletions
@@ -15,7 +15,7 @@ import (
)
const (
opKind = "OIDCProvider"
opKind = "FederationDomain"
)
func generateSymmetricKey() ([]byte, error) {
@@ -24,29 +24,29 @@ import (
"go.pinniped.dev/internal/plog"
)
type oidcProviderSecretsController struct {
type federationDomainSecretsController struct {
secretHelper SecretHelper
kubeClient kubernetes.Interface
pinnipedClient pinnipedclientset.Interface
opcInformer configinformers.OIDCProviderInformer
opcInformer configinformers.FederationDomainInformer
secretInformer corev1informers.SecretInformer
}
// NewOIDCProviderSecretsController returns a controllerlib.Controller that ensures a child Secret
// always exists for a parent OIDCProvider. It does this using the provided secretHelper, which
// NewFederationDomainSecretsController returns a controllerlib.Controller that ensures a child Secret
// always exists for a parent FederationDomain. It does this using the provided secretHelper, which
// provides the parent/child mapping logic.
func NewOIDCProviderSecretsController(
func NewFederationDomainSecretsController(
secretHelper SecretHelper,
kubeClient kubernetes.Interface,
pinnipedClient pinnipedclientset.Interface,
secretInformer corev1informers.SecretInformer,
opcInformer configinformers.OIDCProviderInformer,
opcInformer configinformers.FederationDomainInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
controllerlib.Config{
Name: fmt.Sprintf("%s%s", secretHelper.NamePrefix(), "controller"),
Syncer: &oidcProviderSecretsController{
Syncer: &federationDomainSecretsController{
secretHelper: secretHelper,
kubeClient: kubeClient,
pinnipedClient: pinnipedClient,
@@ -79,12 +79,12 @@ func NewOIDCProviderSecretsController(
)
}
func (c *oidcProviderSecretsController) Sync(ctx controllerlib.Context) error {
op, err := c.opcInformer.Lister().OIDCProviders(ctx.Key.Namespace).Get(ctx.Key.Name)
func (c *federationDomainSecretsController) Sync(ctx controllerlib.Context) error {
op, err := c.opcInformer.Lister().FederationDomains(ctx.Key.Namespace).Get(ctx.Key.Name)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf(
"failed to get %s/%s OIDCProvider: %w",
"failed to get %s/%s FederationDomain: %w",
ctx.Key.Namespace,
ctx.Key.Name,
err,
@@ -95,8 +95,8 @@ func (c *oidcProviderSecretsController) Sync(ctx controllerlib.Context) error {
// The corresponding secret to this OP should have been garbage collected since it should have
// had this OP as its owner.
plog.Debug(
"oidcprovider deleted",
"oidcprovider",
"federationdomain deleted",
"federationdomain",
klog.KRef(ctx.Key.Namespace, ctx.Key.Name),
)
return nil
@@ -115,17 +115,17 @@ func (c *oidcProviderSecretsController) Sync(ctx controllerlib.Context) error {
// Secret is up to date - we are good to go.
plog.Debug(
"secret is up to date",
"oidcprovider",
"federationdomain",
klog.KObj(op),
"secret",
klog.KObj(existingSecret),
)
op = c.secretHelper.ObserveActiveSecretAndUpdateParentOIDCProvider(op, existingSecret)
if err := c.updateOIDCProvider(ctx.Context, op); err != nil {
return fmt.Errorf("failed to update oidcprovider: %w", err)
op = c.secretHelper.ObserveActiveSecretAndUpdateParentFederationDomain(op, existingSecret)
if err := c.updateFederationDomain(ctx.Context, op); err != nil {
return fmt.Errorf("failed to update federationdomain: %w", err)
}
plog.Debug("updated oidcprovider", "oidcprovider", klog.KObj(op), "secret", klog.KObj(newSecret))
plog.Debug("updated federationdomain", "federationdomain", klog.KObj(op), "secret", klog.KObj(newSecret))
return nil
}
@@ -135,21 +135,21 @@ func (c *oidcProviderSecretsController) Sync(ctx controllerlib.Context) error {
if err := c.createOrUpdateSecret(ctx.Context, op, &newSecret); err != nil {
return fmt.Errorf("failed to create or update secret: %w", err)
}
plog.Debug("created/updated secret", "oidcprovider", klog.KObj(op), "secret", klog.KObj(newSecret))
plog.Debug("created/updated secret", "federationdomain", klog.KObj(op), "secret", klog.KObj(newSecret))
op = c.secretHelper.ObserveActiveSecretAndUpdateParentOIDCProvider(op, newSecret)
if err := c.updateOIDCProvider(ctx.Context, op); err != nil {
return fmt.Errorf("failed to update oidcprovider: %w", err)
op = c.secretHelper.ObserveActiveSecretAndUpdateParentFederationDomain(op, newSecret)
if err := c.updateFederationDomain(ctx.Context, op); err != nil {
return fmt.Errorf("failed to update federationdomain: %w", err)
}
plog.Debug("updated oidcprovider", "oidcprovider", klog.KObj(op), "secret", klog.KObj(newSecret))
plog.Debug("updated federationdomain", "federationdomain", klog.KObj(op), "secret", klog.KObj(newSecret))
return nil
}
// secretNeedsUpdate returns whether or not the Secret, with name secretName, for OIDCProvider op
// secretNeedsUpdate returns whether or not the Secret, with name secretName, for FederationDomain op
// needs to be updated. It returns the existing secret as its second argument.
func (c *oidcProviderSecretsController) secretNeedsUpdate(
op *configv1alpha1.OIDCProvider,
func (c *federationDomainSecretsController) secretNeedsUpdate(
op *configv1alpha1.FederationDomain,
secretName string,
) (bool, *corev1.Secret, error) {
// This OPC says it has a secret associated with it. Let's try to get it from the cache.
@@ -171,9 +171,9 @@ func (c *oidcProviderSecretsController) secretNeedsUpdate(
return false, secret, nil
}
func (c *oidcProviderSecretsController) createOrUpdateSecret(
func (c *federationDomainSecretsController) createOrUpdateSecret(
ctx context.Context,
op *configv1alpha1.OIDCProvider,
op *configv1alpha1.FederationDomain,
newSecret **corev1.Secret,
) error {
secretClient := c.kubeClient.CoreV1().Secrets((*newSecret).Namespace)
@@ -210,15 +210,15 @@ func (c *oidcProviderSecretsController) createOrUpdateSecret(
})
}
func (c *oidcProviderSecretsController) updateOIDCProvider(
func (c *federationDomainSecretsController) updateFederationDomain(
ctx context.Context,
newOP *configv1alpha1.OIDCProvider,
newOP *configv1alpha1.FederationDomain,
) error {
opcClient := c.pinnipedClient.ConfigV1alpha1().OIDCProviders(newOP.Namespace)
opcClient := c.pinnipedClient.ConfigV1alpha1().FederationDomains(newOP.Namespace)
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
oldOP, err := opcClient.Get(ctx, newOP.Name, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get oidcprovider %s/%s: %w", newOP.Namespace, newOP.Name, err)
return fmt.Errorf("failed to get federationdomain %s/%s: %w", newOP.Namespace, newOP.Name, err)
}
if reflect.DeepEqual(newOP.Status.Secrets, oldOP.Status.Secrets) {
@@ -30,7 +30,7 @@ import (
"go.pinniped.dev/internal/testutil"
)
func TestOIDCProviderControllerFilterSecret(t *testing.T) {
func TestFederationDomainControllerFilterSecret(t *testing.T) {
t.Parallel()
tests := []struct {
@@ -54,7 +54,7 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
Namespace: "some-namespace",
OwnerReferences: []metav1.OwnerReference{
{
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -85,7 +85,7 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
},
},
@@ -100,7 +100,7 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -123,7 +123,7 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
},
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -153,9 +153,9 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
opcInformer := pinnipedinformers.NewSharedInformerFactory(
pinnipedfake.NewSimpleClientset(),
0,
).Config().V1alpha1().OIDCProviders()
).Config().V1alpha1().FederationDomains()
withInformer := testutil.NewObservableWithInformerOption()
_ = NewOIDCProviderSecretsController(
_ = NewFederationDomainSecretsController(
secretHelper,
nil, // kubeClient, not needed
nil, // pinnipedClient, not needed
@@ -175,12 +175,12 @@ func TestOIDCProviderControllerFilterSecret(t *testing.T) {
}
}
func TestNewOIDCProviderSecretsControllerFilterOPC(t *testing.T) {
func TestNewFederationDomainSecretsControllerFilterOPC(t *testing.T) {
t.Parallel()
tests := []struct {
name string
opc configv1alpha1.OIDCProvider
opc configv1alpha1.FederationDomain
wantAdd bool
wantUpdate bool
wantDelete bool
@@ -188,7 +188,7 @@ func TestNewOIDCProviderSecretsControllerFilterOPC(t *testing.T) {
}{
{
name: "anything goes",
opc: configv1alpha1.OIDCProvider{},
opc: configv1alpha1.FederationDomain{},
wantAdd: true,
wantUpdate: true,
wantDelete: true,
@@ -212,9 +212,9 @@ func TestNewOIDCProviderSecretsControllerFilterOPC(t *testing.T) {
opcInformer := pinnipedinformers.NewSharedInformerFactory(
pinnipedfake.NewSimpleClientset(),
0,
).Config().V1alpha1().OIDCProviders()
).Config().V1alpha1().FederationDomains()
withInformer := testutil.NewObservableWithInformerOption()
_ = NewOIDCProviderSecretsController(
_ = NewFederationDomainSecretsController(
secretHelper,
nil, // kubeClient, not needed
nil, // pinnipedClient, not needed
@@ -223,7 +223,7 @@ func TestNewOIDCProviderSecretsControllerFilterOPC(t *testing.T) {
withInformer.WithInformer,
)
unrelated := configv1alpha1.OIDCProvider{}
unrelated := configv1alpha1.FederationDomain{}
filter := withInformer.GetFilterForInformer(opcInformer)
require.Equal(t, test.wantAdd, filter.Add(&test.opc))
require.Equal(t, test.wantUpdate, filter.Update(&unrelated, &test.opc))
@@ -234,7 +234,7 @@ func TestNewOIDCProviderSecretsControllerFilterOPC(t *testing.T) {
}
}
func TestOIDCProviderSecretsControllerSync(t *testing.T) {
func TestFederationDomainSecretsControllerSync(t *testing.T) {
t.Parallel()
const (
@@ -250,7 +250,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
opGVR := schema.GroupVersionResource{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Resource: "oidcproviders",
Resource: "federationdomains",
}
secretGVR := schema.GroupVersionResource{
@@ -259,7 +259,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
Resource: "secrets",
}
goodOP := &configv1alpha1.OIDCProvider{
goodOP := &configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: opName,
Namespace: namespace,
@@ -275,7 +275,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: opGVR.GroupVersion().String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: opName,
UID: opUID,
BlockOwnerDeletion: boolPtr(true),
@@ -304,7 +304,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: opGVR.GroupVersion().String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: opName,
UID: opUID,
BlockOwnerDeletion: boolPtr(true),
@@ -316,7 +316,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
tests := []struct {
name string
storage func(**configv1alpha1.OIDCProvider, **corev1.Secret)
storage func(**configv1alpha1.FederationDomain, **corev1.Secret)
client func(*pinnipedfake.Clientset, *kubernetesfake.Clientset)
secretHelper func(*mocksecrethelper.MockSecretHelper)
wantOPActions []kubetesting.Action
@@ -324,26 +324,26 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
wantError string
}{
{
name: "OIDCProvider does not exist and secret does not exist",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain does not exist and secret does not exist",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*op = nil
*s = nil
},
},
{
name: "OIDCProvider does not exist and secret exists",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain does not exist and secret exists",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*op = nil
},
},
{
name: "OIDCProvider exists and secret does not exist",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and secret does not exist",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = nil
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
wantOPActions: []kubetesting.Action{
kubetesting.NewGetAction(opGVR, namespace, goodOP.Name),
@@ -355,14 +355,14 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
},
},
{
name: "OIDCProvider exists and invalid secret exists",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and invalid secret exists",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = invalidSecret.DeepCopy()
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, invalidSecret).Times(2).Return(false)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
wantOPActions: []kubetesting.Action{
kubetesting.NewGetAction(opGVR, namespace, goodOP.Name),
@@ -374,14 +374,14 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
},
},
{
name: "OIDCProvider exists and generating a secret fails",
name: "FederationDomain exists and generating a secret fails",
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(nil, errors.New("some generate error"))
},
wantError: "failed to generate secret: some generate error",
},
{
name: "OIDCProvider exists and invalid secret exists and upon update we learn of a valid secret",
name: "FederationDomain exists and invalid secret exists and upon update we learn of a valid secret",
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
otherSecret := goodSecret.DeepCopy()
otherSecret.UID = "other-secret-uid"
@@ -389,7 +389,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(otherSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, goodSecret).Times(1).Return(false)
secretHelper.EXPECT().IsValid(goodOP, goodSecret).Times(1).Return(true)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
wantOPActions: []kubetesting.Action{
kubetesting.NewGetAction(opGVR, namespace, goodOP.Name),
@@ -400,7 +400,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
},
},
{
name: "OIDCProvider exists and invalid secret exists and getting secret fails",
name: "FederationDomain exists and invalid secret exists and getting secret fails",
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, goodSecret).Times(1).Return(false)
@@ -416,8 +416,8 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
wantError: fmt.Sprintf("failed to create or update secret: failed to get secret %s/%s: some get error", namespace, goodSecret.Name),
},
{
name: "OIDCProvider exists and secret does not exist and creating secret fails",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and secret does not exist and creating secret fails",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = nil
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
@@ -435,7 +435,7 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
wantError: fmt.Sprintf("failed to create or update secret: failed to create secret %s/%s: some create error", namespace, goodSecret.Name),
},
{
name: "OIDCProvider exists and invalid secret exists and updating secret fails",
name: "FederationDomain exists and invalid secret exists and updating secret fails",
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, goodSecret).Times(2).Return(false)
@@ -452,14 +452,14 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
wantError: "failed to create or update secret: some update error",
},
{
name: "OIDCProvider exists and invalid secret exists and updating secret fails due to conflict",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and invalid secret exists and updating secret fails due to conflict",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = invalidSecret.DeepCopy()
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, invalidSecret).Times(3).Return(false)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
client: func(_ *pinnipedfake.Clientset, c *kubernetesfake.Clientset) {
once := sync.Once{}
@@ -481,17 +481,17 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
},
},
{
name: "OIDCProvider exists and invalid secret exists and getting OIDCProvider fails",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and invalid secret exists and getting FederationDomain fails",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = invalidSecret.DeepCopy()
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, invalidSecret).Times(2).Return(false)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
client: func(c *pinnipedfake.Clientset, _ *kubernetesfake.Clientset) {
c.PrependReactor("get", "oidcproviders", func(_ kubetesting.Action) (bool, runtime.Object, error) {
c.PrependReactor("get", "federationdomains", func(_ kubetesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("some get error")
})
},
@@ -502,21 +502,21 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
kubetesting.NewGetAction(secretGVR, namespace, goodSecret.Name),
kubetesting.NewUpdateAction(secretGVR, namespace, goodSecret),
},
wantError: fmt.Sprintf("failed to update oidcprovider: failed to get oidcprovider %s/%s: some get error", goodOPWithStatus.Namespace, goodOPWithStatus.Name),
wantError: fmt.Sprintf("failed to update federationdomain: failed to get federationdomain %s/%s: some get error", goodOPWithStatus.Namespace, goodOPWithStatus.Name),
},
{
name: "OIDCProvider exists and invalid secret exists and updating OIDCProvider fails due to conflict",
storage: func(op **configv1alpha1.OIDCProvider, s **corev1.Secret) {
name: "FederationDomain exists and invalid secret exists and updating FederationDomain fails due to conflict",
storage: func(op **configv1alpha1.FederationDomain, s **corev1.Secret) {
*s = invalidSecret.DeepCopy()
},
secretHelper: func(secretHelper *mocksecrethelper.MockSecretHelper) {
secretHelper.EXPECT().Generate(goodOP).Times(1).Return(goodSecret, nil)
secretHelper.EXPECT().IsValid(goodOP, invalidSecret).Times(2).Return(false)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentOIDCProvider(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
secretHelper.EXPECT().ObserveActiveSecretAndUpdateParentFederationDomain(goodOP, goodSecret).Times(1).Return(goodOPWithStatus)
},
client: func(c *pinnipedfake.Clientset, _ *kubernetesfake.Clientset) {
once := sync.Once{}
c.PrependReactor("update", "oidcproviders", func(_ kubetesting.Action) (bool, runtime.Object, error) {
c.PrependReactor("update", "federationdomains", func(_ kubetesting.Action) (bool, runtime.Object, error) {
var err error
once.Do(func() { err = k8serrors.NewConflict(secretGVR.GroupResource(), namespace, errors.New("some error")) })
return true, nil, err
@@ -583,12 +583,12 @@ func TestOIDCProviderSecretsControllerSync(t *testing.T) {
test.secretHelper(secretHelper)
}
c := NewOIDCProviderSecretsController(
c := NewFederationDomainSecretsController(
secretHelper,
kubeAPIClient,
pinnipedAPIClient,
kubeInformers.Core().V1().Secrets(),
pinnipedInformers.Config().V1alpha1().OIDCProviders(),
pinnipedInformers.Config().V1alpha1().FederationDomains(),
controllerlib.WithInformer,
)
@@ -21,9 +21,9 @@ import (
// 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
ObserveActiveSecretAndUpdateParentOIDCProvider(*configv1alpha1.OIDCProvider, *corev1.Secret) *configv1alpha1.OIDCProvider
Generate(*configv1alpha1.FederationDomain) (*corev1.Secret, error)
IsValid(*configv1alpha1.FederationDomain, *corev1.Secret) bool
ObserveActiveSecretAndUpdateParentFederationDomain(*configv1alpha1.FederationDomain, *corev1.Secret) *configv1alpha1.FederationDomain
}
const (
@@ -39,7 +39,7 @@ const (
)
// SecretUsage describes how a cryptographic secret is going to be used. It is currently used to
// indicate to a SecretHelper which status field to set on the parent OIDCProvider for a Secret.
// indicate to a SecretHelper which status field to set on the parent FederationDomain for a Secret.
type SecretUsage int
const (
@@ -77,7 +77,7 @@ type symmetricSecretHelper struct {
func (s *symmetricSecretHelper) NamePrefix() string { return s.namePrefix }
// Generate implements SecretHelper.Generate().
func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.OIDCProvider) (*corev1.Secret, error) {
func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.FederationDomain) (*corev1.Secret, error) {
key := make([]byte, symmetricKeySize)
if _, err := s.rand.Read(key); err != nil {
return nil, err
@@ -92,7 +92,7 @@ func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.OIDCProvider) (*
*metav1.NewControllerRef(parent, schema.GroupVersionKind{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Kind: "OIDCProvider",
Kind: "FederationDomain",
}),
},
},
@@ -104,7 +104,7 @@ func (s *symmetricSecretHelper) Generate(parent *configv1alpha1.OIDCProvider) (*
}
// IsValid implements SecretHelper.IsValid().
func (s *symmetricSecretHelper) IsValid(parent *configv1alpha1.OIDCProvider, secret *corev1.Secret) bool {
func (s *symmetricSecretHelper) IsValid(parent *configv1alpha1.FederationDomain, secret *corev1.Secret) bool {
if !metav1.IsControlledBy(secret, parent) {
return false
}
@@ -124,11 +124,11 @@ func (s *symmetricSecretHelper) IsValid(parent *configv1alpha1.OIDCProvider, sec
return true
}
// ObserveActiveSecretAndUpdateParentOIDCProvider implements SecretHelper.ObserveActiveSecretAndUpdateParentOIDCProvider().
func (s *symmetricSecretHelper) ObserveActiveSecretAndUpdateParentOIDCProvider(
op *configv1alpha1.OIDCProvider,
// ObserveActiveSecretAndUpdateParentFederationDomain implements SecretHelper.ObserveActiveSecretAndUpdateParentFederationDomain().
func (s *symmetricSecretHelper) ObserveActiveSecretAndUpdateParentFederationDomain(
op *configv1alpha1.FederationDomain,
secret *corev1.Secret,
) *configv1alpha1.OIDCProvider {
) *configv1alpha1.FederationDomain {
var cacheKey string
if op != nil {
cacheKey = op.Spec.Issuer
@@ -21,28 +21,28 @@ func TestSymmetricSecretHelper(t *testing.T) {
t.Parallel()
tests := []struct {
name string
secretUsage SecretUsage
wantSetOIDCProviderField func(*configv1alpha1.OIDCProvider) string
name string
secretUsage SecretUsage
wantSetFederationDomainField func(*configv1alpha1.FederationDomain) string
}{
{
name: "token signing key",
secretUsage: SecretUsageTokenSigningKey,
wantSetOIDCProviderField: func(op *configv1alpha1.OIDCProvider) string {
wantSetFederationDomainField: func(op *configv1alpha1.FederationDomain) string {
return op.Status.Secrets.TokenSigningKey.Name
},
},
{
name: "state signing key",
secretUsage: SecretUsageStateSigningKey,
wantSetOIDCProviderField: func(op *configv1alpha1.OIDCProvider) string {
wantSetFederationDomainField: func(op *configv1alpha1.FederationDomain) string {
return op.Status.Secrets.StateSigningKey.Name
},
},
{
name: "state encryption key",
secretUsage: SecretUsageStateEncryptionKey,
wantSetOIDCProviderField: func(op *configv1alpha1.OIDCProvider) string {
wantSetFederationDomainField: func(op *configv1alpha1.FederationDomain) string {
return op.Status.Secrets.StateEncryptionKey.Name
},
},
@@ -57,21 +57,21 @@ func TestSymmetricSecretHelper(t *testing.T) {
"some-label-key-2": "some-label-value-2",
}
randSource := strings.NewReader(keyWith32Bytes)
var oidcProviderIssuerValue string
var federationDomainIssuerValue string
var symmetricKeyValue []byte
h := NewSymmetricSecretHelper(
"some-name-prefix-",
labels,
randSource,
test.secretUsage,
func(oidcProviderIssuer string, symmetricKey []byte) {
require.True(t, oidcProviderIssuer == "" && symmetricKeyValue == nil, "expected notify func not to have been called yet")
oidcProviderIssuerValue = oidcProviderIssuer
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.OIDCProvider{
parent := &configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
UID: "some-uid",
Namespace: "some-namespace",
@@ -88,7 +88,7 @@ func TestSymmetricSecretHelper(t *testing.T) {
*metav1.NewControllerRef(parent, schema.GroupVersionKind{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Kind: "OIDCProvider",
Kind: "FederationDomain",
}),
},
},
@@ -100,9 +100,9 @@ func TestSymmetricSecretHelper(t *testing.T) {
require.True(t, h.IsValid(parent, child))
h.ObserveActiveSecretAndUpdateParentOIDCProvider(parent, child)
require.Equal(t, parent.Spec.Issuer, oidcProviderIssuerValue)
require.Equal(t, child.Name, test.wantSetOIDCProviderField(parent))
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)
})
}
@@ -112,7 +112,7 @@ func TestSymmetricSecretHelperIsValid(t *testing.T) {
tests := []struct {
name string
child func(*corev1.Secret)
parent func(*configv1alpha1.OIDCProvider)
parent func(*configv1alpha1.FederationDomain)
want bool
}{
{
@@ -145,7 +145,7 @@ func TestSymmetricSecretHelperIsValid(t *testing.T) {
},
{
name: "child not owned by parent",
parent: func(op *configv1alpha1.OIDCProvider) {
parent: func(op *configv1alpha1.FederationDomain) {
op.UID = "wrong"
},
want: false,
@@ -160,7 +160,7 @@ func TestSymmetricSecretHelperIsValid(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
h := NewSymmetricSecretHelper("none of these args matter", nil, nil, SecretUsageTokenSigningKey, nil)
parent := &configv1alpha1.OIDCProvider{
parent := &configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "some-parent-name",
Namespace: "some-namespace",
@@ -175,7 +175,7 @@ func TestSymmetricSecretHelperIsValid(t *testing.T) {
*metav1.NewControllerRef(parent, schema.GroupVersionKind{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Kind: "OIDCProvider",
Kind: "FederationDomain",
}),
},
},
@@ -18,9 +18,9 @@ import (
)
type jwksObserverController struct {
issuerToJWKSSetter IssuerToJWKSMapSetter
oidcProviderInformer v1alpha1.OIDCProviderInformer
secretInformer corev1informers.SecretInformer
issuerToJWKSSetter IssuerToJWKSMapSetter
federationDomainInformer v1alpha1.FederationDomainInformer
secretInformer corev1informers.SecretInformer
}
type IssuerToJWKSMapSetter interface {
@@ -30,7 +30,7 @@ type IssuerToJWKSMapSetter interface {
)
}
// Returns a controller which watches all of the OIDCProviders and their corresponding Secrets
// Returns a controller which watches all of the FederationDomains and their corresponding Secrets
// and fills an in-memory cache of the JWKS info for each currently configured issuer.
// This controller assumes that the informers passed to it are already scoped down to the
// appropriate namespace. It also assumes that the IssuerToJWKSMapSetter passed to it has an
@@ -38,16 +38,16 @@ type IssuerToJWKSMapSetter interface {
func NewJWKSObserverController(
issuerToJWKSSetter IssuerToJWKSMapSetter,
secretInformer corev1informers.SecretInformer,
oidcProviderInformer v1alpha1.OIDCProviderInformer,
federationDomainInformer v1alpha1.FederationDomainInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
controllerlib.Config{
Name: "jwks-observer-controller",
Syncer: &jwksObserverController{
issuerToJWKSSetter: issuerToJWKSSetter,
oidcProviderInformer: oidcProviderInformer,
secretInformer: secretInformer,
issuerToJWKSSetter: issuerToJWKSSetter,
federationDomainInformer: federationDomainInformer,
secretInformer: secretInformer,
},
},
withInformer(
@@ -56,7 +56,7 @@ func NewJWKSObserverController(
controllerlib.InformerOption{},
),
withInformer(
oidcProviderInformer,
federationDomainInformer,
pinnipedcontroller.MatchAnythingFilter(nil),
controllerlib.InformerOption{},
),
@@ -65,12 +65,12 @@ func NewJWKSObserverController(
func (c *jwksObserverController) Sync(ctx controllerlib.Context) error {
ns := ctx.Key.Namespace
allProviders, err := c.oidcProviderInformer.Lister().OIDCProviders(ns).List(labels.Everything())
allProviders, err := c.federationDomainInformer.Lister().FederationDomains(ns).List(labels.Everything())
if err != nil {
return fmt.Errorf("failed to list OIDCProviders: %w", err)
return fmt.Errorf("failed to list FederationDomains: %w", err)
}
// Rebuild the whole map on any change to any Secret or OIDCProvider, because either can have changes that
// Rebuild the whole map on any change to any Secret or FederationDomain, because either can have changes that
// can cause the map to need to be updated.
issuerToJWKSMap := map[string]*jose.JSONWebKeySet{}
issuerToActiveJWKMap := map[string]*jose.JSONWebKey{}
@@ -28,25 +28,25 @@ import (
func TestJWKSObserverControllerInformerFilters(t *testing.T) {
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
var (
r *require.Assertions
observableWithInformerOption *testutil.ObservableWithInformerOption
secretsInformerFilter controllerlib.Filter
oidcProviderInformerFilter controllerlib.Filter
r *require.Assertions
observableWithInformerOption *testutil.ObservableWithInformerOption
secretsInformerFilter controllerlib.Filter
federationDomainInformerFilter controllerlib.Filter
)
it.Before(func() {
r = require.New(t)
observableWithInformerOption = testutil.NewObservableWithInformerOption()
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
oidcProviderInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().OIDCProviders()
federationDomainInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().FederationDomains()
_ = NewJWKSObserverController(
nil,
secretsInformer,
oidcProviderInformer,
federationDomainInformer,
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
)
secretsInformerFilter = observableWithInformerOption.GetFilterForInformer(secretsInformer)
oidcProviderInformerFilter = observableWithInformerOption.GetFilterForInformer(oidcProviderInformer)
federationDomainInformerFilter = observableWithInformerOption.GetFilterForInformer(federationDomainInformer)
})
when("watching Secret objects", func() {
@@ -71,19 +71,19 @@ func TestJWKSObserverControllerInformerFilters(t *testing.T) {
})
})
when("watching OIDCProvider objects", func() {
when("watching FederationDomain objects", func() {
var (
subject controllerlib.Filter
provider, otherProvider *v1alpha1.OIDCProvider
provider, otherProvider *v1alpha1.FederationDomain
)
it.Before(func() {
subject = oidcProviderInformerFilter
provider = &v1alpha1.OIDCProvider{ObjectMeta: metav1.ObjectMeta{Name: "any-name", Namespace: "any-namespace"}}
otherProvider = &v1alpha1.OIDCProvider{ObjectMeta: metav1.ObjectMeta{Name: "any-other-name", Namespace: "any-other-namespace"}}
subject = federationDomainInformerFilter
provider = &v1alpha1.FederationDomain{ObjectMeta: metav1.ObjectMeta{Name: "any-name", Namespace: "any-namespace"}}
otherProvider = &v1alpha1.FederationDomain{ObjectMeta: metav1.ObjectMeta{Name: "any-other-name", Namespace: "any-other-namespace"}}
})
when("any OIDCProvider changes", func() {
when("any FederationDomain changes", func() {
it("returns true to trigger the sync method", func() {
r.True(subject.Add(provider))
r.True(subject.Update(provider, otherProvider))
@@ -134,7 +134,7 @@ func TestJWKSObserverControllerSync(t *testing.T) {
subject = NewJWKSObserverController(
issuerToJWKSSetter,
kubeInformers.Core().V1().Secrets(),
pinnipedInformers.Config().V1alpha1().OIDCProviders(),
pinnipedInformers.Config().V1alpha1().FederationDomains(),
controllerlib.WithInformer,
)
@@ -178,7 +178,7 @@ func TestJWKSObserverControllerSync(t *testing.T) {
timeoutContextCancel()
})
when("there are no OIDCProviders and no JWKS Secrets yet", func() {
when("there are no FederationDomains and no JWKS Secrets yet", func() {
it("sets the issuerToJWKSSetter's map to be empty", func() {
startInformersAndController()
err := controllerlib.TestSync(t, subject, *syncContext)
@@ -190,84 +190,84 @@ func TestJWKSObserverControllerSync(t *testing.T) {
})
})
when("there are OIDCProviders where some have corresponding JWKS Secrets and some don't", func() {
when("there are FederationDomains where some have corresponding JWKS Secrets and some don't", func() {
var (
expectedJWK1, expectedJWK2 string
)
it.Before(func() {
oidcProviderWithoutSecret1 := &v1alpha1.OIDCProvider{
federationDomainWithoutSecret1 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "no-secret-oidcprovider1",
Name: "no-secret-federationdomain1",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://no-secret-issuer1.com"},
Status: v1alpha1.OIDCProviderStatus{}, // no Secrets.JWKS field
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://no-secret-issuer1.com"},
Status: v1alpha1.FederationDomainStatus{}, // no Secrets.JWKS field
}
oidcProviderWithoutSecret2 := &v1alpha1.OIDCProvider{
federationDomainWithoutSecret2 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "no-secret-oidcprovider2",
Name: "no-secret-federationdomain2",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://no-secret-issuer2.com"},
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://no-secret-issuer2.com"},
// no Status field
}
oidcProviderWithBadSecret := &v1alpha1.OIDCProvider{
federationDomainWithBadSecret := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "bad-secret-oidcprovider",
Name: "bad-secret-federationdomain",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://bad-secret-issuer.com"},
Status: v1alpha1.OIDCProviderStatus{
Secrets: v1alpha1.OIDCProviderSecrets{
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://bad-secret-issuer.com"},
Status: v1alpha1.FederationDomainStatus{
Secrets: v1alpha1.FederationDomainSecrets{
JWKS: corev1.LocalObjectReference{Name: "bad-secret-name"},
},
},
}
oidcProviderWithBadJWKSSecret := &v1alpha1.OIDCProvider{
federationDomainWithBadJWKSSecret := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "bad-jwks-secret-oidcprovider",
Name: "bad-jwks-secret-federationdomain",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://bad-jwks-secret-issuer.com"},
Status: v1alpha1.OIDCProviderStatus{
Secrets: v1alpha1.OIDCProviderSecrets{
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://bad-jwks-secret-issuer.com"},
Status: v1alpha1.FederationDomainStatus{
Secrets: v1alpha1.FederationDomainSecrets{
JWKS: corev1.LocalObjectReference{Name: "bad-jwks-secret-name"},
},
},
}
oidcProviderWithBadActiveJWKSecret := &v1alpha1.OIDCProvider{
federationDomainWithBadActiveJWKSecret := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "bad-active-jwk-secret-oidcprovider",
Name: "bad-active-jwk-secret-federationdomain",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://bad-active-jwk-secret-issuer.com"},
Status: v1alpha1.OIDCProviderStatus{
Secrets: v1alpha1.OIDCProviderSecrets{
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://bad-active-jwk-secret-issuer.com"},
Status: v1alpha1.FederationDomainStatus{
Secrets: v1alpha1.FederationDomainSecrets{
JWKS: corev1.LocalObjectReference{Name: "bad-active-jwk-secret-name"},
},
},
}
oidcProviderWithGoodSecret1 := &v1alpha1.OIDCProvider{
federationDomainWithGoodSecret1 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "good-secret-oidcprovider1",
Name: "good-secret-federationdomain1",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://issuer-with-good-secret1.com"},
Status: v1alpha1.OIDCProviderStatus{
Secrets: v1alpha1.OIDCProviderSecrets{
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://issuer-with-good-secret1.com"},
Status: v1alpha1.FederationDomainStatus{
Secrets: v1alpha1.FederationDomainSecrets{
JWKS: corev1.LocalObjectReference{Name: "good-jwks-secret-name1"},
},
},
}
oidcProviderWithGoodSecret2 := &v1alpha1.OIDCProvider{
federationDomainWithGoodSecret2 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "good-secret-oidcprovider2",
Name: "good-secret-federationdomain2",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://issuer-with-good-secret2.com"},
Status: v1alpha1.OIDCProviderStatus{
Secrets: v1alpha1.OIDCProviderSecrets{
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://issuer-with-good-secret2.com"},
Status: v1alpha1.FederationDomainStatus{
Secrets: v1alpha1.FederationDomainSecrets{
JWKS: corev1.LocalObjectReference{Name: "good-jwks-secret-name2"},
},
},
@@ -323,13 +323,13 @@ func TestJWKSObserverControllerSync(t *testing.T) {
"jwks": []byte(`{"keys": [` + expectedJWK2 + `]}`),
},
}
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithoutSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithoutSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithBadSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithBadJWKSSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithBadActiveJWKSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithGoodSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithGoodSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithoutSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithoutSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithBadSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithBadJWKSSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithBadActiveJWKSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithGoodSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithGoodSecret2))
r.NoError(kubeInformerClient.Tracker().Add(goodJWKSSecret1))
r.NoError(kubeInformerClient.Tracker().Add(goodJWKSSecret2))
r.NoError(kubeInformerClient.Tracker().Add(badSecret))
@@ -43,7 +43,7 @@ const (
)
const (
opcKind = "OIDCProvider"
opcKind = "FederationDomain"
)
// generateKey is stubbed out for the purpose of testing. The default behavior is to generate an EC key.
@@ -60,7 +60,7 @@ type jwksWriterController struct {
jwksSecretLabels map[string]string
pinnipedClient pinnipedclientset.Interface
kubeClient kubernetes.Interface
opcInformer configinformers.OIDCProviderInformer
opcInformer configinformers.FederationDomainInformer
secretInformer corev1informers.SecretInformer
}
@@ -71,7 +71,7 @@ func NewJWKSWriterController(
kubeClient kubernetes.Interface,
pinnipedClient pinnipedclientset.Interface,
secretInformer corev1informers.SecretInformer,
opcInformer configinformers.OIDCProviderInformer,
opcInformer configinformers.FederationDomainInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
@@ -119,11 +119,11 @@ func NewJWKSWriterController(
// Sync implements controllerlib.Syncer.
func (c *jwksWriterController) Sync(ctx controllerlib.Context) error {
opc, err := c.opcInformer.Lister().OIDCProviders(ctx.Key.Namespace).Get(ctx.Key.Name)
opc, err := c.opcInformer.Lister().FederationDomains(ctx.Key.Namespace).Get(ctx.Key.Name)
notFound := k8serrors.IsNotFound(err)
if err != nil && !notFound {
return fmt.Errorf(
"failed to get %s/%s OIDCProvider: %w",
"failed to get %s/%s FederationDomain: %w",
ctx.Key.Namespace,
ctx.Key.Name,
err,
@@ -134,8 +134,8 @@ func (c *jwksWriterController) Sync(ctx controllerlib.Context) error {
// The corresponding secret to this OPC should have been garbage collected since it should have
// had this OPC as its owner.
plog.Debug(
"oidcprovider deleted",
"oidcprovider",
"federationdomain deleted",
"federationdomain",
klog.KRef(ctx.Key.Namespace, ctx.Key.Name),
)
return nil
@@ -149,7 +149,7 @@ func (c *jwksWriterController) Sync(ctx controllerlib.Context) error {
// Secret is up to date - we are good to go.
plog.Debug(
"secret is up to date",
"oidcprovider",
"federationdomain",
klog.KRef(ctx.Key.Namespace, ctx.Key.Name),
)
return nil
@@ -173,12 +173,12 @@ func (c *jwksWriterController) Sync(ctx controllerlib.Context) error {
if err := c.updateOPC(ctx.Context, newOPC); err != nil {
return fmt.Errorf("cannot update opc: %w", err)
}
plog.Debug("updated oidcprovider", "oidcprovider", klog.KObj(newOPC))
plog.Debug("updated federationdomain", "federationdomain", klog.KObj(newOPC))
return nil
}
func (c *jwksWriterController) secretNeedsUpdate(opc *configv1alpha1.OIDCProvider) (bool, error) {
func (c *jwksWriterController) secretNeedsUpdate(opc *configv1alpha1.FederationDomain) (bool, error) {
if opc.Status.Secrets.JWKS.Name == "" {
// If the OPC says it doesn't have a secret associated with it, then let's create one.
return true, nil
@@ -203,7 +203,7 @@ func (c *jwksWriterController) secretNeedsUpdate(opc *configv1alpha1.OIDCProvide
return false, nil
}
func (c *jwksWriterController) generateSecret(opc *configv1alpha1.OIDCProvider) (*corev1.Secret, error) {
func (c *jwksWriterController) generateSecret(opc *configv1alpha1.FederationDomain) (*corev1.Secret, error) {
// Note! This is where we could potentially add more handling of OPC spec fields which tell us how
// this OIDC provider should sign and verify ID tokens (e.g., hardcoded token secret, gRPC
// connection to KMS, etc).
@@ -292,9 +292,9 @@ func (c *jwksWriterController) createOrUpdateSecret(
func (c *jwksWriterController) updateOPC(
ctx context.Context,
newOPC *configv1alpha1.OIDCProvider,
newOPC *configv1alpha1.FederationDomain,
) error {
opcClient := c.pinnipedClient.ConfigV1alpha1().OIDCProviders(newOPC.Namespace)
opcClient := c.pinnipedClient.ConfigV1alpha1().FederationDomains(newOPC.Namespace)
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
oldOPC, err := opcClient.Get(ctx, newOPC.Name, metav1.GetOptions{})
if err != nil {
@@ -54,7 +54,7 @@ func TestJWKSWriterControllerFilterSecret(t *testing.T) {
Namespace: "some-namespace",
OwnerReferences: []metav1.OwnerReference{
{
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -85,7 +85,7 @@ func TestJWKSWriterControllerFilterSecret(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
},
},
@@ -100,7 +100,7 @@ func TestJWKSWriterControllerFilterSecret(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -123,7 +123,7 @@ func TestJWKSWriterControllerFilterSecret(t *testing.T) {
},
{
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: "some-name",
Controller: boolPtr(true),
},
@@ -148,7 +148,7 @@ func TestJWKSWriterControllerFilterSecret(t *testing.T) {
opcInformer := pinnipedinformers.NewSharedInformerFactory(
pinnipedfake.NewSimpleClientset(),
0,
).Config().V1alpha1().OIDCProviders()
).Config().V1alpha1().FederationDomains()
withInformer := testutil.NewObservableWithInformerOption()
_ = NewJWKSWriterController(
nil, // labels, not needed
@@ -175,7 +175,7 @@ func TestJWKSWriterControllerFilterOPC(t *testing.T) {
tests := []struct {
name string
opc configv1alpha1.OIDCProvider
opc configv1alpha1.FederationDomain
wantAdd bool
wantUpdate bool
wantDelete bool
@@ -183,7 +183,7 @@ func TestJWKSWriterControllerFilterOPC(t *testing.T) {
}{
{
name: "anything goes",
opc: configv1alpha1.OIDCProvider{},
opc: configv1alpha1.FederationDomain{},
wantAdd: true,
wantUpdate: true,
wantDelete: true,
@@ -202,7 +202,7 @@ func TestJWKSWriterControllerFilterOPC(t *testing.T) {
opcInformer := pinnipedinformers.NewSharedInformerFactory(
pinnipedfake.NewSimpleClientset(),
0,
).Config().V1alpha1().OIDCProviders()
).Config().V1alpha1().FederationDomains()
withInformer := testutil.NewObservableWithInformerOption()
_ = NewJWKSWriterController(
nil, // labels, not needed
@@ -213,7 +213,7 @@ func TestJWKSWriterControllerFilterOPC(t *testing.T) {
withInformer.WithInformer,
)
unrelated := configv1alpha1.OIDCProvider{}
unrelated := configv1alpha1.FederationDomain{}
filter := withInformer.GetFilterForInformer(opcInformer)
require.Equal(t, test.wantAdd, filter.Add(&test.opc))
require.Equal(t, test.wantUpdate, filter.Update(&unrelated, &test.opc))
@@ -239,16 +239,16 @@ func TestJWKSWriterControllerSync(t *testing.T) {
opcGVR := schema.GroupVersionResource{
Group: configv1alpha1.SchemeGroupVersion.Group,
Version: configv1alpha1.SchemeGroupVersion.Version,
Resource: "oidcproviders",
Resource: "federationdomains",
}
goodOPC := &configv1alpha1.OIDCProvider{
goodOPC := &configv1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "good-opc",
Namespace: namespace,
UID: "good-opc-uid",
},
Spec: configv1alpha1.OIDCProviderSpec{
Spec: configv1alpha1.FederationDomainSpec{
Issuer: "https://some-issuer.com",
},
}
@@ -273,7 +273,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: opcGVR.GroupVersion().String(),
Kind: "OIDCProvider",
Kind: "FederationDomain",
Name: goodOPC.Name,
UID: goodOPC.UID,
BlockOwnerDeletion: boolPtr(true),
@@ -300,7 +300,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
secrets []*corev1.Secret
configKubeClient func(*kubernetesfake.Clientset)
configPinnipedClient func(*pinnipedfake.Clientset)
opcs []*configv1alpha1.OIDCProvider
opcs []*configv1alpha1.FederationDomain
generateKeyErr error
wantGenerateKeyCount int
wantSecretActions []kubetesting.Action
@@ -310,7 +310,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "new opc with no secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
wantGenerateKeyCount: 1,
@@ -326,7 +326,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "opc without status with existing secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
secrets: []*corev1.Secret{
@@ -344,7 +344,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "existing opc with no secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
wantGenerateKeyCount: 1,
@@ -359,7 +359,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "existing opc with existing secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -374,7 +374,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "missing jwk in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -392,7 +392,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "missing jwks in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -410,7 +410,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "invalid jwk JSON in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -428,7 +428,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "invalid jwks JSON in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -446,7 +446,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "public jwk in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -464,7 +464,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "private jwks in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -482,7 +482,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "invalid jwk key in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -500,7 +500,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "invalid jwks key in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -518,7 +518,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "missing active jwks in secret",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
secrets: []*corev1.Secret{
@@ -536,7 +536,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "generate key fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPCWithStatus,
},
generateKeyErr: errors.New("some generate error"),
@@ -545,7 +545,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "get secret fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
configKubeClient: func(client *kubernetesfake.Clientset) {
@@ -558,7 +558,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "create secret fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
configKubeClient: func(client *kubernetesfake.Clientset) {
@@ -571,7 +571,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "update secret fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
secrets: []*corev1.Secret{
@@ -587,11 +587,11 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "get opc fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
configPinnipedClient: func(client *pinnipedfake.Clientset) {
client.PrependReactor("get", "oidcproviders", func(_ kubetesting.Action) (bool, runtime.Object, error) {
client.PrependReactor("get", "federationdomains", func(_ kubetesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("some get error")
})
},
@@ -600,11 +600,11 @@ func TestJWKSWriterControllerSync(t *testing.T) {
{
name: "update opc fails",
key: controllerlib.Key{Namespace: goodOPC.Namespace, Name: goodOPC.Name},
opcs: []*configv1alpha1.OIDCProvider{
opcs: []*configv1alpha1.FederationDomain{
goodOPC,
},
configPinnipedClient: func(client *pinnipedfake.Clientset) {
client.PrependReactor("update", "oidcproviders", func(_ kubetesting.Action) (bool, runtime.Object, error) {
client.PrependReactor("update", "federationdomains", func(_ kubetesting.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("some update error")
})
},
@@ -661,7 +661,7 @@ func TestJWKSWriterControllerSync(t *testing.T) {
kubeAPIClient,
pinnipedAPIClient,
kubeInformers.Core().V1().Secrets(),
pinnipedInformers.Config().V1alpha1().OIDCProviders(),
pinnipedInformers.Config().V1alpha1().FederationDomains(),
controllerlib.WithInformer,
)
@@ -29,29 +29,29 @@ import (
// If there are no longer any valid issuers, then it can be called with no arguments.
// Implementations of this type should be thread-safe to support calls from multiple goroutines.
type ProvidersSetter interface {
SetProviders(oidcProviders ...*provider.OIDCProvider)
SetProviders(federationDomains ...*provider.FederationDomain)
}
type oidcProviderWatcherController struct {
type federationDomainWatcherController struct {
providerSetter ProvidersSetter
clock clock.Clock
client pinnipedclientset.Interface
opcInformer configinformers.OIDCProviderInformer
opcInformer configinformers.FederationDomainInformer
}
// NewOIDCProviderWatcherController creates a controllerlib.Controller that watches
// OIDCProvider objects and notifies a callback object of the collection of provider configs.
func NewOIDCProviderWatcherController(
// NewFederationDomainWatcherController creates a controllerlib.Controller that watches
// FederationDomain objects and notifies a callback object of the collection of provider configs.
func NewFederationDomainWatcherController(
providerSetter ProvidersSetter,
clock clock.Clock,
client pinnipedclientset.Interface,
opcInformer configinformers.OIDCProviderInformer,
opcInformer configinformers.FederationDomainInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
controllerlib.Config{
Name: "OIDCProviderWatcherController",
Syncer: &oidcProviderWatcherController{
Name: "FederationDomainWatcherController",
Syncer: &federationDomainWatcherController{
providerSetter: providerSetter,
clock: clock,
client: client,
@@ -67,7 +67,7 @@ func NewOIDCProviderWatcherController(
}
// Sync implements controllerlib.Syncer.
func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
func (c *federationDomainWatcherController) Sync(ctx controllerlib.Context) error {
all, err := c.opcInformer.Lister().List(labels.Everything())
if err != nil {
return err
@@ -82,7 +82,7 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
}
// Make a map of issuer hostnames -> set of unique secret names. This will help us complain when
// multiple OIDCProviders have the same issuer hostname (excluding port) but specify
// multiple FederationDomains have the same issuer hostname (excluding port) but specify
// different TLS serving Secrets. Doesn't make sense to have the one address use more than one
// TLS cert. Ignore ports because SNI information on the incoming requests is not going to include
// port numbers. Also make a helper function for forming keys into this map.
@@ -109,7 +109,7 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
errs := multierror.New()
oidcProviders := make([]*provider.OIDCProvider, 0)
federationDomains := make([]*provider.FederationDomain, 0)
for _, opc := range all {
issuerURL, urlParseErr := url.Parse(opc.Spec.Issuer)
@@ -120,7 +120,7 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
ctx.Context,
opc.Namespace,
opc.Name,
configv1alpha1.DuplicateOIDCProviderStatusCondition,
configv1alpha1.DuplicateFederationDomainStatusCondition,
"Duplicate issuer: "+opc.Spec.Issuer,
); err != nil {
errs.Add(fmt.Errorf("could not update status: %w", err))
@@ -135,7 +135,7 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
ctx.Context,
opc.Namespace,
opc.Name,
configv1alpha1.SameIssuerHostMustUseSameSecretOIDCProviderStatusCondition,
configv1alpha1.SameIssuerHostMustUseSameSecretFederationDomainStatusCondition,
"Issuers with the same DNS hostname (address not including port) must use the same secretName: "+issuerURLToHostnameKey(issuerURL),
); err != nil {
errs.Add(fmt.Errorf("could not update status: %w", err))
@@ -143,13 +143,13 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
continue
}
oidcProvider, err := provider.NewOIDCProvider(opc.Spec.Issuer) // This validates the Issuer URL.
federationDomain, err := provider.NewFederationDomain(opc.Spec.Issuer) // This validates the Issuer URL.
if err != nil {
if err := c.updateStatus(
ctx.Context,
opc.Namespace,
opc.Name,
configv1alpha1.InvalidOIDCProviderStatusCondition,
configv1alpha1.InvalidFederationDomainStatusCondition,
"Invalid: "+err.Error(),
); err != nil {
errs.Add(fmt.Errorf("could not update status: %w", err))
@@ -161,28 +161,28 @@ func (c *oidcProviderWatcherController) Sync(ctx controllerlib.Context) error {
ctx.Context,
opc.Namespace,
opc.Name,
configv1alpha1.SuccessOIDCProviderStatusCondition,
configv1alpha1.SuccessFederationDomainStatusCondition,
"Provider successfully created",
); err != nil {
errs.Add(fmt.Errorf("could not update status: %w", err))
continue
}
oidcProviders = append(oidcProviders, oidcProvider)
federationDomains = append(federationDomains, federationDomain)
}
c.providerSetter.SetProviders(oidcProviders...)
c.providerSetter.SetProviders(federationDomains...)
return errs.ErrOrNil()
}
func (c *oidcProviderWatcherController) updateStatus(
func (c *federationDomainWatcherController) updateStatus(
ctx context.Context,
namespace, name string,
status configv1alpha1.OIDCProviderStatusCondition,
status configv1alpha1.FederationDomainStatusCondition,
message string,
) error {
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
opc, err := c.client.ConfigV1alpha1().OIDCProviders(namespace).Get(ctx, name, metav1.GetOptions{})
opc, err := c.client.ConfigV1alpha1().FederationDomains(namespace).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("get failed: %w", err)
}
@@ -193,7 +193,7 @@ func (c *oidcProviderWatcherController) updateStatus(
plog.Debug(
"attempting status update",
"openidproviderconfig",
"federationdomainconfig",
klog.KRef(namespace, name),
"status",
status,
@@ -203,7 +203,7 @@ func (c *oidcProviderWatcherController) updateStatus(
opc.Status.Status = status
opc.Status.Message = message
opc.Status.LastUpdateTime = timePtr(metav1.NewTime(c.clock.Now()))
_, err = c.client.ConfigV1alpha1().OIDCProviders(namespace).Update(ctx, opc, metav1.UpdateOptions{})
_, err = c.client.ConfigV1alpha1().FederationDomains(namespace).Update(ctx, opc, metav1.UpdateOptions{})
return err
})
}
File diff suppressed because it is too large Load Diff
@@ -21,7 +21,7 @@ import (
type tlsCertObserverController struct {
issuerTLSCertSetter IssuerTLSCertSetter
defaultTLSCertificateSecretName string
oidcProviderInformer v1alpha1.OIDCProviderInformer
federationDomainInformer v1alpha1.FederationDomainInformer
secretInformer corev1informers.SecretInformer
}
@@ -34,7 +34,7 @@ func NewTLSCertObserverController(
issuerTLSCertSetter IssuerTLSCertSetter,
defaultTLSCertificateSecretName string,
secretInformer corev1informers.SecretInformer,
oidcProviderInformer v1alpha1.OIDCProviderInformer,
federationDomainInformer v1alpha1.FederationDomainInformer,
withInformer pinnipedcontroller.WithInformerOptionFunc,
) controllerlib.Controller {
return controllerlib.New(
@@ -43,7 +43,7 @@ func NewTLSCertObserverController(
Syncer: &tlsCertObserverController{
issuerTLSCertSetter: issuerTLSCertSetter,
defaultTLSCertificateSecretName: defaultTLSCertificateSecretName,
oidcProviderInformer: oidcProviderInformer,
federationDomainInformer: federationDomainInformer,
secretInformer: secretInformer,
},
},
@@ -53,7 +53,7 @@ func NewTLSCertObserverController(
controllerlib.InformerOption{},
),
withInformer(
oidcProviderInformer,
federationDomainInformer,
pinnipedcontroller.MatchAnythingFilter(nil),
controllerlib.InformerOption{},
),
@@ -62,12 +62,12 @@ func NewTLSCertObserverController(
func (c *tlsCertObserverController) Sync(ctx controllerlib.Context) error {
ns := ctx.Key.Namespace
allProviders, err := c.oidcProviderInformer.Lister().OIDCProviders(ns).List(labels.Everything())
allProviders, err := c.federationDomainInformer.Lister().FederationDomains(ns).List(labels.Everything())
if err != nil {
return fmt.Errorf("failed to list OIDCProviders: %w", err)
return fmt.Errorf("failed to list FederationDomains: %w", err)
}
// Rebuild the whole map on any change to any Secret or OIDCProvider, because either can have changes that
// Rebuild the whole map on any change to any Secret or FederationDomain, because either can have changes that
// can cause the map to need to be updated.
issuerHostToTLSCertMap := map[string]*tls.Certificate{}
@@ -29,26 +29,26 @@ import (
func TestTLSCertObserverControllerInformerFilters(t *testing.T) {
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
var (
r *require.Assertions
observableWithInformerOption *testutil.ObservableWithInformerOption
secretsInformerFilter controllerlib.Filter
oidcProviderInformerFilter controllerlib.Filter
r *require.Assertions
observableWithInformerOption *testutil.ObservableWithInformerOption
secretsInformerFilter controllerlib.Filter
federationDomainInformerFilter controllerlib.Filter
)
it.Before(func() {
r = require.New(t)
observableWithInformerOption = testutil.NewObservableWithInformerOption()
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
oidcProviderInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().OIDCProviders()
federationDomainInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().FederationDomains()
_ = NewTLSCertObserverController(
nil,
"", // don't care about the secret name for this test
secretsInformer,
oidcProviderInformer,
federationDomainInformer,
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
)
secretsInformerFilter = observableWithInformerOption.GetFilterForInformer(secretsInformer)
oidcProviderInformerFilter = observableWithInformerOption.GetFilterForInformer(oidcProviderInformer)
federationDomainInformerFilter = observableWithInformerOption.GetFilterForInformer(federationDomainInformer)
})
when("watching Secret objects", func() {
@@ -73,19 +73,19 @@ func TestTLSCertObserverControllerInformerFilters(t *testing.T) {
})
})
when("watching OIDCProvider objects", func() {
when("watching FederationDomain objects", func() {
var (
subject controllerlib.Filter
provider, otherProvider *v1alpha1.OIDCProvider
provider, otherProvider *v1alpha1.FederationDomain
)
it.Before(func() {
subject = oidcProviderInformerFilter
provider = &v1alpha1.OIDCProvider{ObjectMeta: metav1.ObjectMeta{Name: "any-name", Namespace: "any-namespace"}}
otherProvider = &v1alpha1.OIDCProvider{ObjectMeta: metav1.ObjectMeta{Name: "any-other-name", Namespace: "any-other-namespace"}}
subject = federationDomainInformerFilter
provider = &v1alpha1.FederationDomain{ObjectMeta: metav1.ObjectMeta{Name: "any-name", Namespace: "any-namespace"}}
otherProvider = &v1alpha1.FederationDomain{ObjectMeta: metav1.ObjectMeta{Name: "any-other-name", Namespace: "any-other-namespace"}}
})
when("any OIDCProvider changes", func() {
when("any FederationDomain changes", func() {
it("returns true to trigger the sync method", func() {
r.True(subject.Add(provider))
r.True(subject.Update(provider, otherProvider))
@@ -142,7 +142,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
issuerTLSCertSetter,
defaultTLSSecretName,
kubeInformers.Core().V1().Secrets(),
pinnipedInformers.Config().V1alpha1().OIDCProviders(),
pinnipedInformers.Config().V1alpha1().FederationDomains(),
controllerlib.WithInformer,
)
@@ -192,7 +192,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
timeoutContextCancel()
})
when("there are no OIDCProviders and no TLS Secrets yet", func() {
when("there are no FederationDomains and no TLS Secrets yet", func() {
it("sets the issuerTLSCertSetter's map to be empty", func() {
startInformersAndController()
err := controllerlib.TestSync(t, subject, *syncContext)
@@ -205,71 +205,71 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
})
})
when("there are OIDCProviders where some have corresponding TLS Secrets and some don't", func() {
when("there are FederationDomains where some have corresponding TLS Secrets and some don't", func() {
var (
expectedCertificate1, expectedCertificate2 tls.Certificate
)
it.Before(func() {
var err error
oidcProviderWithoutSecret1 := &v1alpha1.OIDCProvider{
federationDomainWithoutSecret1 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "no-secret-oidcprovider1",
Name: "no-secret-federationdomain1",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: "https://no-secret-issuer1.com"}, // no SNICertificateSecretName field
Spec: v1alpha1.FederationDomainSpec{Issuer: "https://no-secret-issuer1.com"}, // no SNICertificateSecretName field
}
oidcProviderWithoutSecret2 := &v1alpha1.OIDCProvider{
federationDomainWithoutSecret2 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "no-secret-oidcprovider2",
Name: "no-secret-federationdomain2",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{
Spec: v1alpha1.FederationDomainSpec{
Issuer: "https://no-secret-issuer2.com",
TLS: &v1alpha1.OIDCProviderTLSSpec{SecretName: ""},
TLS: &v1alpha1.FederationDomainTLSSpec{SecretName: ""},
},
}
oidcProviderWithBadSecret := &v1alpha1.OIDCProvider{
federationDomainWithBadSecret := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "bad-secret-oidcprovider",
Name: "bad-secret-federationdomain",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{
Spec: v1alpha1.FederationDomainSpec{
Issuer: "https://bad-secret-issuer.com",
TLS: &v1alpha1.OIDCProviderTLSSpec{SecretName: "bad-tls-secret-name"},
TLS: &v1alpha1.FederationDomainTLSSpec{SecretName: "bad-tls-secret-name"},
},
}
// Also add one with a URL that cannot be parsed to make sure that the controller is not confused by invalid URLs.
invalidIssuerURL := ":/host//path"
_, err = url.Parse(invalidIssuerURL) //nolint:staticcheck // Yes, this URL is intentionally invalid.
r.Error(err)
oidcProviderWithBadIssuer := &v1alpha1.OIDCProvider{
federationDomainWithBadIssuer := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "bad-issuer-oidcprovider",
Name: "bad-issuer-federationdomain",
Namespace: installedInNamespace,
},
Spec: v1alpha1.OIDCProviderSpec{Issuer: invalidIssuerURL},
Spec: v1alpha1.FederationDomainSpec{Issuer: invalidIssuerURL},
}
oidcProviderWithGoodSecret1 := &v1alpha1.OIDCProvider{
federationDomainWithGoodSecret1 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "good-secret-oidcprovider1",
Name: "good-secret-federationdomain1",
Namespace: installedInNamespace,
},
// Issuer hostname should be treated in a case-insensitive way and SNI ignores port numbers. Test without a port number.
Spec: v1alpha1.OIDCProviderSpec{
Spec: v1alpha1.FederationDomainSpec{
Issuer: "https://www.iSSuer-wiTh-goOd-secRet1.cOm/path",
TLS: &v1alpha1.OIDCProviderTLSSpec{SecretName: "good-tls-secret-name1"},
TLS: &v1alpha1.FederationDomainTLSSpec{SecretName: "good-tls-secret-name1"},
},
}
oidcProviderWithGoodSecret2 := &v1alpha1.OIDCProvider{
federationDomainWithGoodSecret2 := &v1alpha1.FederationDomain{
ObjectMeta: metav1.ObjectMeta{
Name: "good-secret-oidcprovider2",
Name: "good-secret-federationdomain2",
Namespace: installedInNamespace,
},
// Issuer hostname should be treated in a case-insensitive way and SNI ignores port numbers. Test with a port number.
Spec: v1alpha1.OIDCProviderSpec{
Spec: v1alpha1.FederationDomainSpec{
Issuer: "https://www.issUEr-WIth-gOOd-seCret2.com:1234/path",
TLS: &v1alpha1.OIDCProviderTLSSpec{SecretName: "good-tls-secret-name2"},
TLS: &v1alpha1.FederationDomainTLSSpec{SecretName: "good-tls-secret-name2"},
},
}
testCrt1 := readTestFile("testdata/test.crt")
@@ -296,12 +296,12 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "bad-tls-secret-name", Namespace: installedInNamespace},
Data: map[string][]byte{"junk": nil},
}
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithoutSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithoutSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithBadSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithBadIssuer))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithGoodSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(oidcProviderWithGoodSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithoutSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithoutSecret2))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithBadSecret))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithBadIssuer))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithGoodSecret1))
r.NoError(pinnipedInformerClient.Tracker().Add(federationDomainWithGoodSecret2))
r.NoError(kubeInformerClient.Tracker().Add(goodTLSSecret1))
r.NoError(kubeInformerClient.Tracker().Add(goodTLSSecret2))
r.NoError(kubeInformerClient.Tracker().Add(badTLSSecret))
@@ -1,7 +1,7 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package upstreamwatcher implements a controller that watches UpstreamOIDCProvider objects.
// Package upstreamwatcher implements a controller that watches OIDCIdentityProvider objects.
package upstreamwatcher
import (
@@ -58,7 +58,7 @@ const (
reasonInvalidResponse = "InvalidResponse"
// Errors that are generated by our reconcile process.
errFailureStatus = constable.Error("UpstreamOIDCProvider has a failing condition")
errFailureStatus = constable.Error("OIDCIdentityProvider has a failing condition")
errNoCertificates = constable.Error("no certificates found")
)
@@ -75,7 +75,7 @@ type lruValidatorCacheEntry struct {
client *http.Client
}
func (c *lruValidatorCache) getProvider(spec *v1alpha1.UpstreamOIDCProviderSpec) (*oidc.Provider, *http.Client) {
func (c *lruValidatorCache) getProvider(spec *v1alpha1.OIDCIdentityProviderSpec) (*oidc.Provider, *http.Client) {
if result, ok := c.cache.Get(c.cacheKey(spec)); ok {
entry := result.(*lruValidatorCacheEntry)
return entry.provider, entry.client
@@ -83,11 +83,11 @@ func (c *lruValidatorCache) getProvider(spec *v1alpha1.UpstreamOIDCProviderSpec)
return nil, nil
}
func (c *lruValidatorCache) putProvider(spec *v1alpha1.UpstreamOIDCProviderSpec, provider *oidc.Provider, client *http.Client) {
func (c *lruValidatorCache) putProvider(spec *v1alpha1.OIDCIdentityProviderSpec, provider *oidc.Provider, client *http.Client) {
c.cache.Set(c.cacheKey(spec), &lruValidatorCacheEntry{provider: provider, client: client}, validatorCacheTTL)
}
func (c *lruValidatorCache) cacheKey(spec *v1alpha1.UpstreamOIDCProviderSpec) interface{} {
func (c *lruValidatorCache) cacheKey(spec *v1alpha1.OIDCIdentityProviderSpec) interface{} {
var key struct{ issuer, caBundle string }
key.issuer = spec.Issuer
if spec.TLS != nil {
@@ -100,11 +100,11 @@ type controller struct {
cache IDPCache
log logr.Logger
client pinnipedclientset.Interface
providers idpinformers.UpstreamOIDCProviderInformer
providers idpinformers.OIDCIdentityProviderInformer
secrets corev1informers.SecretInformer
validatorCache interface {
getProvider(*v1alpha1.UpstreamOIDCProviderSpec) (*oidc.Provider, *http.Client)
putProvider(*v1alpha1.UpstreamOIDCProviderSpec, *oidc.Provider, *http.Client)
getProvider(*v1alpha1.OIDCIdentityProviderSpec) (*oidc.Provider, *http.Client)
putProvider(*v1alpha1.OIDCIdentityProviderSpec, *oidc.Provider, *http.Client)
}
}
@@ -112,7 +112,7 @@ type controller struct {
func New(
idpCache IDPCache,
client pinnipedclientset.Interface,
providers idpinformers.UpstreamOIDCProviderInformer,
providers idpinformers.OIDCIdentityProviderInformer,
secrets corev1informers.SecretInformer,
log logr.Logger,
) controllerlib.Controller {
@@ -136,7 +136,7 @@ func New(
func (c *controller) Sync(ctx controllerlib.Context) error {
actualUpstreams, err := c.providers.Lister().List(labels.Everything())
if err != nil {
return fmt.Errorf("failed to list UpstreamOIDCProviders: %w", err)
return fmt.Errorf("failed to list OIDCIdentityProviders: %w", err)
}
requeue := false
@@ -156,9 +156,9 @@ func (c *controller) Sync(ctx controllerlib.Context) error {
return nil
}
// validateUpstream validates the provided v1alpha1.UpstreamOIDCProvider and returns the validated configuration as a
// provider.UpstreamOIDCIdentityProvider. As a side effect, it also updates the status of the v1alpha1.UpstreamOIDCProvider.
func (c *controller) validateUpstream(ctx controllerlib.Context, upstream *v1alpha1.UpstreamOIDCProvider) *upstreamoidc.ProviderConfig {
// validateUpstream validates the provided v1alpha1.OIDCIdentityProvider and returns the validated configuration as a
// provider.UpstreamOIDCIdentityProvider. As a side effect, it also updates the status of the v1alpha1.OIDCIdentityProvider.
func (c *controller) validateUpstream(ctx controllerlib.Context, upstream *v1alpha1.OIDCIdentityProvider) *upstreamoidc.ProviderConfig {
result := upstreamoidc.ProviderConfig{
Name: upstream.Name,
Config: &oauth2.Config{
@@ -192,7 +192,7 @@ func (c *controller) validateUpstream(ctx controllerlib.Context, upstream *v1alp
}
// validateSecret validates the .spec.client.secretName field and returns the appropriate ClientCredentialsValid condition.
func (c *controller) validateSecret(upstream *v1alpha1.UpstreamOIDCProvider, result *upstreamoidc.ProviderConfig) *v1alpha1.Condition {
func (c *controller) validateSecret(upstream *v1alpha1.OIDCIdentityProvider, result *upstreamoidc.ProviderConfig) *v1alpha1.Condition {
secretName := upstream.Spec.Client.SecretName
// Fetch the Secret from informer cache.
@@ -240,7 +240,7 @@ func (c *controller) validateSecret(upstream *v1alpha1.UpstreamOIDCProvider, res
}
// validateIssuer validates the .spec.issuer field, performs OIDC discovery, and returns the appropriate OIDCDiscoverySucceeded condition.
func (c *controller) validateIssuer(ctx context.Context, upstream *v1alpha1.UpstreamOIDCProvider, result *upstreamoidc.ProviderConfig) *v1alpha1.Condition {
func (c *controller) validateIssuer(ctx context.Context, upstream *v1alpha1.OIDCIdentityProvider, result *upstreamoidc.ProviderConfig) *v1alpha1.Condition {
// Get the provider and HTTP Client from cache if possible.
discoveredProvider, httpClient := c.validatorCache.getProvider(&upstream.Spec)
@@ -302,7 +302,7 @@ func (c *controller) validateIssuer(ctx context.Context, upstream *v1alpha1.Upst
}
}
func getTLSConfig(upstream *v1alpha1.UpstreamOIDCProvider) (*tls.Config, error) {
func getTLSConfig(upstream *v1alpha1.OIDCIdentityProvider) (*tls.Config, error) {
result := tls.Config{
MinVersion: tls.VersionTLS12,
}
@@ -324,7 +324,7 @@ func getTLSConfig(upstream *v1alpha1.UpstreamOIDCProvider) (*tls.Config, error)
return &result, nil
}
func (c *controller) updateStatus(ctx context.Context, upstream *v1alpha1.UpstreamOIDCProvider, conditions []*v1alpha1.Condition) {
func (c *controller) updateStatus(ctx context.Context, upstream *v1alpha1.OIDCIdentityProvider, conditions []*v1alpha1.Condition) {
log := c.log.WithValues("namespace", upstream.Namespace, "name", upstream.Name)
updated := upstream.DeepCopy()
@@ -352,7 +352,7 @@ func (c *controller) updateStatus(ctx context.Context, upstream *v1alpha1.Upstre
_, err := c.client.
IDPV1alpha1().
UpstreamOIDCProviders(upstream.Namespace).
OIDCIdentityProviders(upstream.Namespace).
UpdateStatus(ctx, updated, metav1.UpdateOptions{})
if err != nil {
log.Error(err, "failed to update status")
@@ -61,16 +61,16 @@ func TestController(t *testing.T) {
wantErr string
wantLogs []string
wantResultingCache []provider.UpstreamOIDCIdentityProviderI
wantResultingUpstreams []v1alpha1.UpstreamOIDCProvider
wantResultingUpstreams []v1alpha1.OIDCIdentityProvider
}{
{
name: "no upstreams",
},
{
name: "missing secret",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
@@ -82,12 +82,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="secret \"test-client-secret\" not found" "reason"="SecretNotFound" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="secret \"test-client-secret\" not found" "name"="test-name" "namespace"="test-namespace" "reason"="SecretNotFound" "type"="ClientCredentialsValid"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="secret \"test-client-secret\" not found" "name"="test-name" "namespace"="test-namespace" "reason"="SecretNotFound" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -110,9 +110,9 @@ func TestController(t *testing.T) {
},
{
name: "secret has wrong type",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
@@ -128,12 +128,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "reason"="SecretWrongType" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "name"="test-name" "namespace"="test-namespace" "reason"="SecretWrongType" "type"="ClientCredentialsValid"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" has wrong type \"some-other-type\" (should be \"secrets.pinniped.dev/oidc-client\")" "name"="test-name" "namespace"="test-namespace" "reason"="SecretWrongType" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -156,9 +156,9 @@ func TestController(t *testing.T) {
},
{
name: "secret is missing key",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
@@ -173,12 +173,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "reason"="SecretMissingKeys" "status"="False" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="discovered issuer configuration" "reason"="Success" "status"="True" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "name"="test-name" "namespace"="test-namespace" "reason"="SecretMissingKeys" "type"="ClientCredentialsValid"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="referenced Secret \"test-client-secret\" is missing required keys [\"clientID\" \"clientSecret\"]" "name"="test-name" "namespace"="test-namespace" "reason"="SecretMissingKeys" "type"="ClientCredentialsValid"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -201,9 +201,9 @@ func TestController(t *testing.T) {
},
{
name: "TLS CA bundle is invalid base64",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test-name"},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{
CertificateAuthorityData: "invalid-base64",
@@ -221,12 +221,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "reason"="InvalidTLSConfig" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: illegal base64 data at input byte 7" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -249,9 +249,9 @@ func TestController(t *testing.T) {
},
{
name: "TLS CA bundle does not have any certificates",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test-name"},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{
CertificateAuthorityData: base64.StdEncoding.EncodeToString([]byte("not-a-pem-ca-bundle")),
@@ -269,12 +269,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="spec.certificateAuthorityData is invalid: no certificates found" "reason"="InvalidTLSConfig" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: no certificates found" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="spec.certificateAuthorityData is invalid: no certificates found" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidTLSConfig" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -297,9 +297,9 @@ func TestController(t *testing.T) {
},
{
name: "issuer is invalid URL",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: "invalid-url",
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
AuthorizationConfig: v1alpha1.OIDCAuthorizationConfig{AdditionalScopes: testAdditionalScopes},
@@ -314,12 +314,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="failed to perform OIDC discovery against \"invalid-url\"" "reason"="Unreachable" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="failed to perform OIDC discovery against \"invalid-url\"" "name"="test-name" "namespace"="test-namespace" "reason"="Unreachable" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="failed to perform OIDC discovery against \"invalid-url\"" "name"="test-name" "namespace"="test-namespace" "reason"="Unreachable" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -342,9 +342,9 @@ func TestController(t *testing.T) {
},
{
name: "issuer returns invalid authorize URL",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL + "/invalid",
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
@@ -360,12 +360,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "reason"="InvalidResponse" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="failed to parse authorization endpoint URL: parse \"%\": invalid URL escape \"%\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -388,9 +388,9 @@ func TestController(t *testing.T) {
},
{
name: "issuer returns insecure authorize URL",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL + "/insecure",
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
@@ -406,12 +406,12 @@ func TestController(t *testing.T) {
wantLogs: []string{
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="loaded client credentials" "reason"="Success" "status"="True" "type"="ClientCredentialsValid"`,
`upstream-observer "level"=0 "msg"="updated condition" "name"="test-name" "namespace"="test-namespace" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "reason"="InvalidResponse" "status"="False" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="UpstreamOIDCProvider has a failing condition" "msg"="found failing condition" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
`upstream-observer "error"="OIDCIdentityProvider has a failing condition" "msg"="found failing condition" "message"="authorization endpoint URL scheme must be \"https\", not \"http\"" "name"="test-name" "namespace"="test-namespace" "reason"="InvalidResponse" "type"="OIDCDiscoverySucceeded"`,
},
wantResultingCache: []provider.UpstreamOIDCIdentityProviderI{},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{
@@ -434,16 +434,16 @@ func TestController(t *testing.T) {
},
{
name: "upstream becomes valid",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test-name"},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
AuthorizationConfig: v1alpha1.OIDCAuthorizationConfig{AdditionalScopes: append(testAdditionalScopes, "xyz", "openid")},
Claims: v1alpha1.OIDCClaims{Groups: testGroupsClaim, Username: testUsernameClaim},
},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Error",
Conditions: []v1alpha1.Condition{
{Type: "ClientCredentialsValid", Status: "False", LastTransitionTime: earlier, Reason: "SomeError1", Message: "some previous error 1"},
@@ -470,9 +470,9 @@ func TestController(t *testing.T) {
GroupsClaim: testGroupsClaim,
},
},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Ready",
Conditions: []v1alpha1.Condition{
{Type: "ClientCredentialsValid", Status: "True", LastTransitionTime: now, Reason: "Success", Message: "loaded client credentials"},
@@ -483,16 +483,16 @@ func TestController(t *testing.T) {
},
{
name: "existing valid upstream",
inputUpstreams: []runtime.Object{&v1alpha1.UpstreamOIDCProvider{
inputUpstreams: []runtime.Object{&v1alpha1.OIDCIdentityProvider{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
Spec: v1alpha1.UpstreamOIDCProviderSpec{
Spec: v1alpha1.OIDCIdentityProviderSpec{
Issuer: testIssuerURL,
TLS: &v1alpha1.TLSSpec{CertificateAuthorityData: testIssuerCABase64},
Client: v1alpha1.OIDCClient{SecretName: testSecretName},
AuthorizationConfig: v1alpha1.OIDCAuthorizationConfig{AdditionalScopes: testAdditionalScopes},
Claims: v1alpha1.OIDCClaims{Groups: testGroupsClaim, Username: testUsernameClaim},
},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Ready",
Conditions: []v1alpha1.Condition{
{Type: "ClientCredentialsValid", Status: "True", LastTransitionTime: earlier, Reason: "Success", Message: "loaded client credentials"},
@@ -519,9 +519,9 @@ func TestController(t *testing.T) {
GroupsClaim: testGroupsClaim,
},
},
wantResultingUpstreams: []v1alpha1.UpstreamOIDCProvider{{
wantResultingUpstreams: []v1alpha1.OIDCIdentityProvider{{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
Status: v1alpha1.UpstreamOIDCProviderStatus{
Status: v1alpha1.OIDCIdentityProviderStatus{
Phase: "Ready",
Conditions: []v1alpha1.Condition{
{Type: "ClientCredentialsValid", Status: "True", LastTransitionTime: earlier, Reason: "Success", Message: "loaded client credentials", ObservedGeneration: 1234},
@@ -548,7 +548,7 @@ func TestController(t *testing.T) {
controller := New(
cache,
fakePinnipedClient,
pinnipedInformers.IDP().V1alpha1().UpstreamOIDCProviders(),
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
kubeInformers.Core().V1().Secrets(),
testLog)
@@ -580,7 +580,7 @@ func TestController(t *testing.T) {
require.ElementsMatch(t, tt.wantResultingCache[i].GetScopes(), actualIDP.GetScopes())
}
actualUpstreams, err := fakePinnipedClient.IDPV1alpha1().UpstreamOIDCProviders(testNamespace).List(ctx, metav1.ListOptions{})
actualUpstreams, err := fakePinnipedClient.IDPV1alpha1().OIDCIdentityProviders(testNamespace).List(ctx, metav1.ListOptions{})
require.NoError(t, err)
// Preprocess the set of upstreams a bit so that they're easier to assert against.
@@ -597,13 +597,13 @@ func TestController(t *testing.T) {
}
}
func normalizeUpstreams(upstreams []v1alpha1.UpstreamOIDCProvider, now metav1.Time) []v1alpha1.UpstreamOIDCProvider {
result := make([]v1alpha1.UpstreamOIDCProvider, 0, len(upstreams))
func normalizeUpstreams(upstreams []v1alpha1.OIDCIdentityProvider, now metav1.Time) []v1alpha1.OIDCIdentityProvider {
result := make([]v1alpha1.OIDCIdentityProvider, 0, len(upstreams))
for _, u := range upstreams {
normalized := u.DeepCopy()
// We're only interested in comparing the status, so zero out the spec.
normalized.Spec = v1alpha1.UpstreamOIDCProviderSpec{}
normalized.Spec = v1alpha1.OIDCIdentityProviderSpec{}
// Round down the LastTransitionTime values to `now` if they were just updated. This makes
// it much easier to encode assertions about the expected timestamps.