unify TLS Spec between supervisor and concierge

Signed-off-by: Ashish Amarnath <ashish.amarnath@broadcom.com>
This commit is contained in:
Ashish Amarnath
2024-06-26 13:14:42 -07:00
committed by Ryan Richard
parent 080c75efe6
commit aab1ee9edc
3 changed files with 345 additions and 81 deletions

View File

@@ -9,10 +9,12 @@ import (
"fmt"
"github.com/pkg/errors"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers/core/v1"
"go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
supervisorv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
"go.pinniped.dev/internal/constable"
"go.pinniped.dev/internal/controller/conditionsutil"
)
@@ -27,14 +29,66 @@ const (
ErrNoCertificates = constable.Error("no certificates found")
)
// BuildCertPoolIDP reads the tlsSpec of the IDP and returns an X509 cert pool with the CA data that is read either from
type caBundleSource struct {
Kind string
Name string
Key string
}
// TLSSpec unifies the TLSSpec type that Supervisor and Concierge both individually define.
// unifying these two definitions to allow sharing code that will read the spec and translate it into a CA bundle
type TLSSpec struct {
// X.509 Certificate Authority (base64-encoded PEM bundle). If omitted, a default set of system roots will be trusted.
CertificateAuthorityData string
// Reference to a CA bundle in a secret or a configmap.
CertificateAuthorityDataSource *caBundleSource
}
// TLSSpecForSupervisor is a helper function to convert the Supervisor's TLSSpec to the unified TLSSpec
func TLSSpecForSupervisor(source *supervisorv1alpha1.TLSSpec) *TLSSpec {
if source == nil {
return nil
}
dest := &TLSSpec{
CertificateAuthorityData: source.CertificateAuthorityData,
}
if source.CertificateAuthorityDataSource != nil {
dest.CertificateAuthorityDataSource = &caBundleSource{
Kind: source.CertificateAuthorityDataSource.Kind,
Name: source.CertificateAuthorityDataSource.Name,
Key: source.CertificateAuthorityDataSource.Key,
}
}
return dest
}
// TlsSpecForConcierge is a helper function to convert the Concierge's TLSSpec to the unified TLSSpec
func TlsSpecForConcierge(source *conciergev1alpha1.TLSSpec) *TLSSpec {
if source == nil {
return nil
}
dest := &TLSSpec{
CertificateAuthorityData: source.CertificateAuthorityData,
}
if source.CertificateAuthorityDataSource != nil {
dest.CertificateAuthorityDataSource = &caBundleSource{
Kind: source.CertificateAuthorityDataSource.Kind,
Name: source.CertificateAuthorityDataSource.Name,
Key: source.CertificateAuthorityDataSource.Key,
}
}
return dest
}
// getCertPool reads the unified tlsSpec and returns an X509 cert pool with the CA data that is read either from
// the inline tls.certificateAuthorityData or from a kubernetes secret or a config map as specified in the
// tls.certificateAuthorityDataSource.
// If the provided tlsSpec is nil, a nil CA bundle will be returned.
// If the provided spec contains a CA bundle that is not properly encoded, an error will be returned.
// TODO: should this function be exposed outside this package?
func BuildCertPoolIDP(
tlsSpec *v1alpha1.TLSSpec,
func getCertPool(
tlsSpec *TLSSpec,
conditionPrefix string,
namespace string,
secretInformer v1.SecretInformer,
@@ -55,7 +109,7 @@ func BuildCertPoolIDP(
var err error
caBundle := tlsSpec.CertificateAuthorityData
field := fmt.Sprintf("%s.%s", conditionPrefix, "certificateAuthorityData")
// currently, the ca data supplied inline in the CRDs is expected to be base64 encoded.
// the ca data supplied inline in the CRDs is expected to be base64 encoded.
// However, the ca data read from kubernetes secrets or config map will not be base64 encoded.
// For kubernetes secrets, secret data read using the client-go code automatically decodes base64 encoded values.
// So a base64 decode is required only when fetching ca bundle from the tls.certificateAuthorityData field.
@@ -67,9 +121,7 @@ func BuildCertPoolIDP(
field = fmt.Sprintf("%s.%s", conditionPrefix, "certificateAuthorityDataSource")
caBundle, err = readCABundleFromSource(tlsSpec.CertificateAuthorityDataSource, namespace, secretInformer, configMapInformer)
if err != nil {
return nil, nil, fmt.Errorf("%s is invalid: failed to read CA bundle from source %s/%s/%s: %s",
field, tlsSpec.CertificateAuthorityDataSource.Kind, tlsSpec.CertificateAuthorityDataSource.Name,
tlsSpec.CertificateAuthorityDataSource.Key, err.Error())
return nil, nil, fmt.Errorf("%s is invalid: %s", field, err.Error())
}
}
@@ -81,7 +133,7 @@ func BuildCertPoolIDP(
if decodeRequired {
bundleBytes, err = base64.StdEncoding.DecodeString(caBundle)
if err != nil {
return nil, nil, fmt.Errorf("%s is invalid: %s", conditionPrefix, err.Error())
return nil, nil, fmt.Errorf("%s is invalid: %s", field, err.Error())
}
}
@@ -104,14 +156,14 @@ func BuildCertPoolIDP(
// TODO: it should suffice that this function returns a TLSConfigurationValid condition, and perhaps we could skip
// returning the error. This can be done once all controllers are able to use this function.
func ValidateTLSConfig(
tlsSpec *v1alpha1.TLSSpec,
tlsSpec *TLSSpec,
conditionPrefix string,
namespace string,
secretInformer v1.SecretInformer,
configMapInformer v1.ConfigMapInformer,
) (*v12.Condition, []byte, *x509.CertPool, error) {
) (*metav1.Condition, []byte, *x509.CertPool, error) {
// try to build a x509 cert pool using the ca data specified in the tlsSpec.
certPool, bundle, err := BuildCertPoolIDP(tlsSpec, conditionPrefix, namespace, secretInformer, configMapInformer)
certPool, bundle, err := getCertPool(tlsSpec, conditionPrefix, namespace, secretInformer, configMapInformer)
if err != nil {
// an error encountered during building a certpool using the ca data from the tlsSpec results in an invalid
// TLS condition.
@@ -126,14 +178,14 @@ func ValidateTLSConfig(
return validTLSCondition(fmt.Sprintf("%s is valid: %s", conditionPrefix, loadedTLSConfigurationMessage)), bundle, certPool, err
}
func readCABundleFromSource(source *v1alpha1.CABundleSource, namespace string, secretInformer v1.SecretInformer, configMapInformer v1.ConfigMapInformer) (string, error) {
func readCABundleFromSource(source *caBundleSource, namespace string, secretInformer v1.SecretInformer, configMapInformer v1.ConfigMapInformer) (string, error) {
switch source.Kind {
case "Secret":
return readCABundleFromK8sSecret(namespace, source.Name, source.Key, secretInformer)
case "ConfigMap":
return readCABundleFromK8sConfigMap(namespace, source.Name, source.Key, configMapInformer)
default:
return "", fmt.Errorf("unsupported CA bundle source: %s", source.Kind)
return "", fmt.Errorf("unsupported CA bundle source kind: %s", source.Kind)
}
}
@@ -142,6 +194,11 @@ func readCABundleFromK8sSecret(namespace string, name string, key string, secret
if err != nil {
return "", errors.Wrapf(err, "failed to get secret %s/%s", namespace, name)
}
// for kubernetes secrets to be used as a certificate authority data source, the secret should be of type
// kubernetes.io/tls or Opaque. It is an error to use a secret that is of any other type.
if s.Type != corev1.SecretTypeTLS && s.Type != corev1.SecretTypeOpaque {
return "", fmt.Errorf("secret %s/%s of type %s cannot be used as a certificate authority data source", namespace, name, s.Type)
}
// ca bundle in the secret is expected to exist in a specific key, if that key does not exist, then it is an error
if val, exists := s.Data[key]; exists {
return string(val), nil
@@ -162,19 +219,19 @@ func readCABundleFromK8sConfigMap(namespace string, name string, key string, con
return "", fmt.Errorf("key %s not found in configmap %s/%s", key, namespace, name)
}
func validTLSCondition(message string) *v12.Condition {
return &v12.Condition{
func validTLSCondition(message string) *metav1.Condition {
return &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: v12.ConditionTrue,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: message,
}
}
func invalidTLSCondition(message string) *v12.Condition {
return &v12.Condition{
func invalidTLSCondition(message string) *metav1.Condition {
return &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: v12.ConditionFalse,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: message,
}

View File

@@ -5,7 +5,6 @@ package tlsconfigutil
import (
"encoding/base64"
"fmt"
"testing"
"time"
@@ -17,8 +16,10 @@ import (
corev1informers "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes/fake"
idpv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
supervisorv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idp/v1alpha1"
"go.pinniped.dev/internal/certauthority"
"go.pinniped.dev/internal/controller/conditionsutil"
)
func TestValidateTLSConfig(t *testing.T) {
@@ -28,67 +29,90 @@ func TestValidateTLSConfig(t *testing.T) {
base64EncodedBundle := base64.StdEncoding.EncodeToString(bundle)
tests := []struct {
name string
tlsSpec *idpv1alpha1.TLSSpec
tlsSpec *TLSSpec
namespace string
k8sObjects []runtime.Object
expectedCondition *metav1.Condition
expectError bool
}{
{
name: "nil TLSSpec should generate a noTLSConfigurationMessage condition",
tlsSpec: nil,
expectedCondition: validTLSCondition(noTLSConfigurationMessage),
expectError: false,
name: "nil TLSSpec should generate a noTLSConfigurationMessage condition",
tlsSpec: nil,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: " + noTLSConfigurationMessage,
},
},
{
name: "empty inline ca data should generate a loadedTLSConfigurationMessage condition",
tlsSpec: &idpv1alpha1.TLSSpec{},
expectedCondition: validTLSCondition(loadedTLSConfigurationMessage),
expectError: false,
name: "empty inline ca data should generate a loadedTLSConfigurationMessage condition",
tlsSpec: &TLSSpec{},
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: " + noTLSConfigurationMessage,
},
},
{
name: "valid base64 encode ca data should generate a loadedTLSConfigurationMessage condition",
tlsSpec: &idpv1alpha1.TLSSpec{
tlsSpec: &TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
},
expectedCondition: validTLSCondition(loadedTLSConfigurationMessage),
expectError: false,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: " + loadedTLSConfigurationMessage,
},
},
{
name: "valid base64 encoded non cert data should generate a invalidTLSCondition condition",
tlsSpec: &idpv1alpha1.TLSSpec{
tlsSpec: &TLSSpec{
CertificateAuthorityData: "dGhpcyBpcyBzb21lIHRlc3QgZGF0YSB0aGF0IGlzIGJhc2U2NCBlbmNvZGVkIHRoYXQgaXMgbm90IGEgY2VydAo=",
},
expectedCondition: invalidTLSCondition(fmt.Sprintf("certificateAuthorityData is invalid: %s", ErrNoCertificates)),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityData is invalid: " + ErrNoCertificates.Error(),
},
},
{
name: "non-base64 encoded string as ca data should generate an invalidTLSCondition condition",
tlsSpec: &idpv1alpha1.TLSSpec{
tlsSpec: &TLSSpec{
CertificateAuthorityData: "non base64 encoded string",
},
expectedCondition: invalidTLSCondition("certificateAuthorityData is invalid: illegal base64 data"),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityData is invalid: illegal base64 data at input byte 3",
},
},
{
name: "supplying certificateAuthorityDataSource and certificateAuthorityData should generate an invalid condition",
tlsSpec: &idpv1alpha1.TLSSpec{
tlsSpec: &TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "super-secret",
Key: "ca-base64EncodedBundle",
},
},
expectedCondition: invalidTLSCondition("tls spec config error: both tls.certificateAuthorityDataSource and tls.certificateAuthorityData provided."),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls is invalid: both tls.certificateAuthorityDataSource and tls.certificateAuthorityData provided",
},
},
{
name: "should return ca bundle from kubernetes secret",
tlsSpec: &idpv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
name: "should return ca bundle from kubernetes secret of type tls",
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "awesome-secret",
Name: "awesome-secret-tls",
Key: "ca-bundle",
},
},
@@ -96,21 +120,86 @@ func TestValidateTLSConfig(t *testing.T) {
k8sObjects: []runtime.Object{
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "awesome-secret",
Name: "awesome-secret-tls",
Namespace: "awesome-namespace",
},
Type: corev1.SecretTypeTLS,
Data: map[string][]byte{
"ca-bundle": []byte(bundle),
"ca-bundle": bundle,
},
},
},
expectedCondition: validTLSCondition(fmt.Sprintf("tls is valid: %s", loadedTLSConfigurationMessage)),
expectError: false,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: loaded TLS configuration",
},
},
{
name: "should return ca bundle from kubernetes secret of type opaque",
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "awesome-secret-opaque",
Key: "ca-bundle",
},
},
namespace: "awesome-namespace",
k8sObjects: []runtime.Object{
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "awesome-secret-opaque",
Namespace: "awesome-namespace",
},
Type: corev1.SecretTypeOpaque,
Data: map[string][]byte{
"ca-bundle": bundle,
},
},
},
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: loaded TLS configuration",
},
},
{
name: "should return invalid condition when a secrets not of type tls or opaque are used as ca data source",
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "awesome-secret-ba",
Key: "ca-bundle",
},
},
namespace: "awesome-namespace",
k8sObjects: []runtime.Object{
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "awesome-secret-ba",
Namespace: "awesome-namespace",
},
Type: corev1.SecretTypeBasicAuth,
Data: map[string][]byte{
"ca-bundle": bundle,
},
},
},
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityDataSource is invalid: secret awesome-namespace/awesome-secret-ba of type kubernetes.io/basic-auth cannot be used as a certificate authority data source",
},
},
{
name: "should return ca bundle from kubernetes configMap",
tlsSpec: &idpv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "ConfigMap",
Name: "awesome-cm",
Key: "ca-bundle",
@@ -128,13 +217,17 @@ func TestValidateTLSConfig(t *testing.T) {
},
},
},
expectedCondition: validTLSCondition(fmt.Sprintf("tls is valid: %s", loadedTLSConfigurationMessage)),
expectError: false,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionTrue,
Reason: conditionsutil.ReasonSuccess,
Message: "tls is valid: loaded TLS configuration",
},
},
{
name: "should return invalid condition when failing to read ca bundle from kubernetes secret that does not exist",
tlsSpec: &idpv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "does-not-exist",
Key: "does-not-matter",
@@ -152,13 +245,17 @@ func TestValidateTLSConfig(t *testing.T) {
},
},
},
expectedCondition: invalidTLSCondition("tls.certificateAuthorityDataSource is invalid: failed to read from source"),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityDataSource is invalid: failed to get secret awesome-namespace/does-not-exist: secret \"does-not-exist\" not found",
},
},
{
name: "should return invalid condition when failing to read ca bundle from kubernetes configMap that does not exist",
tlsSpec: &idpv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "ConfigMap",
Name: "does-not-exist",
Key: "does-not-matter",
@@ -176,13 +273,17 @@ func TestValidateTLSConfig(t *testing.T) {
},
},
},
expectedCondition: invalidTLSCondition("tls.certificateAuthorityDataSource is invalid: failed to read from source"),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityDataSource is invalid: failed to get configmap awesome-namespace/does-not-exist: configmap \"does-not-exist\" not found",
},
},
{
name: "should return invalid condition when using an invalid certificate authority data source",
tlsSpec: &idpv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &idpv1alpha1.CABundleSource{
tlsSpec: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "SomethingElse",
Name: "does-not-exist",
Key: "does-not-matter",
@@ -200,8 +301,12 @@ func TestValidateTLSConfig(t *testing.T) {
},
},
},
expectedCondition: invalidTLSCondition("tls.certificateAuthorityDataSource is invalid: unsupported CA bundle source"),
expectError: true,
expectedCondition: &metav1.Condition{
Type: typeTLSConfigurationValid,
Status: metav1.ConditionFalse,
Reason: ReasonInvalidTLSConfig,
Message: "tls.certificateAuthorityDataSource is invalid: unsupported CA bundle source kind: SomethingElse",
},
},
}
@@ -231,15 +336,8 @@ func TestValidateTLSConfig(t *testing.T) {
close(stopConfigMapInformer)
// now the objects from kubernetes should be sync'd into the informer cache.
}
actualCondition, _, _, err := ValidateTLSConfig(tt.tlsSpec, "tls", tt.namespace, secretsInformer, configMapInformer)
if tt.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.expectedCondition.Type, actualCondition.Type)
require.Equal(t, tt.expectedCondition.Status, actualCondition.Status)
require.Equal(t, tt.expectedCondition.Reason, actualCondition.Reason)
}
actualCondition, _, _, _ := ValidateTLSConfig(tt.tlsSpec, "tls", tt.namespace, secretsInformer, configMapInformer)
require.Equal(t, tt.expectedCondition, actualCondition)
})
}
}
@@ -430,3 +528,111 @@ func TestReadCABundleFromK8sConfigMap(t *testing.T) {
})
}
}
func TestNewCommonTLSSpecForSupervisor(t *testing.T) {
testCA, err := certauthority.New("Test CA", 1*time.Hour)
require.NoError(t, err)
bundle := testCA.Bundle()
base64EncodedBundle := base64.StdEncoding.EncodeToString(bundle)
tests := []struct {
name string
supervisorTLSSpec *supervisorv1alpha1.TLSSpec
expected *TLSSpec
}{
{
name: "should return nil spec when supervisorTLSSpec is nil",
supervisorTLSSpec: nil,
expected: nil,
},
{
name: "should return tls spec with non-empty certificateAuthorityData",
supervisorTLSSpec: &supervisorv1alpha1.TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
CertificateAuthorityDataSource: nil,
},
expected: &TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
CertificateAuthorityDataSource: nil,
},
},
{
name: "should return tls spec with certificateAuthorityDataSource",
supervisorTLSSpec: &supervisorv1alpha1.TLSSpec{
CertificateAuthorityDataSource: &supervisorv1alpha1.CABundleSource{
Kind: "Secret",
Name: "awesome-secret",
Key: "ca-bundle",
},
},
expected: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "awesome-secret",
Key: "ca-bundle",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
actual := TLSSpecForSupervisor(tt.supervisorTLSSpec)
require.Equal(t, tt.expected, actual)
})
}
}
func TestNewCommonTlsSpecForConcierge(t *testing.T) {
testCA, err := certauthority.New("Test CA", 1*time.Hour)
require.NoError(t, err)
bundle := testCA.Bundle()
base64EncodedBundle := base64.StdEncoding.EncodeToString(bundle)
tests := []struct {
name string
conciergeTLSSpec *conciergev1alpha1.TLSSpec
expected *TLSSpec
}{
{
name: "should return nil spec when supervisorTLSSpec is nil",
conciergeTLSSpec: nil,
expected: nil,
},
{
name: "should return tls spec with non-empty certificateAuthorityData",
conciergeTLSSpec: &conciergev1alpha1.TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
CertificateAuthorityDataSource: nil,
},
expected: &TLSSpec{
CertificateAuthorityData: base64EncodedBundle,
CertificateAuthorityDataSource: nil,
},
},
{
name: "should return tls spec with certificateAuthorityDataSource",
conciergeTLSSpec: &conciergev1alpha1.TLSSpec{
CertificateAuthorityDataSource: &conciergev1alpha1.CABundleSource{
Kind: "Secret",
Name: "awesome-secret",
Key: "ca-bundle",
},
},
expected: &TLSSpec{
CertificateAuthorityDataSource: &caBundleSource{
Kind: "Secret",
Name: "awesome-secret",
Key: "ca-bundle",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
actual := TlsSpecForConcierge(tt.conciergeTLSSpec)
require.Equal(t, tt.expected, actual)
})
}
}