Split package upstreamwatchers into four packages
This commit is contained in:
parent
22092e9aed
commit
1ae3c6a1ad
@ -32,7 +32,8 @@ import (
|
|||||||
"go.pinniped.dev/internal/config/supervisor"
|
"go.pinniped.dev/internal/config/supervisor"
|
||||||
"go.pinniped.dev/internal/controller/supervisorconfig"
|
"go.pinniped.dev/internal/controller/supervisorconfig"
|
||||||
"go.pinniped.dev/internal/controller/supervisorconfig/generator"
|
"go.pinniped.dev/internal/controller/supervisorconfig/generator"
|
||||||
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatcher"
|
"go.pinniped.dev/internal/controller/supervisorconfig/ldapupstreamwatcher"
|
||||||
|
"go.pinniped.dev/internal/controller/supervisorconfig/oidcupstreamwatcher"
|
||||||
"go.pinniped.dev/internal/controller/supervisorstorage"
|
"go.pinniped.dev/internal/controller/supervisorstorage"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
"go.pinniped.dev/internal/deploymentref"
|
"go.pinniped.dev/internal/deploymentref"
|
||||||
@ -233,7 +234,7 @@ func startControllers(
|
|||||||
singletonWorker,
|
singletonWorker,
|
||||||
).
|
).
|
||||||
WithController(
|
WithController(
|
||||||
upstreamwatcher.NewOIDCUpstreamWatcherController(
|
oidcupstreamwatcher.New(
|
||||||
dynamicUpstreamIDPProvider,
|
dynamicUpstreamIDPProvider,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
||||||
@ -243,7 +244,7 @@ func startControllers(
|
|||||||
),
|
),
|
||||||
singletonWorker).
|
singletonWorker).
|
||||||
WithController(
|
WithController(
|
||||||
upstreamwatcher.NewLDAPUpstreamWatcherController(
|
ldapupstreamwatcher.New(
|
||||||
dynamicUpstreamIDPProvider,
|
dynamicUpstreamIDPProvider,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
pinnipedInformers.IDP().V1alpha1().LDAPIdentityProviders(),
|
pinnipedInformers.IDP().V1alpha1().LDAPIdentityProviders(),
|
||||||
|
68
internal/controller/conditionsutil/conditions_util.go.go
Normal file
68
internal/controller/conditionsutil/conditions_util.go.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package conditionsutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Merge merges conditions into conditionsToUpdate. If returns true if it merged any error conditions.
|
||||||
|
func Merge(conditions []*v1alpha1.Condition, observedGeneration int64, conditionsToUpdate *[]v1alpha1.Condition, log logr.Logger) bool {
|
||||||
|
hadErrorCondition := false
|
||||||
|
for i := range conditions {
|
||||||
|
cond := conditions[i].DeepCopy()
|
||||||
|
cond.LastTransitionTime = v1.Now()
|
||||||
|
cond.ObservedGeneration = observedGeneration
|
||||||
|
if mergeCondition(conditionsToUpdate, cond) {
|
||||||
|
log.Info("updated condition", "type", cond.Type, "status", cond.Status, "reason", cond.Reason, "message", cond.Message)
|
||||||
|
}
|
||||||
|
if cond.Status == v1alpha1.ConditionFalse {
|
||||||
|
hadErrorCondition = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.SliceStable(*conditionsToUpdate, func(i, j int) bool {
|
||||||
|
return (*conditionsToUpdate)[i].Type < (*conditionsToUpdate)[j].Type
|
||||||
|
})
|
||||||
|
return hadErrorCondition
|
||||||
|
}
|
||||||
|
|
||||||
|
// mergeCondition merges a new v1alpha1.Condition into a slice of existing conditions. It returns true
|
||||||
|
// if the condition has meaningfully changed.
|
||||||
|
func mergeCondition(existing *[]v1alpha1.Condition, new *v1alpha1.Condition) bool {
|
||||||
|
// Find any existing condition with a matching type.
|
||||||
|
var old *v1alpha1.Condition
|
||||||
|
for i := range *existing {
|
||||||
|
if (*existing)[i].Type == new.Type {
|
||||||
|
old = &(*existing)[i]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no existing condition of this type, append this one and we're done.
|
||||||
|
if old == nil {
|
||||||
|
*existing = append(*existing, *new)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the LastTransitionTime depending on whether the status has changed.
|
||||||
|
new = new.DeepCopy()
|
||||||
|
if old.Status == new.Status {
|
||||||
|
new.LastTransitionTime = old.LastTransitionTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// If anything has actually changed, update the entry and return true.
|
||||||
|
if !equality.Semantic.DeepEqual(old, new) {
|
||||||
|
*old = *new
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise the entry is already up to date.
|
||||||
|
return false
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package upstreamwatcher
|
// Package ldapupstreamwatcher implements a controller which watches LDAPIdentityProviders.
|
||||||
|
package ldapupstreamwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -22,6 +23,8 @@ import (
|
|||||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||||
idpinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1"
|
idpinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1"
|
||||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||||
|
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||||
|
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
"go.pinniped.dev/internal/upstreamldap"
|
"go.pinniped.dev/internal/upstreamldap"
|
||||||
@ -58,8 +61,8 @@ type ldapWatcherController struct {
|
|||||||
secretInformer corev1informers.SecretInformer
|
secretInformer corev1informers.SecretInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLDAPUpstreamWatcherController instantiates a new controllerlib.Controller which will populate the provided UpstreamLDAPIdentityProviderICache.
|
// New instantiates a new controllerlib.Controller which will populate the provided UpstreamLDAPIdentityProviderICache.
|
||||||
func NewLDAPUpstreamWatcherController(
|
func New(
|
||||||
idpCache UpstreamLDAPIdentityProviderICache,
|
idpCache UpstreamLDAPIdentityProviderICache,
|
||||||
client pinnipedclientset.Interface,
|
client pinnipedclientset.Interface,
|
||||||
ldapIdentityProviderInformer idpinformers.LDAPIdentityProviderInformer,
|
ldapIdentityProviderInformer idpinformers.LDAPIdentityProviderInformer,
|
||||||
@ -178,7 +181,7 @@ func (c *ldapWatcherController) validateTLSConfig(upstream *v1alpha1.LDAPIdentit
|
|||||||
ca := x509.NewCertPool()
|
ca := x509.NewCertPool()
|
||||||
ok := ca.AppendCertsFromPEM(bundle)
|
ok := ca.AppendCertsFromPEM(bundle)
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.invalidTLSCondition(fmt.Sprintf("certificateAuthorityData is invalid: %s", errNoCertificates))
|
return c.invalidTLSCondition(fmt.Sprintf("certificateAuthorityData is invalid: %s", upstreamwatchers.ErrNoCertificates))
|
||||||
}
|
}
|
||||||
|
|
||||||
config.CABundle = bundle
|
config.CABundle = bundle
|
||||||
@ -219,7 +222,7 @@ func (c *ldapWatcherController) testConnection(
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeLDAPConnectionValid,
|
Type: typeLDAPConnectionValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: upstreamwatchers.ReasonSuccess,
|
||||||
Message: fmt.Sprintf(`successfully able to connect to "%s" and bind as user "%s" [validated with Secret "%s" at version "%s"]`,
|
Message: fmt.Sprintf(`successfully able to connect to "%s" and bind as user "%s" [validated with Secret "%s" at version "%s"]`,
|
||||||
config.Host, config.BindUsername, upstream.Spec.Bind.SecretName, currentSecretVersion),
|
config.Host, config.BindUsername, upstream.Spec.Bind.SecretName, currentSecretVersion),
|
||||||
}
|
}
|
||||||
@ -248,7 +251,7 @@ func (c *ldapWatcherController) validTLSCondition(message string) *v1alpha1.Cond
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeTLSConfigurationValid,
|
Type: typeTLSConfigurationValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: upstreamwatchers.ReasonSuccess,
|
||||||
Message: message,
|
Message: message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +260,7 @@ func (c *ldapWatcherController) invalidTLSCondition(message string) *v1alpha1.Co
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeTLSConfigurationValid,
|
Type: typeTLSConfigurationValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonInvalidTLSConfig,
|
Reason: upstreamwatchers.ReasonInvalidTLSConfig,
|
||||||
Message: message,
|
Message: message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +273,7 @@ func (c *ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeBindSecretValid,
|
Type: typeBindSecretValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonNotFound,
|
Reason: upstreamwatchers.ReasonNotFound,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}, ""
|
}, ""
|
||||||
}
|
}
|
||||||
@ -279,7 +282,7 @@ func (c *ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeBindSecretValid,
|
Type: typeBindSecretValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonWrongType,
|
Reason: upstreamwatchers.ReasonWrongType,
|
||||||
Message: fmt.Sprintf("referenced Secret %q has wrong type %q (should be %q)",
|
Message: fmt.Sprintf("referenced Secret %q has wrong type %q (should be %q)",
|
||||||
secretName, secret.Type, corev1.SecretTypeBasicAuth),
|
secretName, secret.Type, corev1.SecretTypeBasicAuth),
|
||||||
}, secret.ResourceVersion
|
}, secret.ResourceVersion
|
||||||
@ -291,7 +294,7 @@ func (c *ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeBindSecretValid,
|
Type: typeBindSecretValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonMissingKeys,
|
Reason: upstreamwatchers.ReasonMissingKeys,
|
||||||
Message: fmt.Sprintf("referenced Secret %q is missing required keys %q",
|
Message: fmt.Sprintf("referenced Secret %q is missing required keys %q",
|
||||||
secretName, []string{corev1.BasicAuthUsernameKey, corev1.BasicAuthPasswordKey}),
|
secretName, []string{corev1.BasicAuthUsernameKey, corev1.BasicAuthPasswordKey}),
|
||||||
}, secret.ResourceVersion
|
}, secret.ResourceVersion
|
||||||
@ -300,7 +303,7 @@ func (c *ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeBindSecretValid,
|
Type: typeBindSecretValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: upstreamwatchers.ReasonSuccess,
|
||||||
Message: "loaded bind secret",
|
Message: "loaded bind secret",
|
||||||
}, secret.ResourceVersion
|
}, secret.ResourceVersion
|
||||||
}
|
}
|
||||||
@ -309,7 +312,7 @@ func (c *ldapWatcherController) updateStatus(ctx context.Context, upstream *v1al
|
|||||||
log := klogr.New().WithValues("namespace", upstream.Namespace, "name", upstream.Name)
|
log := klogr.New().WithValues("namespace", upstream.Namespace, "name", upstream.Name)
|
||||||
updated := upstream.DeepCopy()
|
updated := upstream.DeepCopy()
|
||||||
|
|
||||||
hadErrorCondition := mergeConditions(conditions, upstream.Generation, &updated.Status.Conditions, log)
|
hadErrorCondition := conditionsutil.Merge(conditions, upstream.Generation, &updated.Status.Conditions, log)
|
||||||
|
|
||||||
updated.Status.Phase = v1alpha1.LDAPPhaseReady
|
updated.Status.Phase = v1alpha1.LDAPPhaseReady
|
||||||
if hadErrorCondition {
|
if hadErrorCondition {
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package upstreamwatcher
|
package ldapupstreamwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -78,7 +78,7 @@ func TestLDAPUpstreamWatcherControllerFilterSecrets(t *testing.T) {
|
|||||||
secretInformer := kubeInformers.Core().V1().Secrets()
|
secretInformer := kubeInformers.Core().V1().Secrets()
|
||||||
withInformer := testutil.NewObservableWithInformerOption()
|
withInformer := testutil.NewObservableWithInformerOption()
|
||||||
|
|
||||||
NewLDAPUpstreamWatcherController(nil, nil, ldapIDPInformer, secretInformer, withInformer.WithInformer)
|
New(nil, nil, ldapIDPInformer, secretInformer, withInformer.WithInformer)
|
||||||
|
|
||||||
unrelated := corev1.Secret{}
|
unrelated := corev1.Secret{}
|
||||||
filter := withInformer.GetFilterForInformer(secretInformer)
|
filter := withInformer.GetFilterForInformer(secretInformer)
|
||||||
@ -123,7 +123,7 @@ func TestLDAPUpstreamWatcherControllerFilterLDAPIdentityProviders(t *testing.T)
|
|||||||
secretInformer := kubeInformers.Core().V1().Secrets()
|
secretInformer := kubeInformers.Core().V1().Secrets()
|
||||||
withInformer := testutil.NewObservableWithInformerOption()
|
withInformer := testutil.NewObservableWithInformerOption()
|
||||||
|
|
||||||
NewLDAPUpstreamWatcherController(nil, nil, ldapIDPInformer, secretInformer, withInformer.WithInformer)
|
New(nil, nil, ldapIDPInformer, secretInformer, withInformer.WithInformer)
|
||||||
|
|
||||||
unrelated := corev1.Secret{}
|
unrelated := corev1.Secret{}
|
||||||
filter := withInformer.GetFilterForInformer(ldapIDPInformer)
|
filter := withInformer.GetFilterForInformer(ldapIDPInformer)
|
@ -1,8 +1,8 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Package upstreamwatcher implements controllers that watch the idp.supervisor.pinniped.dev API group's objects.
|
// Package oidcupstreamwatcher implements a controller which watches OIDCIdentityProviders.
|
||||||
package upstreamwatcher
|
package oidcupstreamwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -31,6 +31,8 @@ import (
|
|||||||
idpinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1"
|
idpinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions/idp/v1alpha1"
|
||||||
"go.pinniped.dev/internal/constable"
|
"go.pinniped.dev/internal/constable"
|
||||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||||
|
"go.pinniped.dev/internal/controller/conditionsutil"
|
||||||
|
"go.pinniped.dev/internal/controller/supervisorconfig/upstreamwatchers"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
"go.pinniped.dev/internal/upstreamoidc"
|
"go.pinniped.dev/internal/upstreamoidc"
|
||||||
@ -52,17 +54,12 @@ const (
|
|||||||
// Constants related to conditions.
|
// Constants related to conditions.
|
||||||
typeClientCredentialsValid = "ClientCredentialsValid"
|
typeClientCredentialsValid = "ClientCredentialsValid"
|
||||||
typeOIDCDiscoverySucceeded = "OIDCDiscoverySucceeded"
|
typeOIDCDiscoverySucceeded = "OIDCDiscoverySucceeded"
|
||||||
reasonNotFound = "SecretNotFound"
|
|
||||||
reasonWrongType = "SecretWrongType"
|
|
||||||
reasonMissingKeys = "SecretMissingKeys"
|
|
||||||
reasonSuccess = "Success"
|
|
||||||
reasonUnreachable = "Unreachable"
|
reasonUnreachable = "Unreachable"
|
||||||
reasonInvalidTLSConfig = "InvalidTLSConfig"
|
|
||||||
reasonInvalidResponse = "InvalidResponse"
|
reasonInvalidResponse = "InvalidResponse"
|
||||||
|
|
||||||
// Errors that are generated by our reconcile process.
|
// Errors that are generated by our reconcile process.
|
||||||
errOIDCFailureStatus = constable.Error("OIDCIdentityProvider has a failing condition")
|
errOIDCFailureStatus = constable.Error("OIDCIdentityProvider has a failing condition")
|
||||||
errNoCertificates = constable.Error("no certificates found")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpstreamOIDCIdentityProviderICache is a thread safe cache that holds a list of validated upstream OIDC IDP configurations.
|
// UpstreamOIDCIdentityProviderICache is a thread safe cache that holds a list of validated upstream OIDC IDP configurations.
|
||||||
@ -111,8 +108,8 @@ type oidcWatcherController struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOIDCUpstreamWatcherController instantiates a new controllerlib.Controller which will populate the provided UpstreamOIDCIdentityProviderICache.
|
// New instantiates a new controllerlib.Controller which will populate the provided UpstreamOIDCIdentityProviderICache.
|
||||||
func NewOIDCUpstreamWatcherController(
|
func New(
|
||||||
idpCache UpstreamOIDCIdentityProviderICache,
|
idpCache UpstreamOIDCIdentityProviderICache,
|
||||||
client pinnipedclientset.Interface,
|
client pinnipedclientset.Interface,
|
||||||
oidcIdentityProviderInformer idpinformers.OIDCIdentityProviderInformer,
|
oidcIdentityProviderInformer idpinformers.OIDCIdentityProviderInformer,
|
||||||
@ -212,7 +209,7 @@ func (c *oidcWatcherController) validateSecret(upstream *v1alpha1.OIDCIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeClientCredentialsValid,
|
Type: typeClientCredentialsValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonNotFound,
|
Reason: upstreamwatchers.ReasonNotFound,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,7 +219,7 @@ func (c *oidcWatcherController) validateSecret(upstream *v1alpha1.OIDCIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeClientCredentialsValid,
|
Type: typeClientCredentialsValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonWrongType,
|
Reason: upstreamwatchers.ReasonWrongType,
|
||||||
Message: fmt.Sprintf("referenced Secret %q has wrong type %q (should be %q)", secretName, secret.Type, oidcClientSecretType),
|
Message: fmt.Sprintf("referenced Secret %q has wrong type %q (should be %q)", secretName, secret.Type, oidcClientSecretType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +231,7 @@ func (c *oidcWatcherController) validateSecret(upstream *v1alpha1.OIDCIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeClientCredentialsValid,
|
Type: typeClientCredentialsValid,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonMissingKeys,
|
Reason: upstreamwatchers.ReasonMissingKeys,
|
||||||
Message: fmt.Sprintf("referenced Secret %q is missing required keys %q", secretName, []string{clientIDDataKey, clientSecretDataKey}),
|
Message: fmt.Sprintf("referenced Secret %q is missing required keys %q", secretName, []string{clientIDDataKey, clientSecretDataKey}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,7 +242,7 @@ func (c *oidcWatcherController) validateSecret(upstream *v1alpha1.OIDCIdentityPr
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeClientCredentialsValid,
|
Type: typeClientCredentialsValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: upstreamwatchers.ReasonSuccess,
|
||||||
Message: "loaded client credentials",
|
Message: "loaded client credentials",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,7 +259,7 @@ func (c *oidcWatcherController) validateIssuer(ctx context.Context, upstream *v1
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeOIDCDiscoverySucceeded,
|
Type: typeOIDCDiscoverySucceeded,
|
||||||
Status: v1alpha1.ConditionFalse,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonInvalidTLSConfig,
|
Reason: upstreamwatchers.ReasonInvalidTLSConfig,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,7 +311,7 @@ func (c *oidcWatcherController) validateIssuer(ctx context.Context, upstream *v1
|
|||||||
return &v1alpha1.Condition{
|
return &v1alpha1.Condition{
|
||||||
Type: typeOIDCDiscoverySucceeded,
|
Type: typeOIDCDiscoverySucceeded,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: upstreamwatchers.ReasonSuccess,
|
||||||
Message: "discovered issuer configuration",
|
Message: "discovered issuer configuration",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,7 +332,7 @@ func (*oidcWatcherController) getTLSConfig(upstream *v1alpha1.OIDCIdentityProvid
|
|||||||
|
|
||||||
result.RootCAs = x509.NewCertPool()
|
result.RootCAs = x509.NewCertPool()
|
||||||
if !result.RootCAs.AppendCertsFromPEM(bundle) {
|
if !result.RootCAs.AppendCertsFromPEM(bundle) {
|
||||||
return nil, fmt.Errorf("spec.certificateAuthorityData is invalid: %w", errNoCertificates)
|
return nil, fmt.Errorf("spec.certificateAuthorityData is invalid: %w", upstreamwatchers.ErrNoCertificates)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &result, nil
|
return &result, nil
|
||||||
@ -345,7 +342,7 @@ func (c *oidcWatcherController) updateStatus(ctx context.Context, upstream *v1al
|
|||||||
log := c.log.WithValues("namespace", upstream.Namespace, "name", upstream.Name)
|
log := c.log.WithValues("namespace", upstream.Namespace, "name", upstream.Name)
|
||||||
updated := upstream.DeepCopy()
|
updated := upstream.DeepCopy()
|
||||||
|
|
||||||
hadErrorCondition := mergeConditions(conditions, upstream.Generation, &updated.Status.Conditions, log)
|
hadErrorCondition := conditionsutil.Merge(conditions, upstream.Generation, &updated.Status.Conditions, log)
|
||||||
|
|
||||||
updated.Status.Phase = v1alpha1.PhaseReady
|
updated.Status.Phase = v1alpha1.PhaseReady
|
||||||
if hadErrorCondition {
|
if hadErrorCondition {
|
||||||
@ -365,60 +362,6 @@ func (c *oidcWatcherController) updateStatus(ctx context.Context, upstream *v1al
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mergeConditions merges conditions into conditionsToUpdate. If returns true if it merged any error conditions.
|
|
||||||
func mergeConditions(conditions []*v1alpha1.Condition, observedGeneration int64, conditionsToUpdate *[]v1alpha1.Condition, log logr.Logger) bool {
|
|
||||||
hadErrorCondition := false
|
|
||||||
for i := range conditions {
|
|
||||||
cond := conditions[i].DeepCopy()
|
|
||||||
cond.LastTransitionTime = metav1.Now()
|
|
||||||
cond.ObservedGeneration = observedGeneration
|
|
||||||
if mergeCondition(conditionsToUpdate, cond) {
|
|
||||||
log.Info("updated condition", "type", cond.Type, "status", cond.Status, "reason", cond.Reason, "message", cond.Message)
|
|
||||||
}
|
|
||||||
if cond.Status == v1alpha1.ConditionFalse {
|
|
||||||
hadErrorCondition = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.SliceStable(*conditionsToUpdate, func(i, j int) bool {
|
|
||||||
return (*conditionsToUpdate)[i].Type < (*conditionsToUpdate)[j].Type
|
|
||||||
})
|
|
||||||
return hadErrorCondition
|
|
||||||
}
|
|
||||||
|
|
||||||
// mergeCondition merges a new v1alpha1.Condition into a slice of existing conditions. It returns true
|
|
||||||
// if the condition has meaningfully changed.
|
|
||||||
func mergeCondition(existing *[]v1alpha1.Condition, new *v1alpha1.Condition) bool {
|
|
||||||
// Find any existing condition with a matching type.
|
|
||||||
var old *v1alpha1.Condition
|
|
||||||
for i := range *existing {
|
|
||||||
if (*existing)[i].Type == new.Type {
|
|
||||||
old = &(*existing)[i]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no existing condition of this type, append this one and we're done.
|
|
||||||
if old == nil {
|
|
||||||
*existing = append(*existing, *new)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the LastTransitionTime depending on whether the status has changed.
|
|
||||||
new = new.DeepCopy()
|
|
||||||
if old.Status == new.Status {
|
|
||||||
new.LastTransitionTime = old.LastTransitionTime
|
|
||||||
}
|
|
||||||
|
|
||||||
// If anything has actually changed, update the entry and return true.
|
|
||||||
if !equality.Semantic.DeepEqual(old, new) {
|
|
||||||
*old = *new
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise the entry is already up to date.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*oidcWatcherController) computeScopes(additionalScopes []string) []string {
|
func (*oidcWatcherController) computeScopes(additionalScopes []string) []string {
|
||||||
// First compute the unique set of scopes, including "openid" (de-duplicate).
|
// First compute the unique set of scopes, including "openid" (de-duplicate).
|
||||||
set := make(map[string]bool, len(additionalScopes)+1)
|
set := make(map[string]bool, len(additionalScopes)+1)
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package upstreamwatcher
|
package oidcupstreamwatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -82,7 +82,7 @@ func TestOIDCUpstreamWatcherControllerFilterSecret(t *testing.T) {
|
|||||||
secretInformer := kubeInformers.Core().V1().Secrets()
|
secretInformer := kubeInformers.Core().V1().Secrets()
|
||||||
withInformer := testutil.NewObservableWithInformerOption()
|
withInformer := testutil.NewObservableWithInformerOption()
|
||||||
|
|
||||||
NewOIDCUpstreamWatcherController(
|
New(
|
||||||
cache,
|
cache,
|
||||||
nil,
|
nil,
|
||||||
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
||||||
@ -762,7 +762,7 @@ oidc: issuer did not match the issuer returned by provider, expected "` + testIs
|
|||||||
&upstreamoidc.ProviderConfig{Name: "initial-entry"},
|
&upstreamoidc.ProviderConfig{Name: "initial-entry"},
|
||||||
})
|
})
|
||||||
|
|
||||||
controller := NewOIDCUpstreamWatcherController(
|
controller := New(
|
||||||
cache,
|
cache,
|
||||||
fakePinnipedClient,
|
fakePinnipedClient,
|
||||||
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2021 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package upstreamwatchers
|
||||||
|
|
||||||
|
import "go.pinniped.dev/internal/constable"
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReasonNotFound = "SecretNotFound"
|
||||||
|
ReasonWrongType = "SecretWrongType"
|
||||||
|
ReasonMissingKeys = "SecretMissingKeys"
|
||||||
|
ReasonSuccess = "Success"
|
||||||
|
ReasonInvalidTLSConfig = "InvalidTLSConfig"
|
||||||
|
|
||||||
|
ErrNoCertificates = constable.Error("no certificates found")
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user