ldap_upstream_watcher.go: decode and validate CertificateAuthorityData
This commit is contained in:
parent
51263a0f07
commit
14ff5ee4ff
@ -5,6 +5,8 @@ package upstreamwatcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
@ -28,7 +30,10 @@ const (
|
|||||||
ldapBindAccountSecretType = corev1.SecretTypeBasicAuth
|
ldapBindAccountSecretType = corev1.SecretTypeBasicAuth
|
||||||
|
|
||||||
// Constants related to conditions.
|
// Constants related to conditions.
|
||||||
typeBindSecretValid = "BindSecretValid"
|
typeBindSecretValid = "BindSecretValid"
|
||||||
|
tlsConfigurationValid = "TLSConfigurationValid"
|
||||||
|
noTLSConfigurationMessage = "no TLS configuration provided"
|
||||||
|
loadedTLSConfigurationMessage = "loaded TLS configuration"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UpstreamLDAPIdentityProviderICache is a thread safe cache that holds a list of validated upstream LDAP IDP configurations.
|
// UpstreamLDAPIdentityProviderICache is a thread safe cache that holds a list of validated upstream LDAP IDP configurations.
|
||||||
@ -101,10 +106,10 @@ func (c *ldapWatcherController) Sync(ctx controllerlib.Context) error {
|
|||||||
|
|
||||||
func (c *ldapWatcherController) validateUpstream(ctx context.Context, upstream *v1alpha1.LDAPIdentityProvider) provider.UpstreamLDAPIdentityProviderI {
|
func (c *ldapWatcherController) validateUpstream(ctx context.Context, upstream *v1alpha1.LDAPIdentityProvider) provider.UpstreamLDAPIdentityProviderI {
|
||||||
spec := upstream.Spec
|
spec := upstream.Spec
|
||||||
|
|
||||||
result := &upstreamldap.Provider{
|
result := &upstreamldap.Provider{
|
||||||
Name: upstream.Name,
|
Name: upstream.Name,
|
||||||
Host: spec.Host,
|
Host: spec.Host,
|
||||||
CABundle: []byte(spec.TLS.CertificateAuthorityData),
|
|
||||||
UserSearch: &upstreamldap.UserSearch{
|
UserSearch: &upstreamldap.UserSearch{
|
||||||
Base: spec.UserSearch.Base,
|
Base: spec.UserSearch.Base,
|
||||||
Filter: spec.UserSearch.Filter,
|
Filter: spec.UserSearch.Filter,
|
||||||
@ -115,6 +120,7 @@ func (c *ldapWatcherController) validateUpstream(ctx context.Context, upstream *
|
|||||||
}
|
}
|
||||||
conditions := []*v1alpha1.Condition{
|
conditions := []*v1alpha1.Condition{
|
||||||
c.validateSecret(upstream, result),
|
c.validateSecret(upstream, result),
|
||||||
|
c.validateTLSConfig(upstream, result),
|
||||||
}
|
}
|
||||||
hadErrorCondition := c.updateStatus(ctx, upstream, conditions)
|
hadErrorCondition := c.updateStatus(ctx, upstream, conditions)
|
||||||
if hadErrorCondition {
|
if hadErrorCondition {
|
||||||
@ -123,7 +129,49 @@ func (c *ldapWatcherController) validateUpstream(ctx context.Context, upstream *
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityProvider, result *upstreamldap.Provider) *v1alpha1.Condition {
|
func (c *ldapWatcherController) validateTLSConfig(upstream *v1alpha1.LDAPIdentityProvider, result *upstreamldap.Provider) *v1alpha1.Condition {
|
||||||
|
tlsSpec := upstream.Spec.TLS
|
||||||
|
if tlsSpec == nil {
|
||||||
|
return c.validTLSCondition(noTLSConfigurationMessage)
|
||||||
|
}
|
||||||
|
if len(tlsSpec.CertificateAuthorityData) == 0 {
|
||||||
|
return c.validTLSCondition(loadedTLSConfigurationMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle, err := base64.StdEncoding.DecodeString(tlsSpec.CertificateAuthorityData)
|
||||||
|
if err != nil {
|
||||||
|
return c.invalidTLSCondition(fmt.Sprintf("certificateAuthorityData is invalid: %s", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
ca := x509.NewCertPool()
|
||||||
|
ok := ca.AppendCertsFromPEM(bundle)
|
||||||
|
if !ok {
|
||||||
|
return c.invalidTLSCondition(fmt.Sprintf("certificateAuthorityData is invalid: %s", errNoCertificates))
|
||||||
|
}
|
||||||
|
|
||||||
|
result.CABundle = bundle
|
||||||
|
return c.validTLSCondition(loadedTLSConfigurationMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ldapWatcherController) validTLSCondition(message string) *v1alpha1.Condition {
|
||||||
|
return &v1alpha1.Condition{
|
||||||
|
Type: tlsConfigurationValid,
|
||||||
|
Status: v1alpha1.ConditionTrue,
|
||||||
|
Reason: reasonSuccess,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ldapWatcherController) invalidTLSCondition(message string) *v1alpha1.Condition {
|
||||||
|
return &v1alpha1.Condition{
|
||||||
|
Type: tlsConfigurationValid,
|
||||||
|
Status: v1alpha1.ConditionFalse,
|
||||||
|
Reason: reasonInvalidTLSConfig,
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ldapWatcherController) validateSecret(upstream *v1alpha1.LDAPIdentityProvider, result *upstreamldap.Provider) *v1alpha1.Condition {
|
||||||
secretName := upstream.Spec.Bind.SecretName
|
secretName := upstream.Spec.Bind.SecretName
|
||||||
|
|
||||||
secret, err := c.secretInformer.Lister().Secrets(upstream.Namespace).Get(secretName)
|
secret, err := c.secretInformer.Lister().Secrets(upstream.Namespace).Get(secretName)
|
||||||
|
@ -5,6 +5,7 @@ package upstreamwatcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
@ -20,6 +21,7 @@ import (
|
|||||||
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
|
||||||
pinnipedfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
pinnipedfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||||
pinnipedinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions"
|
pinnipedinformers "go.pinniped.dev/generated/latest/client/supervisor/informers/externalversions"
|
||||||
|
"go.pinniped.dev/internal/certauthority"
|
||||||
"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/testutil"
|
"go.pinniped.dev/internal/testutil"
|
||||||
@ -150,15 +152,18 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
testBindUsername = "test-bind-username"
|
testBindUsername = "test-bind-username"
|
||||||
testBindPassword = "test-bind-password"
|
testBindPassword = "test-bind-password"
|
||||||
testHost = "ldap.example.com:123"
|
testHost = "ldap.example.com:123"
|
||||||
testCABundle = "test-ca-bundle"
|
|
||||||
testUserSearchBase = "test-user-search-base"
|
testUserSearchBase = "test-user-search-base"
|
||||||
testUserSearchFilter = "test-user-search-filter"
|
testUserSearchFilter = "test-user-search-filter"
|
||||||
testUsernameAttrName = "test-username-attr"
|
testUsernameAttrName = "test-username-attr"
|
||||||
testUIDAttrName = "test-uid-attr"
|
testUIDAttrName = "test-uid-attr"
|
||||||
)
|
)
|
||||||
var (
|
|
||||||
testValidSecretData = map[string][]byte{"username": []byte(testBindUsername), "password": []byte(testBindPassword)}
|
testValidSecretData := map[string][]byte{"username": []byte(testBindUsername), "password": []byte(testBindPassword)}
|
||||||
)
|
|
||||||
|
testCA, err := certauthority.New("test CA", time.Minute)
|
||||||
|
require.NoError(t, err)
|
||||||
|
testCABundle := testCA.Bundle()
|
||||||
|
testCABundleBase64Encoded := base64.StdEncoding.EncodeToString(testCABundle)
|
||||||
|
|
||||||
successfulDialer := &comparableDialer{
|
successfulDialer := &comparableDialer{
|
||||||
f: func(ctx context.Context, hostAndPort string) (upstreamldap.Conn, error) {
|
f: func(ctx context.Context, hostAndPort string) (upstreamldap.Conn, error) {
|
||||||
@ -171,7 +176,7 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{Name: testName, Namespace: testNamespace, Generation: 1234},
|
ObjectMeta: metav1.ObjectMeta{Name: testName, Namespace: testNamespace, Generation: 1234},
|
||||||
Spec: v1alpha1.LDAPIdentityProviderSpec{
|
Spec: v1alpha1.LDAPIdentityProviderSpec{
|
||||||
Host: testHost,
|
Host: testHost,
|
||||||
TLS: &v1alpha1.LDAPIdentityProviderTLSSpec{CertificateAuthorityData: testCABundle},
|
TLS: &v1alpha1.LDAPIdentityProviderTLSSpec{CertificateAuthorityData: testCABundleBase64Encoded},
|
||||||
Bind: v1alpha1.LDAPIdentityProviderBindSpec{SecretName: testSecretName},
|
Bind: v1alpha1.LDAPIdentityProviderBindSpec{SecretName: testSecretName},
|
||||||
UserSearch: v1alpha1.LDAPIdentityProviderUserSearchSpec{
|
UserSearch: v1alpha1.LDAPIdentityProviderUserSearchSpec{
|
||||||
Base: testUserSearchBase,
|
Base: testUserSearchBase,
|
||||||
@ -192,7 +197,7 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
providerForValidUpstream := &upstreamldap.Provider{
|
providerForValidUpstream := &upstreamldap.Provider{
|
||||||
Name: testName,
|
Name: testName,
|
||||||
Host: testHost,
|
Host: testHost,
|
||||||
CABundle: []byte(testCABundle),
|
CABundle: testCABundle,
|
||||||
BindUsername: testBindUsername,
|
BindUsername: testBindUsername,
|
||||||
BindPassword: testBindPassword,
|
BindPassword: testBindPassword,
|
||||||
UserSearch: &upstreamldap.UserSearch{
|
UserSearch: &upstreamldap.UserSearch{
|
||||||
@ -239,6 +244,14 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: "loaded bind secret",
|
Message: "loaded bind secret",
|
||||||
ObservedGeneration: 1234,
|
ObservedGeneration: 1234,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -263,6 +276,14 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: fmt.Sprintf(`secret "%s" not found`, testSecretName),
|
Message: fmt.Sprintf(`secret "%s" not found`, testSecretName),
|
||||||
ObservedGeneration: 1234,
|
ObservedGeneration: 1234,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -291,6 +312,14 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: fmt.Sprintf(`referenced Secret "%s" has wrong type "some-other-type" (should be "kubernetes.io/basic-auth")`, testSecretName),
|
Message: fmt.Sprintf(`referenced Secret "%s" has wrong type "some-other-type" (should be "kubernetes.io/basic-auth")`, testSecretName),
|
||||||
ObservedGeneration: 1234,
|
ObservedGeneration: 1234,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -318,6 +347,194 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: fmt.Sprintf(`referenced Secret "%s" is missing required keys ["username" "password"]`, testSecretName),
|
Message: fmt.Sprintf(`referenced Secret "%s" is missing required keys ["username" "password"]`, testSecretName),
|
||||||
ObservedGeneration: 1234,
|
ObservedGeneration: 1234,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CertificateAuthorityData is not base64 encoded",
|
||||||
|
ldapDialer: successfulDialer,
|
||||||
|
inputUpstreams: []runtime.Object{modifiedCopyOfValidUpstream(func(upstream *v1alpha1.LDAPIdentityProvider) {
|
||||||
|
upstream.Spec.TLS.CertificateAuthorityData = "this-is-not-base64-encoded"
|
||||||
|
})},
|
||||||
|
inputSecrets: []runtime.Object{&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: testSecretName, Namespace: testNamespace},
|
||||||
|
Type: corev1.SecretTypeBasicAuth,
|
||||||
|
Data: testValidSecretData,
|
||||||
|
}},
|
||||||
|
wantErr: controllerlib.ErrSyntheticRequeue.Error(),
|
||||||
|
wantResultingCache: []*upstreamldap.Provider{},
|
||||||
|
wantResultingUpstreams: []v1alpha1.LDAPIdentityProvider{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
|
||||||
|
Status: v1alpha1.LDAPIdentityProviderStatus{
|
||||||
|
Phase: "Error",
|
||||||
|
Conditions: []v1alpha1.Condition{
|
||||||
|
{
|
||||||
|
Type: "BindSecretValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded bind secret",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "False",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "InvalidTLSConfig",
|
||||||
|
Message: "certificateAuthorityData is invalid: illegal base64 data at input byte 4",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "CertificateAuthorityData is not valid pem data",
|
||||||
|
ldapDialer: successfulDialer,
|
||||||
|
inputUpstreams: []runtime.Object{modifiedCopyOfValidUpstream(func(upstream *v1alpha1.LDAPIdentityProvider) {
|
||||||
|
upstream.Spec.TLS.CertificateAuthorityData = base64.StdEncoding.EncodeToString([]byte("this is not pem data"))
|
||||||
|
})},
|
||||||
|
inputSecrets: []runtime.Object{&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: testSecretName, Namespace: testNamespace},
|
||||||
|
Type: corev1.SecretTypeBasicAuth,
|
||||||
|
Data: testValidSecretData,
|
||||||
|
}},
|
||||||
|
wantErr: controllerlib.ErrSyntheticRequeue.Error(),
|
||||||
|
wantResultingCache: []*upstreamldap.Provider{},
|
||||||
|
wantResultingUpstreams: []v1alpha1.LDAPIdentityProvider{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
|
||||||
|
Status: v1alpha1.LDAPIdentityProviderStatus{
|
||||||
|
Phase: "Error",
|
||||||
|
Conditions: []v1alpha1.Condition{
|
||||||
|
{
|
||||||
|
Type: "BindSecretValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded bind secret",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "False",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "InvalidTLSConfig",
|
||||||
|
Message: "certificateAuthorityData is invalid: no certificates found",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil TLS configuration",
|
||||||
|
ldapDialer: successfulDialer,
|
||||||
|
inputUpstreams: []runtime.Object{modifiedCopyOfValidUpstream(func(upstream *v1alpha1.LDAPIdentityProvider) {
|
||||||
|
upstream.Spec.TLS = nil
|
||||||
|
})},
|
||||||
|
inputSecrets: []runtime.Object{&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: testSecretName, Namespace: testNamespace},
|
||||||
|
Type: corev1.SecretTypeBasicAuth,
|
||||||
|
Data: testValidSecretData,
|
||||||
|
}},
|
||||||
|
wantResultingCache: []*upstreamldap.Provider{
|
||||||
|
{
|
||||||
|
Name: testName,
|
||||||
|
Host: testHost,
|
||||||
|
CABundle: nil,
|
||||||
|
BindUsername: testBindUsername,
|
||||||
|
BindPassword: testBindPassword,
|
||||||
|
UserSearch: &upstreamldap.UserSearch{
|
||||||
|
Base: testUserSearchBase,
|
||||||
|
Filter: testUserSearchFilter,
|
||||||
|
UsernameAttribute: testUsernameAttrName,
|
||||||
|
UIDAttribute: testUIDAttrName,
|
||||||
|
},
|
||||||
|
Dialer: successfulDialer, // the dialer passed to the controller's constructor should have been passed through
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantResultingUpstreams: []v1alpha1.LDAPIdentityProvider{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
|
||||||
|
Status: v1alpha1.LDAPIdentityProviderStatus{
|
||||||
|
Phase: "Ready",
|
||||||
|
Conditions: []v1alpha1.Condition{
|
||||||
|
{
|
||||||
|
Type: "BindSecretValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded bind secret",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "no TLS configuration provided",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-nil TLS configuration with empty CertificateAuthorityData",
|
||||||
|
ldapDialer: successfulDialer,
|
||||||
|
inputUpstreams: []runtime.Object{modifiedCopyOfValidUpstream(func(upstream *v1alpha1.LDAPIdentityProvider) {
|
||||||
|
upstream.Spec.TLS.CertificateAuthorityData = ""
|
||||||
|
})},
|
||||||
|
inputSecrets: []runtime.Object{&corev1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: testSecretName, Namespace: testNamespace},
|
||||||
|
Type: corev1.SecretTypeBasicAuth,
|
||||||
|
Data: testValidSecretData,
|
||||||
|
}},
|
||||||
|
wantResultingCache: []*upstreamldap.Provider{
|
||||||
|
{
|
||||||
|
Name: testName,
|
||||||
|
Host: testHost,
|
||||||
|
CABundle: nil,
|
||||||
|
BindUsername: testBindUsername,
|
||||||
|
BindPassword: testBindPassword,
|
||||||
|
UserSearch: &upstreamldap.UserSearch{
|
||||||
|
Base: testUserSearchBase,
|
||||||
|
Filter: testUserSearchFilter,
|
||||||
|
UsernameAttribute: testUsernameAttrName,
|
||||||
|
UIDAttribute: testUIDAttrName,
|
||||||
|
},
|
||||||
|
Dialer: successfulDialer, // the dialer passed to the controller's constructor should have been passed through
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantResultingUpstreams: []v1alpha1.LDAPIdentityProvider{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234},
|
||||||
|
Status: v1alpha1.LDAPIdentityProviderStatus{
|
||||||
|
Phase: "Ready",
|
||||||
|
Conditions: []v1alpha1.Condition{
|
||||||
|
{
|
||||||
|
Type: "BindSecretValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded bind secret",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -351,6 +568,14 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: fmt.Sprintf(`secret "%s" not found`, "non-existent-secret"),
|
Message: fmt.Sprintf(`secret "%s" not found`, "non-existent-secret"),
|
||||||
ObservedGeneration: 42,
|
ObservedGeneration: 42,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 42,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -367,6 +592,14 @@ func TestLDAPUpstreamWatcherControllerSync(t *testing.T) {
|
|||||||
Message: "loaded bind secret",
|
Message: "loaded bind secret",
|
||||||
ObservedGeneration: 1234,
|
ObservedGeneration: 1234,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: "TLSConfigurationValid",
|
||||||
|
Status: "True",
|
||||||
|
LastTransitionTime: now,
|
||||||
|
Reason: "Success",
|
||||||
|
Message: "loaded TLS configuration",
|
||||||
|
ObservedGeneration: 1234,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -60,7 +60,7 @@ type Provider struct {
|
|||||||
// the default LDAP port will be used.
|
// the default LDAP port will be used.
|
||||||
Host string
|
Host string
|
||||||
|
|
||||||
// PEM-encoded CA cert bundle to trust when connecting to the LDAP server.
|
// PEM-encoded CA cert bundle to trust when connecting to the LDAP server. Can be nil.
|
||||||
CABundle []byte
|
CABundle []byte
|
||||||
|
|
||||||
// BindUsername is the username to use when performing a bind with the upstream LDAP IDP.
|
// BindUsername is the username to use when performing a bind with the upstream LDAP IDP.
|
||||||
|
@ -45,7 +45,9 @@ var (
|
|||||||
func TestAuthenticateUser(t *testing.T) {
|
func TestAuthenticateUser(t *testing.T) {
|
||||||
provider := func(editFunc func(p *Provider)) *Provider {
|
provider := func(editFunc func(p *Provider)) *Provider {
|
||||||
provider := &Provider{
|
provider := &Provider{
|
||||||
|
Name: "some-provider-name",
|
||||||
Host: testHost,
|
Host: testHost,
|
||||||
|
CABundle: nil, // this field is only used by the production dialer, which is replaced by a mock for this test
|
||||||
BindUsername: testBindUsername,
|
BindUsername: testBindUsername,
|
||||||
BindPassword: testBindPassword,
|
BindPassword: testBindPassword,
|
||||||
UserSearch: &UserSearch{
|
UserSearch: &UserSearch{
|
||||||
|
Loading…
Reference in New Issue
Block a user