Configure name of the supervisor default TLS cert secret via ConfigMap
Signed-off-by: Andrew Keesler <akeesler@vmware.com>
This commit is contained in:
parent
978ecda758
commit
29e0ce5662
@ -113,6 +113,7 @@ func startControllers(
|
|||||||
WithController(
|
WithController(
|
||||||
supervisorconfig.NewTLSCertObserverController(
|
supervisorconfig.NewTLSCertObserverController(
|
||||||
dynamicTLSCertProvider,
|
dynamicTLSCertProvider,
|
||||||
|
cfg.NamesConfig.DefaultTLSCertificateSecret,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
pinnipedInformers.Config().V1alpha1().OIDCProviderConfigs(),
|
pinnipedInformers.Config().V1alpha1().OIDCProviderConfigs(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
|
@ -30,6 +30,8 @@ metadata:
|
|||||||
data:
|
data:
|
||||||
#@yaml/text-templated-strings
|
#@yaml/text-templated-strings
|
||||||
pinniped.yaml: |
|
pinniped.yaml: |
|
||||||
|
names:
|
||||||
|
defaultTLSCertificateSecret: (@= defaultResourceNameWithSuffix("default-tls-certificate") @)
|
||||||
labels: (@= json.encode(labels()).rstrip() @)
|
labels: (@= json.encode(labels()).rstrip() @)
|
||||||
---
|
---
|
||||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
|
@ -8,8 +8,11 @@ package supervisor
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
"go.pinniped.dev/internal/constable"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FromPath loads an Config from a provided local file path, inserts any
|
// FromPath loads an Config from a provided local file path, inserts any
|
||||||
@ -30,5 +33,20 @@ func FromPath(path string) (*Config, error) {
|
|||||||
config.Labels = make(map[string]string)
|
config.Labels = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := validateNames(&config.NamesConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("validate names: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateNames(names *NamesConfigSpec) error {
|
||||||
|
missingNames := []string{}
|
||||||
|
if names.DefaultTLSCertificateSecret == "" {
|
||||||
|
missingNames = append(missingNames, "defaultTLSCertificateSecret")
|
||||||
|
}
|
||||||
|
if len(missingNames) > 0 {
|
||||||
|
return constable.Error("missing required names: " + strings.Join(missingNames, ", "))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ func TestFromPath(t *testing.T) {
|
|||||||
name string
|
name string
|
||||||
yaml string
|
yaml string
|
||||||
wantConfig *Config
|
wantConfig *Config
|
||||||
|
wantError string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Happy",
|
name: "Happy",
|
||||||
@ -26,23 +27,40 @@ func TestFromPath(t *testing.T) {
|
|||||||
labels:
|
labels:
|
||||||
myLabelKey1: myLabelValue1
|
myLabelKey1: myLabelValue1
|
||||||
myLabelKey2: myLabelValue2
|
myLabelKey2: myLabelValue2
|
||||||
|
names:
|
||||||
|
defaultTLSCertificateSecret: my-secret-name
|
||||||
`),
|
`),
|
||||||
wantConfig: &Config{
|
wantConfig: &Config{
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"myLabelKey1": "myLabelValue1",
|
"myLabelKey1": "myLabelValue1",
|
||||||
"myLabelKey2": "myLabelValue2",
|
"myLabelKey2": "myLabelValue2",
|
||||||
},
|
},
|
||||||
|
NamesConfig: NamesConfigSpec{
|
||||||
|
DefaultTLSCertificateSecret: "my-secret-name",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "When only the required fields are present, causes other fields to be defaulted",
|
name: "When only the required fields are present, causes other fields to be defaulted",
|
||||||
yaml: here.Doc(`
|
yaml: here.Doc(`
|
||||||
---
|
---
|
||||||
|
names:
|
||||||
|
defaultTLSCertificateSecret: my-secret-name
|
||||||
`),
|
`),
|
||||||
wantConfig: &Config{
|
wantConfig: &Config{
|
||||||
Labels: map[string]string{},
|
Labels: map[string]string{},
|
||||||
|
NamesConfig: NamesConfigSpec{
|
||||||
|
DefaultTLSCertificateSecret: "my-secret-name",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "Missing defaultTLSCertificateSecret name",
|
||||||
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
`),
|
||||||
|
wantError: "validate names: missing required names: defaultTLSCertificateSecret",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
test := test
|
test := test
|
||||||
@ -62,8 +80,12 @@ func TestFromPath(t *testing.T) {
|
|||||||
// Test FromPath()
|
// Test FromPath()
|
||||||
config, err := FromPath(f.Name())
|
config, err := FromPath(f.Name())
|
||||||
|
|
||||||
require.NoError(t, err)
|
if test.wantError != "" {
|
||||||
require.Equal(t, test.wantConfig, config)
|
require.EqualError(t, err, test.wantError)
|
||||||
|
} else {
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, test.wantConfig, config)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,11 @@ package supervisor
|
|||||||
|
|
||||||
// Config contains knobs to setup an instance of the Pinniped Supervisor.
|
// Config contains knobs to setup an instance of the Pinniped Supervisor.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Labels map[string]string `json:"labels"`
|
Labels map[string]string `json:"labels"`
|
||||||
|
NamesConfig NamesConfigSpec `json:"names"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NamesConfigSpec configures the names of some Kubernetes resources for the Supervisor.
|
||||||
|
type NamesConfigSpec struct {
|
||||||
|
DefaultTLSCertificateSecret string `json:"defaultTLSCertificateSecret"`
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,11 @@ import (
|
|||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
)
|
)
|
||||||
|
|
||||||
const SecretNameForDefaultTLSCertificate = "default-tls-certificate" //nolint:gosec // this is not a hardcoded credential
|
|
||||||
|
|
||||||
type tlsCertObserverController struct {
|
type tlsCertObserverController struct {
|
||||||
issuerTLSCertSetter IssuerTLSCertSetter
|
issuerTLSCertSetter IssuerTLSCertSetter
|
||||||
oidcProviderConfigInformer v1alpha1.OIDCProviderConfigInformer
|
defaultTLSCertificateSecretName string
|
||||||
secretInformer corev1informers.SecretInformer
|
oidcProviderConfigInformer v1alpha1.OIDCProviderConfigInformer
|
||||||
|
secretInformer corev1informers.SecretInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
type IssuerTLSCertSetter interface {
|
type IssuerTLSCertSetter interface {
|
||||||
@ -33,6 +32,7 @@ type IssuerTLSCertSetter interface {
|
|||||||
|
|
||||||
func NewTLSCertObserverController(
|
func NewTLSCertObserverController(
|
||||||
issuerTLSCertSetter IssuerTLSCertSetter,
|
issuerTLSCertSetter IssuerTLSCertSetter,
|
||||||
|
defaultTLSCertificateSecretName string,
|
||||||
secretInformer corev1informers.SecretInformer,
|
secretInformer corev1informers.SecretInformer,
|
||||||
oidcProviderConfigInformer v1alpha1.OIDCProviderConfigInformer,
|
oidcProviderConfigInformer v1alpha1.OIDCProviderConfigInformer,
|
||||||
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
||||||
@ -41,9 +41,10 @@ func NewTLSCertObserverController(
|
|||||||
controllerlib.Config{
|
controllerlib.Config{
|
||||||
Name: "tls-certs-observer-controller",
|
Name: "tls-certs-observer-controller",
|
||||||
Syncer: &tlsCertObserverController{
|
Syncer: &tlsCertObserverController{
|
||||||
issuerTLSCertSetter: issuerTLSCertSetter,
|
issuerTLSCertSetter: issuerTLSCertSetter,
|
||||||
oidcProviderConfigInformer: oidcProviderConfigInformer,
|
defaultTLSCertificateSecretName: defaultTLSCertificateSecretName,
|
||||||
secretInformer: secretInformer,
|
oidcProviderConfigInformer: oidcProviderConfigInformer,
|
||||||
|
secretInformer: secretInformer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
@ -88,7 +89,7 @@ func (c *tlsCertObserverController) Sync(ctx controllerlib.Context) error {
|
|||||||
klog.InfoS("tlsCertObserverController Sync updated the TLS cert cache", "issuerHostCount", len(issuerHostToTLSCertMap))
|
klog.InfoS("tlsCertObserverController Sync updated the TLS cert cache", "issuerHostCount", len(issuerHostToTLSCertMap))
|
||||||
c.issuerTLSCertSetter.SetIssuerHostToTLSCertMap(issuerHostToTLSCertMap)
|
c.issuerTLSCertSetter.SetIssuerHostToTLSCertMap(issuerHostToTLSCertMap)
|
||||||
|
|
||||||
defaultCert, err := c.certFromSecret(ns, SecretNameForDefaultTLSCertificate)
|
defaultCert, err := c.certFromSecret(ns, c.defaultTLSCertificateSecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.issuerTLSCertSetter.SetDefaultTLSCert(nil)
|
c.issuerTLSCertSetter.SetDefaultTLSCert(nil)
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,6 +42,7 @@ func TestTLSCertObserverControllerInformerFilters(t *testing.T) {
|
|||||||
oidcProviderConfigInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().OIDCProviderConfigs()
|
oidcProviderConfigInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().OIDCProviderConfigs()
|
||||||
_ = NewTLSCertObserverController(
|
_ = NewTLSCertObserverController(
|
||||||
nil,
|
nil,
|
||||||
|
"", // don't care about the secret name for this test
|
||||||
secretsInformer,
|
secretsInformer,
|
||||||
oidcProviderConfigInformer,
|
oidcProviderConfigInformer,
|
||||||
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
|
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
|
||||||
@ -115,7 +116,10 @@ func (f *fakeIssuerTLSCertSetter) SetDefaultTLSCert(certificate *tls.Certificate
|
|||||||
|
|
||||||
func TestTLSCertObserverControllerSync(t *testing.T) {
|
func TestTLSCertObserverControllerSync(t *testing.T) {
|
||||||
spec.Run(t, "Sync", func(t *testing.T, when spec.G, it spec.S) {
|
spec.Run(t, "Sync", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
const installedInNamespace = "some-namespace"
|
const (
|
||||||
|
installedInNamespace = "some-namespace"
|
||||||
|
defaultTLSSecretName = "some-default-secret-name"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
r *require.Assertions
|
r *require.Assertions
|
||||||
@ -136,6 +140,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
|
|||||||
// Set this at the last second to allow for injection of server override.
|
// Set this at the last second to allow for injection of server override.
|
||||||
subject = NewTLSCertObserverController(
|
subject = NewTLSCertObserverController(
|
||||||
issuerTLSCertSetter,
|
issuerTLSCertSetter,
|
||||||
|
defaultTLSSecretName,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
pinnipedInformers.Config().V1alpha1().OIDCProviderConfigs(),
|
pinnipedInformers.Config().V1alpha1().OIDCProviderConfigs(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -324,7 +329,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
|
|||||||
r.Equal(expectedCertificate2, *actualCertificate2)
|
r.Equal(expectedCertificate2, *actualCertificate2)
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is also a default TLS cert secret called default-tls-certificate", func() {
|
when("there is also a default TLS cert secret with the configured default TLS cert secret name", func() {
|
||||||
var (
|
var (
|
||||||
expectedDefaultCertificate tls.Certificate
|
expectedDefaultCertificate tls.Certificate
|
||||||
)
|
)
|
||||||
@ -338,7 +343,7 @@ func TestTLSCertObserverControllerSync(t *testing.T) {
|
|||||||
expectedDefaultCertificate, err = tls.X509KeyPair(testCrt, testKey)
|
expectedDefaultCertificate, err = tls.X509KeyPair(testCrt, testKey)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
defaultTLSCertSecret := &corev1.Secret{
|
defaultTLSCertSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "default-tls-certificate", Namespace: installedInNamespace},
|
ObjectMeta: metav1.ObjectMeta{Name: defaultTLSSecretName, Namespace: installedInNamespace},
|
||||||
Data: map[string][]byte{"tls.crt": testCrt, "tls.key": testKey},
|
Data: map[string][]byte{"tls.crt": testCrt, "tls.key": testKey},
|
||||||
}
|
}
|
||||||
r.NoError(kubeInformerClient.Tracker().Add(defaultTLSCertSecret))
|
r.NoError(kubeInformerClient.Tracker().Add(defaultTLSCertSecret))
|
||||||
|
@ -135,7 +135,7 @@ func TestSupervisorTLSTerminationWithDefaultCerts(t *testing.T) {
|
|||||||
requireEndpointHasTLSErrorBecauseCertificatesAreNotReady(t, issuerUsingIPAddress)
|
requireEndpointHasTLSErrorBecauseCertificatesAreNotReady(t, issuerUsingIPAddress)
|
||||||
|
|
||||||
// Create a Secret at the special name which represents the default TLS cert.
|
// Create a Secret at the special name which represents the default TLS cert.
|
||||||
specialNameForDefaultTLSCertSecret := "default-tls-certificate" //nolint:gosec // this is not a hardcoded credential
|
specialNameForDefaultTLSCertSecret := "pinniped-supervisor-default-tls-certificate" //nolint:gosec // this is not a hardcoded credential
|
||||||
defaultCA := createTLSCertificateSecret(ctx, t, ns, "cert-hostname-doesnt-matter", []net.IP{ip}, specialNameForDefaultTLSCertSecret, kubeClient)
|
defaultCA := createTLSCertificateSecret(ctx, t, ns, "cert-hostname-doesnt-matter", []net.IP{ip}, specialNameForDefaultTLSCertSecret, kubeClient)
|
||||||
|
|
||||||
// Now that the Secret exists, we should be able to access the endpoints by IP address using the CA.
|
// Now that the Secret exists, we should be able to access the endpoints by IP address using the CA.
|
||||||
|
Loading…
Reference in New Issue
Block a user