Merge pull request #127 from vmware-tanzu/rename_stuff
Rename many of resources that are created in Kubernetes by Pinniped
This commit is contained in:
commit
49145791cc
@ -301,12 +301,15 @@ func startControllers(
|
|||||||
) {
|
) {
|
||||||
aVeryLongTime := time.Hour * 24 * 365 * 100
|
aVeryLongTime := time.Hour * 24 * 365 * 100
|
||||||
|
|
||||||
|
const certsSecretResourceName = "local-user-authenticator-tls-serving-certificate"
|
||||||
|
|
||||||
// Create controller manager.
|
// Create controller manager.
|
||||||
controllerManager := controllerlib.
|
controllerManager := controllerlib.
|
||||||
NewManager().
|
NewManager().
|
||||||
WithController(
|
WithController(
|
||||||
apicerts.NewCertsManagerController(
|
apicerts.NewCertsManagerController(
|
||||||
namespace,
|
namespace,
|
||||||
|
certsSecretResourceName,
|
||||||
kubeClient,
|
kubeClient,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -320,6 +323,7 @@ func startControllers(
|
|||||||
WithController(
|
WithController(
|
||||||
apicerts.NewCertsObserverController(
|
apicerts.NewCertsObserverController(
|
||||||
namespace,
|
namespace,
|
||||||
|
certsSecretResourceName,
|
||||||
dynamicCertProvider,
|
dynamicCertProvider,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -367,7 +371,7 @@ func run() error {
|
|||||||
startControllers(ctx, dynamicCertProvider, kubeClient, kubeInformers)
|
startControllers(ctx, dynamicCertProvider, kubeClient, kubeInformers)
|
||||||
klog.InfoS("controllers are ready")
|
klog.InfoS("controllers are ready")
|
||||||
|
|
||||||
//nolint: gosec
|
//nolint: gosec // Intentionally binding to all network interfaces.
|
||||||
l, err := net.Listen("tcp", ":443")
|
l, err := net.Listen("tcp", ":443")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot create listener: %w", err)
|
return fmt.Errorf("cannot create listener: %w", err)
|
||||||
|
@ -14,7 +14,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
@ -25,7 +24,6 @@ import (
|
|||||||
configv1alpha1 "go.pinniped.dev/generated/1.19/apis/config/v1alpha1"
|
configv1alpha1 "go.pinniped.dev/generated/1.19/apis/config/v1alpha1"
|
||||||
pinnipedclientset "go.pinniped.dev/generated/1.19/client/clientset/versioned"
|
pinnipedclientset "go.pinniped.dev/generated/1.19/client/clientset/versioned"
|
||||||
"go.pinniped.dev/internal/constable"
|
"go.pinniped.dev/internal/constable"
|
||||||
"go.pinniped.dev/internal/controller/issuerconfig"
|
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -239,20 +237,27 @@ func fetchPinnipedCredentialIssuerConfig(clientConfig clientcmd.ClientConfig, ku
|
|||||||
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
|
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
|
||||||
defer cancelFunc()
|
defer cancelFunc()
|
||||||
|
|
||||||
credentialIssuerConfig, err := clientset.ConfigV1alpha1().CredentialIssuerConfigs(pinnipedInstallationNamespace).Get(ctx, issuerconfig.ConfigName, metav1.GetOptions{})
|
credentialIssuerConfigs, err := clientset.ConfigV1alpha1().CredentialIssuerConfigs(pinnipedInstallationNamespace).List(ctx, metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if apierrors.IsNotFound(err) {
|
|
||||||
return nil, constable.Error(fmt.Sprintf(
|
|
||||||
`CredentialIssuerConfig "%s" was not found in namespace "%s". Is Pinniped installed on this cluster in namespace "%s"?`,
|
|
||||||
issuerconfig.ConfigName,
|
|
||||||
pinnipedInstallationNamespace,
|
|
||||||
pinnipedInstallationNamespace,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return credentialIssuerConfig, nil
|
if len(credentialIssuerConfigs.Items) == 0 {
|
||||||
|
return nil, constable.Error(fmt.Sprintf(
|
||||||
|
`No CredentialIssuerConfig was found in namespace "%s". Is Pinniped installed on this cluster in namespace "%s"?`,
|
||||||
|
pinnipedInstallationNamespace,
|
||||||
|
pinnipedInstallationNamespace,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(credentialIssuerConfigs.Items) > 1 {
|
||||||
|
return nil, constable.Error(fmt.Sprintf(
|
||||||
|
`More than one CredentialIssuerConfig was found in namespace "%s"`,
|
||||||
|
pinnipedInstallationNamespace,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &credentialIssuerConfigs.Items[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClientConfig(kubeconfigPathOverride string, currentContextName string) clientcmd.ClientConfig {
|
func newClientConfig(kubeconfigPathOverride string, currentContextName string) clientcmd.ClientConfig {
|
||||||
|
@ -200,8 +200,17 @@ func TestNewGetKubeConfigCmd(t *testing.T) {
|
|||||||
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
}, spec.Parallel(), spec.Report(report.Terminal{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint: unparam
|
func expectedKubeconfigYAML(
|
||||||
func expectedKubeconfigYAML(clusterCAData, clusterServer, command, token, pinnipedEndpoint, pinnipedCABundle, namespace string) string {
|
clusterCAData,
|
||||||
|
clusterServer,
|
||||||
|
command,
|
||||||
|
// nolint: unparam // Pass in the token even if it is always the same in practice
|
||||||
|
token,
|
||||||
|
pinnipedEndpoint,
|
||||||
|
pinnipedCABundle,
|
||||||
|
// nolint: unparam // Pass in the namespace even if it is always the same in practice
|
||||||
|
namespace string,
|
||||||
|
) string {
|
||||||
return here.Docf(`
|
return here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
clusters:
|
clusters:
|
||||||
@ -240,15 +249,21 @@ func expectedKubeconfigYAML(clusterCAData, clusterServer, command, token, pinnip
|
|||||||
`, clusterCAData, clusterServer, command, pinnipedEndpoint, pinnipedCABundle, namespace, token)
|
`, clusterCAData, clusterServer, command, pinnipedEndpoint, pinnipedCABundle, namespace, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCredentialIssuerConfig(server, certificateAuthorityData string) *configv1alpha1.CredentialIssuerConfig {
|
func newCredentialIssuerConfig(
|
||||||
|
name,
|
||||||
|
//nolint: unparam // Pass in the namespace even if it is always the same in practice
|
||||||
|
namespace,
|
||||||
|
server,
|
||||||
|
certificateAuthorityData string,
|
||||||
|
) *configv1alpha1.CredentialIssuerConfig {
|
||||||
return &configv1alpha1.CredentialIssuerConfig{
|
return &configv1alpha1.CredentialIssuerConfig{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "CredentialIssuerConfig",
|
Kind: "CredentialIssuerConfig",
|
||||||
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
|
APIVersion: configv1alpha1.SchemeGroupVersion.String(),
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pinniped-config",
|
Name: name,
|
||||||
Namespace: "some-namespace",
|
Namespace: namespace,
|
||||||
},
|
},
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerConfigKubeConfigInfo{
|
KubeConfigInfo: &configv1alpha1.CredentialIssuerConfigKubeConfigInfo{
|
||||||
@ -266,6 +281,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
var warningsBuffer *bytes.Buffer
|
var warningsBuffer *bytes.Buffer
|
||||||
var fullPathToSelf string
|
var fullPathToSelf string
|
||||||
var pinnipedClient *pinnipedfake.Clientset
|
var pinnipedClient *pinnipedfake.Clientset
|
||||||
|
const installationNamespace = "some-namespace"
|
||||||
|
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
r = require.New(t)
|
r = require.New(t)
|
||||||
@ -283,7 +299,12 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
when("the CredentialIssuerConfig is found on the cluster with a configuration that matches the existing kubeconfig", func() {
|
when("the CredentialIssuerConfig is found on the cluster with a configuration that matches the existing kubeconfig", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
r.NoError(pinnipedClient.Tracker().Add(
|
||||||
newCredentialIssuerConfig("https://fake-server-url-value", "fake-certificate-authority-data-value"),
|
newCredentialIssuerConfig(
|
||||||
|
"some-cic-name",
|
||||||
|
installationNamespace,
|
||||||
|
"https://fake-server-url-value",
|
||||||
|
"fake-certificate-authority-data-value",
|
||||||
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -294,7 +315,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -313,7 +334,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"https://fake-server-url-value",
|
"https://fake-server-url-value",
|
||||||
"fake-certificate-authority-data-value",
|
"fake-certificate-authority-data-value",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
), outputBuffer.String())
|
), outputBuffer.String())
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -327,10 +348,12 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
Resource: "credentialissuerconfigs",
|
Resource: "credentialissuerconfigs",
|
||||||
},
|
},
|
||||||
newCredentialIssuerConfig(
|
newCredentialIssuerConfig(
|
||||||
|
"some-cic-name",
|
||||||
|
installationNamespace,
|
||||||
"https://some-other-fake-server-url-value",
|
"https://some-other-fake-server-url-value",
|
||||||
"some-other-fake-certificate-authority-data-value",
|
"some-other-fake-certificate-authority-data-value",
|
||||||
),
|
),
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -342,7 +365,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"some-other-context",
|
"some-other-context",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://some-other-fake-server-url-value", restConfig.Host)
|
r.Equal("https://some-other-fake-server-url-value", restConfig.Host)
|
||||||
@ -361,7 +384,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"https://some-other-fake-server-url-value",
|
"https://some-other-fake-server-url-value",
|
||||||
"some-other-fake-certificate-authority-data-value",
|
"some-other-fake-certificate-authority-data-value",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
), outputBuffer.String())
|
), outputBuffer.String())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -373,7 +396,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"this-context-name-does-not-exist-in-kubeconfig.yaml",
|
"this-context-name-does-not-exist-in-kubeconfig.yaml",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
||||||
)
|
)
|
||||||
r.EqualError(err, `context "this-context-name-does-not-exist-in-kubeconfig.yaml" does not exist`)
|
r.EqualError(err, `context "this-context-name-does-not-exist-in-kubeconfig.yaml" does not exist`)
|
||||||
@ -390,7 +413,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
||||||
)
|
)
|
||||||
r.EqualError(err, "--token flag value cannot be empty")
|
r.EqualError(err, "--token flag value cannot be empty")
|
||||||
@ -406,7 +429,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/this-file-does-not-exist.yaml",
|
"./testdata/this-file-does-not-exist.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) { return pinnipedClient, nil },
|
||||||
)
|
)
|
||||||
r.EqualError(err, "stat ./testdata/this-file-does-not-exist.yaml: no such file or directory")
|
r.EqualError(err, "stat ./testdata/this-file-does-not-exist.yaml: no such file or directory")
|
||||||
@ -434,7 +457,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -453,7 +476,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"https://fake-server-url-value",
|
"https://fake-server-url-value",
|
||||||
"fake-certificate-authority-data-value",
|
"fake-certificate-authority-data-value",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
), outputBuffer.String())
|
), outputBuffer.String())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -474,7 +497,39 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
return pinnipedClient, nil
|
return pinnipedClient, nil
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
r.EqualError(err, `CredentialIssuerConfig "pinniped-config" was not found in namespace "this-is-the-wrong-namespace". Is Pinniped installed on this cluster in namespace "this-is-the-wrong-namespace"?`)
|
r.EqualError(err, `No CredentialIssuerConfig was found in namespace "this-is-the-wrong-namespace". Is Pinniped installed on this cluster in namespace "this-is-the-wrong-namespace"?`)
|
||||||
|
r.True(kubeClientCreatorFuncWasCalled)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
when("there is more than one CredentialIssuerConfig is found on the cluster", func() {
|
||||||
|
it.Before(func() {
|
||||||
|
r.NoError(pinnipedClient.Tracker().Add(
|
||||||
|
newCredentialIssuerConfig(
|
||||||
|
"another-cic-name",
|
||||||
|
installationNamespace,
|
||||||
|
"https://fake-server-url-value",
|
||||||
|
"fake-certificate-authority-data-value",
|
||||||
|
),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns an error", func() {
|
||||||
|
kubeClientCreatorFuncWasCalled := false
|
||||||
|
err := getKubeConfig(outputBuffer,
|
||||||
|
warningsBuffer,
|
||||||
|
"some-token",
|
||||||
|
"./testdata/kubeconfig.yaml",
|
||||||
|
"",
|
||||||
|
installationNamespace,
|
||||||
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
|
kubeClientCreatorFuncWasCalled = true
|
||||||
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
|
r.Equal("fake-certificate-authority-data-value", string(restConfig.CAData))
|
||||||
|
return pinnipedClient, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
r.EqualError(err, `More than one CredentialIssuerConfig was found in namespace "some-namespace"`)
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
r.True(kubeClientCreatorFuncWasCalled)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -484,7 +539,12 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
when("the Server doesn't match", func() {
|
when("the Server doesn't match", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
r.NoError(pinnipedClient.Tracker().Add(
|
||||||
newCredentialIssuerConfig("non-matching-pinniped-server-url", "fake-certificate-authority-data-value"),
|
newCredentialIssuerConfig(
|
||||||
|
"some-cic-name",
|
||||||
|
installationNamespace,
|
||||||
|
"non-matching-pinniped-server-url",
|
||||||
|
"fake-certificate-authority-data-value",
|
||||||
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -495,7 +555,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -517,7 +577,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"https://fake-server-url-value",
|
"https://fake-server-url-value",
|
||||||
"fake-certificate-authority-data-value",
|
"fake-certificate-authority-data-value",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
), outputBuffer.String())
|
), outputBuffer.String())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -525,7 +585,12 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
when("the CA doesn't match", func() {
|
when("the CA doesn't match", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
r.NoError(pinnipedClient.Tracker().Add(
|
r.NoError(pinnipedClient.Tracker().Add(
|
||||||
newCredentialIssuerConfig("https://fake-server-url-value", "non-matching-certificate-authority-data-value"),
|
newCredentialIssuerConfig(
|
||||||
|
"some-cic-name",
|
||||||
|
installationNamespace,
|
||||||
|
"https://fake-server-url-value",
|
||||||
|
"non-matching-certificate-authority-data-value",
|
||||||
|
),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -536,7 +601,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -558,7 +623,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"https://fake-server-url-value",
|
"https://fake-server-url-value",
|
||||||
"fake-certificate-authority-data-value",
|
"fake-certificate-authority-data-value",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
), outputBuffer.String())
|
), outputBuffer.String())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -574,7 +639,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pinniped-config",
|
Name: "pinniped-config",
|
||||||
Namespace: "some-namespace",
|
Namespace: installationNamespace,
|
||||||
},
|
},
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{},
|
Status: configv1alpha1.CredentialIssuerConfigStatus{},
|
||||||
},
|
},
|
||||||
@ -588,7 +653,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -611,7 +676,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
kubeClientCreatorFuncWasCalled = true
|
kubeClientCreatorFuncWasCalled = true
|
||||||
r.Equal("https://fake-server-url-value", restConfig.Host)
|
r.Equal("https://fake-server-url-value", restConfig.Host)
|
||||||
@ -620,7 +685,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
r.True(kubeClientCreatorFuncWasCalled)
|
r.True(kubeClientCreatorFuncWasCalled)
|
||||||
r.EqualError(err, `CredentialIssuerConfig "pinniped-config" was not found in namespace "some-namespace". Is Pinniped installed on this cluster in namespace "some-namespace"?`)
|
r.EqualError(err, `No CredentialIssuerConfig was found in namespace "some-namespace". Is Pinniped installed on this cluster in namespace "some-namespace"?`)
|
||||||
r.Empty(warningsBuffer.String())
|
r.Empty(warningsBuffer.String())
|
||||||
r.Empty(outputBuffer.String())
|
r.Empty(outputBuffer.String())
|
||||||
})
|
})
|
||||||
@ -633,7 +698,7 @@ func TestGetKubeConfig(t *testing.T) {
|
|||||||
"some-token",
|
"some-token",
|
||||||
"./testdata/kubeconfig.yaml",
|
"./testdata/kubeconfig.yaml",
|
||||||
"",
|
"",
|
||||||
"some-namespace",
|
installationNamespace,
|
||||||
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
func(restConfig *rest.Config) (pinnipedclientset.Interface, error) {
|
||||||
return nil, fmt.Errorf("some error getting CredentialIssuerConfig")
|
return nil, fmt.Errorf("some error getting CredentialIssuerConfig")
|
||||||
},
|
},
|
||||||
|
@ -54,7 +54,7 @@ kubectl create secret generic ryan \
|
|||||||
Fetch the auto-generated CA bundle for the `local-user-authenticator`'s HTTP TLS endpoint.
|
Fetch the auto-generated CA bundle for the `local-user-authenticator`'s HTTP TLS endpoint.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl get secret api-serving-cert --namespace local-user-authenticator \
|
kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator \
|
||||||
-o jsonpath={.data.caCertificate} \
|
-o jsonpath={.data.caCertificate} \
|
||||||
| base64 -d \
|
| base64 -d \
|
||||||
| tee /tmp/local-user-authenticator-ca
|
| tee /tmp/local-user-authenticator-ca
|
||||||
|
@ -14,7 +14,7 @@ metadata:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: local-user-authenticator-service-account
|
name: local-user-authenticator
|
||||||
namespace: local-user-authenticator
|
namespace: local-user-authenticator
|
||||||
---
|
---
|
||||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
@ -47,7 +47,7 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: local-user-authenticator
|
app: local-user-authenticator
|
||||||
spec:
|
spec:
|
||||||
serviceAccountName: local-user-authenticator-service-account
|
serviceAccountName: local-user-authenticator
|
||||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
- name: image-pull-secret
|
- name: image-pull-secret
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: local-user-authenticator-aggregated-api-server-role
|
name: local-user-authenticator
|
||||||
namespace: local-user-authenticator
|
namespace: local-user-authenticator
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
@ -18,13 +18,13 @@ rules:
|
|||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: local-user-authenticator-aggregated-api-server-role-binding
|
name: local-user-authenticator
|
||||||
namespace: local-user-authenticator
|
namespace: local-user-authenticator
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: local-user-authenticator-service-account
|
name: local-user-authenticator
|
||||||
namespace: local-user-authenticator
|
namespace: local-user-authenticator
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: Role
|
kind: Role
|
||||||
name: local-user-authenticator-aggregated-api-server-role
|
name: local-user-authenticator
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
@ -14,7 +14,7 @@ metadata:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@ -25,6 +25,7 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
app: #@ data.values.app_name
|
app: #@ data.values.app_name
|
||||||
data:
|
data:
|
||||||
|
#! If names.apiService is changed in this ConfigMap, must also change name of the ClusterIP Service resource below.
|
||||||
#@yaml/text-templated-strings
|
#@yaml/text-templated-strings
|
||||||
pinniped.yaml: |
|
pinniped.yaml: |
|
||||||
discovery:
|
discovery:
|
||||||
@ -33,6 +34,10 @@ data:
|
|||||||
servingCertificate:
|
servingCertificate:
|
||||||
durationSeconds: (@= str(data.values.api_serving_certificate_duration_seconds) @)
|
durationSeconds: (@= str(data.values.api_serving_certificate_duration_seconds) @)
|
||||||
renewBeforeSeconds: (@= str(data.values.api_serving_certificate_renew_before_seconds) @)
|
renewBeforeSeconds: (@= str(data.values.api_serving_certificate_renew_before_seconds) @)
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: (@= data.values.app_name + "-api-tls-serving-certificate" @)
|
||||||
|
credentialIssuerConfig: (@= data.values.app_name + "-config" @)
|
||||||
|
apiService: (@= data.values.app_name + "-api" @)
|
||||||
---
|
---
|
||||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@ -66,7 +71,7 @@ spec:
|
|||||||
annotations:
|
annotations:
|
||||||
scheduler.alpha.kubernetes.io/critical-pod: ""
|
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||||
spec:
|
spec:
|
||||||
serviceAccountName: #@ data.values.app_name + "-service-account"
|
serviceAccountName: #@ data.values.app_name
|
||||||
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
#@ if data.values.image_pull_dockerconfigjson and data.values.image_pull_dockerconfigjson != "":
|
||||||
imagePullSecrets:
|
imagePullSecrets:
|
||||||
- name: image-pull-secret
|
- name: image-pull-secret
|
||||||
@ -144,7 +149,8 @@ spec:
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: pinniped-api #! the golang code assumes this specific name as part of the common name during cert generation
|
#! If name is changed, must also change names.apiService in the ConfigMap above
|
||||||
|
name: #@ data.values.app_name + "-api"
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
labels:
|
labels:
|
||||||
app: #@ data.values.app_name
|
app: #@ data.values.app_name
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-cluster-role"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: [namespaces]
|
resources: [namespaces]
|
||||||
@ -23,14 +23,14 @@ rules:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-cluster-role-binding"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-cluster-role"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
#! Give permission to various objects within the app's own namespace
|
#! Give permission to various objects within the app's own namespace
|
||||||
@ -38,7 +38,7 @@ roleRef:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-role"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
@ -54,15 +54,15 @@ rules:
|
|||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-role-binding"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: Role
|
kind: Role
|
||||||
name: #@ data.values.app_name + "-aggregated-api-server-role"
|
name: #@ data.values.app_name + "-aggregated-api-server"
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
#! Give permission to list pods and pod exec in the kube-system namespace so we can find the API server's private key
|
#! Give permission to list pods and pod exec in the kube-system namespace so we can find the API server's private key
|
||||||
@ -70,7 +70,7 @@ roleRef:
|
|||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: Role
|
kind: Role
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-kube-system-pod-exec-role"
|
name: #@ data.values.app_name + "-kube-system-pod-exec"
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
@ -83,23 +83,23 @@ rules:
|
|||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-kube-system-pod-exec-role-binding"
|
name: #@ data.values.app_name + "-kube-system-pod-exec"
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: Role
|
kind: Role
|
||||||
name: #@ data.values.app_name + "-kube-system-pod-exec-role"
|
name: #@ data.values.app_name + "-kube-system-pod-exec"
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
#! Allow both authenticated and unauthenticated CredentialRequests (i.e. allow all requests)
|
#! Allow both authenticated and unauthenticated TokenCredentialRequests (i.e. allow all requests)
|
||||||
---
|
---
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-credentialrequests-cluster-role"
|
name: #@ data.values.app_name + "-create-token-credential-requests"
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [login.pinniped.dev]
|
- apiGroups: [login.pinniped.dev]
|
||||||
resources: [tokencredentialrequests]
|
resources: [tokencredentialrequests]
|
||||||
@ -108,7 +108,7 @@ rules:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-credentialrequests-cluster-role-binding"
|
name: #@ data.values.app_name + "-create-token-credential-requests"
|
||||||
subjects:
|
subjects:
|
||||||
- kind: Group
|
- kind: Group
|
||||||
name: system:authenticated
|
name: system:authenticated
|
||||||
@ -118,7 +118,7 @@ subjects:
|
|||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
name: #@ data.values.app_name + "-credentialrequests-cluster-role"
|
name: #@ data.values.app_name + "-create-token-credential-requests"
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
#! Give permissions for subjectaccessreviews, tokenreview that is needed by aggregated api servers
|
||||||
@ -126,11 +126,11 @@ roleRef:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-service-account-cluster-role-binding"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: ClusterRole
|
kind: ClusterRole
|
||||||
@ -142,11 +142,11 @@ roleRef:
|
|||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-extension-apiserver-authentication-reader-role-binding"
|
name: #@ data.values.app_name + "-extension-apiserver-authentication-reader"
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: Role
|
kind: Role
|
||||||
@ -158,7 +158,7 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-cluster-info-lister-watcher-role"
|
name: #@ data.values.app_name + "-cluster-info-lister-watcher"
|
||||||
namespace: kube-public
|
namespace: kube-public
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
@ -168,13 +168,13 @@ rules:
|
|||||||
kind: RoleBinding
|
kind: RoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1
|
apiVersion: rbac.authorization.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: #@ data.values.app_name + "-cluster-info-lister-watcher-role-binding"
|
name: #@ data.values.app_name + "-cluster-info-lister-watcher"
|
||||||
namespace: kube-public
|
namespace: kube-public
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: #@ data.values.app_name + "-service-account"
|
name: #@ data.values.app_name
|
||||||
namespace: #@ data.values.namespace
|
namespace: #@ data.values.namespace
|
||||||
roleRef:
|
roleRef:
|
||||||
kind: Role
|
kind: Role
|
||||||
name: #@ data.values.app_name + "-cluster-info-lister-watcher-role"
|
name: #@ data.values.app_name + "-cluster-info-lister-watcher"
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
1. Fetch the auto-generated CA bundle for the `local-user-authenticator`'s HTTP TLS endpoint.
|
1. Fetch the auto-generated CA bundle for the `local-user-authenticator`'s HTTP TLS endpoint.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl get secret api-serving-cert --namespace local-user-authenticator \
|
kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator \
|
||||||
-o jsonpath={.data.caCertificate} \
|
-o jsonpath={.data.caCertificate} \
|
||||||
| tee /tmp/local-user-authenticator-ca-base64-encoded
|
| tee /tmp/local-user-authenticator-ca-base64-encoded
|
||||||
```
|
```
|
||||||
@ -101,7 +101,7 @@
|
|||||||
```bash
|
```bash
|
||||||
pinniped get-kubeconfig --token "pinny-the-seal:password123" > /tmp/pinniped-kubeconfig
|
pinniped get-kubeconfig --token "pinny-the-seal:password123" > /tmp/pinniped-kubeconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the above command will print a warning to the screen. You can ignore this warning.
|
Note that the above command will print a warning to the screen. You can ignore this warning.
|
||||||
Pinniped tries to auto-discover the URL for the Kubernetes API server, but it is not able
|
Pinniped tries to auto-discover the URL for the Kubernetes API server, but it is not able
|
||||||
to do so on kind clusters. The warning is just letting you know that the Pinniped CLI decided
|
to do so on kind clusters. The warning is just letting you know that the Pinniped CLI decided
|
||||||
|
@ -35,7 +35,7 @@ function unittest_cmd() {
|
|||||||
else
|
else
|
||||||
cmd='go test'
|
cmd='go test'
|
||||||
fi
|
fi
|
||||||
echo "${cmd} -count 1 -short -race ./..."
|
echo "${cmd} -short -race ./..."
|
||||||
}
|
}
|
||||||
|
|
||||||
function with_modules() {
|
function with_modules() {
|
||||||
|
@ -177,7 +177,7 @@ kubectl create secret generic "$test_username" \
|
|||||||
app_name="pinniped"
|
app_name="pinniped"
|
||||||
namespace="integration"
|
namespace="integration"
|
||||||
webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate"
|
webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate"
|
||||||
webhook_ca_bundle="$(kubectl get secret api-serving-cert --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')"
|
webhook_ca_bundle="$(kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')"
|
||||||
discovery_url="$(TERM=dumb kubectl cluster-info | awk '/Kubernetes master/ {print $NF}')"
|
discovery_url="$(TERM=dumb kubectl cluster-info | awk '/Kubernetes master/ {print $NF}')"
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -26,8 +26,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
//nolint: gochecknoglobals
|
//nolint: gochecknoglobals
|
||||||
scheme = runtime.NewScheme()
|
scheme = runtime.NewScheme()
|
||||||
//nolint: gochecknoglobals
|
//nolint: gochecknoglobals, golint
|
||||||
//nolint: golint
|
|
||||||
Codecs = serializer.NewCodecFactory(scheme)
|
Codecs = serializer.NewCodecFactory(scheme)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,14 +16,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type apiServiceUpdaterController struct {
|
type apiServiceUpdaterController struct {
|
||||||
namespace string
|
namespace string
|
||||||
aggregatorClient aggregatorclient.Interface
|
certsSecretResourceName string
|
||||||
secretInformer corev1informers.SecretInformer
|
aggregatorClient aggregatorclient.Interface
|
||||||
apiServiceName string
|
secretInformer corev1informers.SecretInformer
|
||||||
|
apiServiceName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIServiceUpdaterController(
|
func NewAPIServiceUpdaterController(
|
||||||
namespace string,
|
namespace string,
|
||||||
|
certsSecretResourceName string,
|
||||||
apiServiceName string,
|
apiServiceName string,
|
||||||
aggregatorClient aggregatorclient.Interface,
|
aggregatorClient aggregatorclient.Interface,
|
||||||
secretInformer corev1informers.SecretInformer,
|
secretInformer corev1informers.SecretInformer,
|
||||||
@ -33,15 +35,16 @@ func NewAPIServiceUpdaterController(
|
|||||||
controllerlib.Config{
|
controllerlib.Config{
|
||||||
Name: "certs-manager-controller",
|
Name: "certs-manager-controller",
|
||||||
Syncer: &apiServiceUpdaterController{
|
Syncer: &apiServiceUpdaterController{
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
aggregatorClient: aggregatorClient,
|
certsSecretResourceName: certsSecretResourceName,
|
||||||
secretInformer: secretInformer,
|
aggregatorClient: aggregatorClient,
|
||||||
apiServiceName: apiServiceName,
|
secretInformer: secretInformer,
|
||||||
|
apiServiceName: apiServiceName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
secretInformer,
|
secretInformer,
|
||||||
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
|
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretResourceName, namespace),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -49,10 +52,10 @@ func NewAPIServiceUpdaterController(
|
|||||||
|
|
||||||
func (c *apiServiceUpdaterController) Sync(ctx controllerlib.Context) error {
|
func (c *apiServiceUpdaterController) Sync(ctx controllerlib.Context) error {
|
||||||
// Try to get the secret from the informer cache.
|
// Try to get the secret from the informer cache.
|
||||||
certSecret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(certsSecretName)
|
certSecret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(c.certsSecretResourceName)
|
||||||
notFound := k8serrors.IsNotFound(err)
|
notFound := k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, certsSecretName, err)
|
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
||||||
}
|
}
|
||||||
if notFound {
|
if notFound {
|
||||||
// The secret does not exist yet, so nothing to do.
|
// The secret does not exist yet, so nothing to do.
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
func TestAPIServiceUpdaterControllerOptions(t *testing.T) {
|
func TestAPIServiceUpdaterControllerOptions(t *testing.T) {
|
||||||
spec.Run(t, "options", func(t *testing.T, when spec.G, it spec.S) {
|
spec.Run(t, "options", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
const installedInNamespace = "some-namespace"
|
const installedInNamespace = "some-namespace"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
||||||
@ -41,6 +42,7 @@ func TestAPIServiceUpdaterControllerOptions(t *testing.T) {
|
|||||||
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
||||||
_ = NewAPIServiceUpdaterController(
|
_ = NewAPIServiceUpdaterController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
||||||
nil,
|
nil,
|
||||||
secretsInformer,
|
secretsInformer,
|
||||||
@ -55,8 +57,8 @@ func TestAPIServiceUpdaterControllerOptions(t *testing.T) {
|
|||||||
|
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
subject = secretsInformerFilter
|
subject = secretsInformerFilter
|
||||||
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: installedInNamespace}}
|
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: installedInNamespace}}
|
||||||
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: "wrong-namespace"}}
|
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: "wrong-namespace"}}
|
||||||
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
||||||
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
||||||
})
|
})
|
||||||
@ -102,6 +104,7 @@ func TestAPIServiceUpdaterControllerOptions(t *testing.T) {
|
|||||||
func TestAPIServiceUpdaterControllerSync(t *testing.T) {
|
func TestAPIServiceUpdaterControllerSync(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"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
|
|
||||||
@ -119,6 +122,7 @@ func TestAPIServiceUpdaterControllerSync(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 = NewAPIServiceUpdaterController(
|
subject = NewAPIServiceUpdaterController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
||||||
aggregatorAPIClient,
|
aggregatorAPIClient,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
@ -131,7 +135,7 @@ func TestAPIServiceUpdaterControllerSync(t *testing.T) {
|
|||||||
Name: subject.Name(),
|
Name: subject.Name(),
|
||||||
Key: controllerlib.Key{
|
Key: controllerlib.Key{
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +158,7 @@ func TestAPIServiceUpdaterControllerSync(t *testing.T) {
|
|||||||
timeoutContextCancel()
|
timeoutContextCancel()
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is not yet an api-serving-cert Secret in the installation namespace or it was deleted", func() {
|
when("there is not yet a serving cert Secret in the installation namespace or it was deleted", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
unrelatedSecret := &corev1.Secret{
|
unrelatedSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -174,11 +178,11 @@ func TestAPIServiceUpdaterControllerSync(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is an api-serving-cert Secret already in the installation namespace", func() {
|
when("there is a serving cert Secret already in the installation namespace", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
apiServingCertSecret := &corev1.Secret{
|
apiServingCertSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
|
@ -22,9 +22,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type certsExpirerController struct {
|
type certsExpirerController struct {
|
||||||
namespace string
|
namespace string
|
||||||
k8sClient kubernetes.Interface
|
certsSecretResourceName string
|
||||||
secretInformer corev1informers.SecretInformer
|
k8sClient kubernetes.Interface
|
||||||
|
secretInformer corev1informers.SecretInformer
|
||||||
|
|
||||||
// renewBefore is the amount of time after the cert's issuance where
|
// renewBefore is the amount of time after the cert's issuance where
|
||||||
// this controller will start to try to rotate it.
|
// this controller will start to try to rotate it.
|
||||||
@ -36,6 +37,7 @@ type certsExpirerController struct {
|
|||||||
// deletion forces rotation of the secret with the help of other controllers.
|
// deletion forces rotation of the secret with the help of other controllers.
|
||||||
func NewCertsExpirerController(
|
func NewCertsExpirerController(
|
||||||
namespace string,
|
namespace string,
|
||||||
|
certsSecretResourceName string,
|
||||||
k8sClient kubernetes.Interface,
|
k8sClient kubernetes.Interface,
|
||||||
secretInformer corev1informers.SecretInformer,
|
secretInformer corev1informers.SecretInformer,
|
||||||
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
||||||
@ -45,15 +47,16 @@ func NewCertsExpirerController(
|
|||||||
controllerlib.Config{
|
controllerlib.Config{
|
||||||
Name: "certs-expirer-controller",
|
Name: "certs-expirer-controller",
|
||||||
Syncer: &certsExpirerController{
|
Syncer: &certsExpirerController{
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
k8sClient: k8sClient,
|
certsSecretResourceName: certsSecretResourceName,
|
||||||
secretInformer: secretInformer,
|
k8sClient: k8sClient,
|
||||||
renewBefore: renewBefore,
|
secretInformer: secretInformer,
|
||||||
|
renewBefore: renewBefore,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
secretInformer,
|
secretInformer,
|
||||||
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
|
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretResourceName, namespace),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -61,10 +64,10 @@ func NewCertsExpirerController(
|
|||||||
|
|
||||||
// Sync implements controller.Syncer.Sync.
|
// Sync implements controller.Syncer.Sync.
|
||||||
func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
||||||
secret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(certsSecretName)
|
secret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(c.certsSecretResourceName)
|
||||||
notFound := k8serrors.IsNotFound(err)
|
notFound := k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, certsSecretName, err)
|
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
||||||
}
|
}
|
||||||
if notFound {
|
if notFound {
|
||||||
klog.Info("certsExpirerController Sync found that the secret does not exist yet or was deleted")
|
klog.Info("certsExpirerController Sync found that the secret does not exist yet or was deleted")
|
||||||
@ -87,7 +90,7 @@ func (c *certsExpirerController) Sync(ctx controllerlib.Context) error {
|
|||||||
err := c.k8sClient.
|
err := c.k8sClient.
|
||||||
CoreV1().
|
CoreV1().
|
||||||
Secrets(c.namespace).
|
Secrets(c.namespace).
|
||||||
Delete(ctx.Context, certsSecretName, metav1.DeleteOptions{})
|
Delete(ctx.Context, c.certsSecretResourceName, metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Do return an error here so that the controller library will reschedule
|
// Do return an error here so that the controller library will reschedule
|
||||||
// us to try deleting this cert again.
|
// us to try deleting this cert again.
|
||||||
|
@ -29,6 +29,8 @@ import (
|
|||||||
func TestExpirerControllerFilters(t *testing.T) {
|
func TestExpirerControllerFilters(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
namespace string
|
namespace string
|
||||||
@ -40,7 +42,7 @@ func TestExpirerControllerFilters(t *testing.T) {
|
|||||||
namespace: "good-namespace",
|
namespace: "good-namespace",
|
||||||
secret: corev1.Secret{
|
secret: corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: "good-namespace",
|
Namespace: "good-namespace",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -62,7 +64,7 @@ func TestExpirerControllerFilters(t *testing.T) {
|
|||||||
namespace: "good-namespacee",
|
namespace: "good-namespacee",
|
||||||
secret: corev1.Secret{
|
secret: corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: "bad-namespace",
|
Namespace: "bad-namespace",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -92,6 +94,7 @@ func TestExpirerControllerFilters(t *testing.T) {
|
|||||||
withInformer := testutil.NewObservableWithInformerOption()
|
withInformer := testutil.NewObservableWithInformerOption()
|
||||||
_ = NewCertsExpirerController(
|
_ = NewCertsExpirerController(
|
||||||
test.namespace,
|
test.namespace,
|
||||||
|
certsSecretResourceName,
|
||||||
nil, // k8sClient, not needed
|
nil, // k8sClient, not needed
|
||||||
secretsInformer,
|
secretsInformer,
|
||||||
withInformer.WithInformer,
|
withInformer.WithInformer,
|
||||||
@ -111,6 +114,8 @@ func TestExpirerControllerFilters(t *testing.T) {
|
|||||||
func TestExpirerControllerSync(t *testing.T) {
|
func TestExpirerControllerSync(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
renewBefore time.Duration
|
renewBefore time.Duration
|
||||||
@ -220,7 +225,7 @@ func TestExpirerControllerSync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kubeInformerClient := kubernetesfake.NewSimpleClientset()
|
kubeInformerClient := kubernetesfake.NewSimpleClientset()
|
||||||
name := "api-serving-cert" // See certs_manager.go.
|
name := certsSecretResourceName
|
||||||
namespace := "some-namespace"
|
namespace := "some-namespace"
|
||||||
if test.fillSecretData != nil {
|
if test.fillSecretData != nil {
|
||||||
secret := &corev1.Secret{
|
secret := &corev1.Secret{
|
||||||
@ -243,6 +248,7 @@ func TestExpirerControllerSync(t *testing.T) {
|
|||||||
|
|
||||||
c := NewCertsExpirerController(
|
c := NewCertsExpirerController(
|
||||||
namespace,
|
namespace,
|
||||||
|
certsSecretResourceName,
|
||||||
kubeAPIClient,
|
kubeAPIClient,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
|
@ -21,17 +21,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//nolint: gosec
|
|
||||||
certsSecretName = "api-serving-cert"
|
|
||||||
caCertificateSecretKey = "caCertificate"
|
caCertificateSecretKey = "caCertificate"
|
||||||
tlsPrivateKeySecretKey = "tlsPrivateKey"
|
tlsPrivateKeySecretKey = "tlsPrivateKey"
|
||||||
tlsCertificateChainSecretKey = "tlsCertificateChain"
|
tlsCertificateChainSecretKey = "tlsCertificateChain"
|
||||||
)
|
)
|
||||||
|
|
||||||
type certsManagerController struct {
|
type certsManagerController struct {
|
||||||
namespace string
|
namespace string
|
||||||
k8sClient kubernetes.Interface
|
certsSecretResourceName string
|
||||||
secretInformer corev1informers.SecretInformer
|
k8sClient kubernetes.Interface
|
||||||
|
secretInformer corev1informers.SecretInformer
|
||||||
|
|
||||||
// certDuration is the lifetime of both the serving certificate and its CA
|
// certDuration is the lifetime of both the serving certificate and its CA
|
||||||
// certificate that this controller will use when issuing the certificates.
|
// certificate that this controller will use when issuing the certificates.
|
||||||
@ -41,7 +40,9 @@ type certsManagerController struct {
|
|||||||
serviceNameForGeneratedCertCommonName string
|
serviceNameForGeneratedCertCommonName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCertsManagerController(namespace string,
|
func NewCertsManagerController(
|
||||||
|
namespace string,
|
||||||
|
certsSecretResourceName string,
|
||||||
k8sClient kubernetes.Interface,
|
k8sClient kubernetes.Interface,
|
||||||
secretInformer corev1informers.SecretInformer,
|
secretInformer corev1informers.SecretInformer,
|
||||||
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
||||||
@ -55,6 +56,7 @@ func NewCertsManagerController(namespace string,
|
|||||||
Name: "certs-manager-controller",
|
Name: "certs-manager-controller",
|
||||||
Syncer: &certsManagerController{
|
Syncer: &certsManagerController{
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
|
certsSecretResourceName: certsSecretResourceName,
|
||||||
k8sClient: k8sClient,
|
k8sClient: k8sClient,
|
||||||
secretInformer: secretInformer,
|
secretInformer: secretInformer,
|
||||||
certDuration: certDuration,
|
certDuration: certDuration,
|
||||||
@ -64,23 +66,23 @@ func NewCertsManagerController(namespace string,
|
|||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
secretInformer,
|
secretInformer,
|
||||||
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
|
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretResourceName, namespace),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
// Be sure to run once even if the Secret that the informer is watching doesn't exist.
|
// Be sure to run once even if the Secret that the informer is watching doesn't exist.
|
||||||
withInitialEvent(controllerlib.Key{
|
withInitialEvent(controllerlib.Key{
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Name: certsSecretName,
|
Name: certsSecretResourceName,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *certsManagerController) Sync(ctx controllerlib.Context) error {
|
func (c *certsManagerController) Sync(ctx controllerlib.Context) error {
|
||||||
// Try to get the secret from the informer cache.
|
// Try to get the secret from the informer cache.
|
||||||
_, err := c.secretInformer.Lister().Secrets(c.namespace).Get(certsSecretName)
|
_, err := c.secretInformer.Lister().Secrets(c.namespace).Get(c.certsSecretResourceName)
|
||||||
notFound := k8serrors.IsNotFound(err)
|
notFound := k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, certsSecretName, err)
|
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
||||||
}
|
}
|
||||||
if !notFound {
|
if !notFound {
|
||||||
// The secret already exists, so nothing to do.
|
// The secret already exists, so nothing to do.
|
||||||
@ -112,7 +114,7 @@ func (c *certsManagerController) Sync(ctx controllerlib.Context) error {
|
|||||||
secret := corev1.Secret{
|
secret := corev1.Secret{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: certsSecretName,
|
Name: c.certsSecretResourceName,
|
||||||
Namespace: c.namespace,
|
Namespace: c.namespace,
|
||||||
},
|
},
|
||||||
StringData: map[string]string{
|
StringData: map[string]string{
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
func TestManagerControllerOptions(t *testing.T) {
|
func TestManagerControllerOptions(t *testing.T) {
|
||||||
spec.Run(t, "options", func(t *testing.T, when spec.G, it spec.S) {
|
spec.Run(t, "options", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
const installedInNamespace = "some-namespace"
|
const installedInNamespace = "some-namespace"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
||||||
@ -38,7 +39,17 @@ func TestManagerControllerOptions(t *testing.T) {
|
|||||||
observableWithInformerOption = testutil.NewObservableWithInformerOption()
|
observableWithInformerOption = testutil.NewObservableWithInformerOption()
|
||||||
observableWithInitialEventOption = testutil.NewObservableWithInitialEventOption()
|
observableWithInitialEventOption = testutil.NewObservableWithInitialEventOption()
|
||||||
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
||||||
_ = NewCertsManagerController(installedInNamespace, nil, secretsInformer, observableWithInformerOption.WithInformer, observableWithInitialEventOption.WithInitialEvent, 0, "Pinniped CA", "pinniped-api")
|
_ = NewCertsManagerController(
|
||||||
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
|
nil,
|
||||||
|
secretsInformer,
|
||||||
|
observableWithInformerOption.WithInformer,
|
||||||
|
observableWithInitialEventOption.WithInitialEvent,
|
||||||
|
0,
|
||||||
|
"Pinniped CA",
|
||||||
|
"pinniped-api",
|
||||||
|
)
|
||||||
secretsInformerFilter = observableWithInformerOption.GetFilterForInformer(secretsInformer)
|
secretsInformerFilter = observableWithInformerOption.GetFilterForInformer(secretsInformer)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -48,8 +59,8 @@ func TestManagerControllerOptions(t *testing.T) {
|
|||||||
|
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
subject = secretsInformerFilter
|
subject = secretsInformerFilter
|
||||||
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: installedInNamespace}}
|
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: installedInNamespace}}
|
||||||
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: "wrong-namespace"}}
|
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: "wrong-namespace"}}
|
||||||
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
||||||
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
||||||
})
|
})
|
||||||
@ -94,7 +105,7 @@ func TestManagerControllerOptions(t *testing.T) {
|
|||||||
it("asks for an initial event because the Secret may not exist yet and it needs to run anyway", func() {
|
it("asks for an initial event because the Secret may not exist yet and it needs to run anyway", func() {
|
||||||
r.Equal(controllerlib.Key{
|
r.Equal(controllerlib.Key{
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
}, observableWithInitialEventOption.GetInitialEventKey())
|
}, observableWithInitialEventOption.GetInitialEventKey())
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -104,6 +115,7 @@ func TestManagerControllerOptions(t *testing.T) {
|
|||||||
func TestManagerControllerSync(t *testing.T) {
|
func TestManagerControllerSync(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"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
const certDuration = 12345678 * time.Second
|
const certDuration = 12345678 * time.Second
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
@ -122,6 +134,7 @@ func TestManagerControllerSync(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 = NewCertsManagerController(
|
subject = NewCertsManagerController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
kubeAPIClient,
|
kubeAPIClient,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -137,7 +150,7 @@ func TestManagerControllerSync(t *testing.T) {
|
|||||||
Name: subject.Name(),
|
Name: subject.Name(),
|
||||||
Key: controllerlib.Key{
|
Key: controllerlib.Key{
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +173,7 @@ func TestManagerControllerSync(t *testing.T) {
|
|||||||
timeoutContextCancel()
|
timeoutContextCancel()
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is not yet an api-serving-cert Secret in the installation namespace or it was deleted", func() {
|
when("there is not yet a serving cert Secret in the installation namespace or it was deleted", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
unrelatedSecret := &corev1.Secret{
|
unrelatedSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -172,7 +185,7 @@ func TestManagerControllerSync(t *testing.T) {
|
|||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("creates the api-serving-cert Secret", func() {
|
it("creates the serving cert Secret", func() {
|
||||||
startInformersAndController()
|
startInformersAndController()
|
||||||
err := controllerlib.TestSync(t, subject, *syncContext)
|
err := controllerlib.TestSync(t, subject, *syncContext)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
@ -183,7 +196,7 @@ func TestManagerControllerSync(t *testing.T) {
|
|||||||
r.Equal(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}, actualAction.GetResource())
|
r.Equal(schema.GroupVersionResource{Group: "", Version: "v1", Resource: "secrets"}, actualAction.GetResource())
|
||||||
r.Equal(installedInNamespace, actualAction.GetNamespace())
|
r.Equal(installedInNamespace, actualAction.GetNamespace())
|
||||||
actualSecret := actualAction.GetObject().(*corev1.Secret)
|
actualSecret := actualAction.GetObject().(*corev1.Secret)
|
||||||
r.Equal("api-serving-cert", actualSecret.Name)
|
r.Equal(certsSecretResourceName, actualSecret.Name)
|
||||||
r.Equal(installedInNamespace, actualSecret.Namespace)
|
r.Equal(installedInNamespace, actualSecret.Namespace)
|
||||||
actualCACert := actualSecret.StringData["caCertificate"]
|
actualCACert := actualSecret.StringData["caCertificate"]
|
||||||
actualPrivateKey := actualSecret.StringData["tlsPrivateKey"]
|
actualPrivateKey := actualSecret.StringData["tlsPrivateKey"]
|
||||||
@ -222,11 +235,11 @@ func TestManagerControllerSync(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is an api-serving-cert Secret already in the installation namespace", func() {
|
when("there is a serving cert Secret already in the installation namespace", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
apiServingCertSecret := &corev1.Secret{
|
apiServingCertSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type certsObserverController struct {
|
type certsObserverController struct {
|
||||||
namespace string
|
namespace string
|
||||||
dynamicCertProvider provider.DynamicTLSServingCertProvider
|
certsSecretResourceName string
|
||||||
secretInformer corev1informers.SecretInformer
|
dynamicCertProvider provider.DynamicTLSServingCertProvider
|
||||||
|
secretInformer corev1informers.SecretInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCertsObserverController(
|
func NewCertsObserverController(
|
||||||
namespace string,
|
namespace string,
|
||||||
|
certsSecretResourceName string,
|
||||||
dynamicCertProvider provider.DynamicTLSServingCertProvider,
|
dynamicCertProvider provider.DynamicTLSServingCertProvider,
|
||||||
secretInformer corev1informers.SecretInformer,
|
secretInformer corev1informers.SecretInformer,
|
||||||
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
withInformer pinnipedcontroller.WithInformerOptionFunc,
|
||||||
@ -31,14 +33,15 @@ func NewCertsObserverController(
|
|||||||
controllerlib.Config{
|
controllerlib.Config{
|
||||||
Name: "certs-observer-controller",
|
Name: "certs-observer-controller",
|
||||||
Syncer: &certsObserverController{
|
Syncer: &certsObserverController{
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
dynamicCertProvider: dynamicCertProvider,
|
certsSecretResourceName: certsSecretResourceName,
|
||||||
secretInformer: secretInformer,
|
dynamicCertProvider: dynamicCertProvider,
|
||||||
|
secretInformer: secretInformer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
secretInformer,
|
secretInformer,
|
||||||
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretName, namespace),
|
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(certsSecretResourceName, namespace),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -46,10 +49,10 @@ func NewCertsObserverController(
|
|||||||
|
|
||||||
func (c *certsObserverController) Sync(_ controllerlib.Context) error {
|
func (c *certsObserverController) Sync(_ controllerlib.Context) error {
|
||||||
// Try to get the secret from the informer cache.
|
// Try to get the secret from the informer cache.
|
||||||
certSecret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(certsSecretName)
|
certSecret, err := c.secretInformer.Lister().Secrets(c.namespace).Get(c.certsSecretResourceName)
|
||||||
notFound := k8serrors.IsNotFound(err)
|
notFound := k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, certsSecretName, err)
|
return fmt.Errorf("failed to get %s/%s secret: %w", c.namespace, c.certsSecretResourceName, err)
|
||||||
}
|
}
|
||||||
if notFound {
|
if notFound {
|
||||||
klog.Info("certsObserverController Sync found that the secret does not exist yet or was deleted")
|
klog.Info("certsObserverController Sync found that the secret does not exist yet or was deleted")
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
func TestObserverControllerInformerFilters(t *testing.T) {
|
func TestObserverControllerInformerFilters(t *testing.T) {
|
||||||
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
|
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
const installedInNamespace = "some-namespace"
|
const installedInNamespace = "some-namespace"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
var observableWithInformerOption *testutil.ObservableWithInformerOption
|
||||||
@ -35,6 +36,7 @@ func TestObserverControllerInformerFilters(t *testing.T) {
|
|||||||
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
secretsInformer := kubeinformers.NewSharedInformerFactory(nil, 0).Core().V1().Secrets()
|
||||||
_ = NewCertsObserverController(
|
_ = NewCertsObserverController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
nil,
|
nil,
|
||||||
secretsInformer,
|
secretsInformer,
|
||||||
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
|
observableWithInformerOption.WithInformer, // make it possible to observe the behavior of the Filters
|
||||||
@ -48,8 +50,8 @@ func TestObserverControllerInformerFilters(t *testing.T) {
|
|||||||
|
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
subject = secretsInformerFilter
|
subject = secretsInformerFilter
|
||||||
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: installedInNamespace}}
|
target = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: installedInNamespace}}
|
||||||
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "api-serving-cert", Namespace: "wrong-namespace"}}
|
wrongNamespace = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: certsSecretResourceName, Namespace: "wrong-namespace"}}
|
||||||
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
wrongName = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace}}
|
||||||
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
unrelated = &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: "wrong-namespace"}}
|
||||||
})
|
})
|
||||||
@ -95,6 +97,7 @@ func TestObserverControllerInformerFilters(t *testing.T) {
|
|||||||
func TestObserverControllerSync(t *testing.T) {
|
func TestObserverControllerSync(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"
|
||||||
|
const certsSecretResourceName = "some-resource-name"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
|
|
||||||
@ -112,6 +115,7 @@ func TestObserverControllerSync(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 = NewCertsObserverController(
|
subject = NewCertsObserverController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
certsSecretResourceName,
|
||||||
dynamicCertProvider,
|
dynamicCertProvider,
|
||||||
kubeInformers.Core().V1().Secrets(),
|
kubeInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -123,7 +127,7 @@ func TestObserverControllerSync(t *testing.T) {
|
|||||||
Name: subject.Name(),
|
Name: subject.Name(),
|
||||||
Key: controllerlib.Key{
|
Key: controllerlib.Key{
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +150,7 @@ func TestObserverControllerSync(t *testing.T) {
|
|||||||
timeoutContextCancel()
|
timeoutContextCancel()
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is not yet an api-serving-cert Secret in the installation namespace or it was deleted", func() {
|
when("there is not yet a serving cert Secret in the installation namespace or it was deleted", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
unrelatedSecret := &corev1.Secret{
|
unrelatedSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -171,11 +175,11 @@ func TestObserverControllerSync(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
when("there is an api-serving-cert Secret with the expected keys already in the installation namespace", func() {
|
when("there is a serving cert Secret with the expected keys already in the installation namespace", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
apiServingCertSecret := &corev1.Secret{
|
apiServingCertSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: map[string][]byte{
|
||||||
@ -201,11 +205,11 @@ func TestObserverControllerSync(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
when("the api-serving-cert Secret exists but is missing the expected keys", func() {
|
when("the serving cert Secret exists but is missing the expected keys", func() {
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
apiServingCertSecret := &corev1.Secret{
|
apiServingCertSecret := &corev1.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "api-serving-cert",
|
Name: certsSecretResourceName,
|
||||||
Namespace: installedInNamespace,
|
Namespace: installedInNamespace,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{},
|
Data: map[string][]byte{},
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
func CreateOrUpdateCredentialIssuerConfig(
|
func CreateOrUpdateCredentialIssuerConfig(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
credentialIssuerConfigNamespace string,
|
credentialIssuerConfigNamespace string,
|
||||||
|
credentialIssuerConfigResourceName string,
|
||||||
pinnipedClient pinnipedclientset.Interface,
|
pinnipedClient pinnipedclientset.Interface,
|
||||||
applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *configv1alpha1.CredentialIssuerConfig),
|
applyUpdatesToCredentialIssuerConfigFunc func(configToUpdate *configv1alpha1.CredentialIssuerConfig),
|
||||||
) error {
|
) error {
|
||||||
@ -26,7 +27,7 @@ func CreateOrUpdateCredentialIssuerConfig(
|
|||||||
existingCredentialIssuerConfig, err := pinnipedClient.
|
existingCredentialIssuerConfig, err := pinnipedClient.
|
||||||
ConfigV1alpha1().
|
ConfigV1alpha1().
|
||||||
CredentialIssuerConfigs(credentialIssuerConfigNamespace).
|
CredentialIssuerConfigs(credentialIssuerConfigNamespace).
|
||||||
Get(ctx, ConfigName, metav1.GetOptions{})
|
Get(ctx, credentialIssuerConfigResourceName, metav1.GetOptions{})
|
||||||
|
|
||||||
notFound := k8serrors.IsNotFound(err)
|
notFound := k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
@ -37,7 +38,7 @@ func CreateOrUpdateCredentialIssuerConfig(
|
|||||||
ctx,
|
ctx,
|
||||||
existingCredentialIssuerConfig,
|
existingCredentialIssuerConfig,
|
||||||
notFound,
|
notFound,
|
||||||
ConfigName,
|
credentialIssuerConfigResourceName,
|
||||||
credentialIssuerConfigNamespace,
|
credentialIssuerConfigNamespace,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
applyUpdatesToCredentialIssuerConfigFunc)
|
applyUpdatesToCredentialIssuerConfigFunc)
|
||||||
|
@ -30,7 +30,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
var pinnipedAPIClient *pinnipedfake.Clientset
|
var pinnipedAPIClient *pinnipedfake.Clientset
|
||||||
var credentialIssuerConfigGVR schema.GroupVersionResource
|
var credentialIssuerConfigGVR schema.GroupVersionResource
|
||||||
const installationNamespace = "some-namespace"
|
const installationNamespace = "some-namespace"
|
||||||
const configName = "pinniped-config"
|
const credentialIssuerConfigResourceName = "some-resource-name"
|
||||||
|
|
||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
r = require.New(t)
|
r = require.New(t)
|
||||||
@ -45,7 +45,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
|
|
||||||
when("the config does not exist", func() {
|
when("the config does not exist", func() {
|
||||||
it("creates a new config which includes only the updates made by the func parameter", func() {
|
it("creates a new config which includes only the updates made by the func parameter", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.KubeConfigInfo = &configv1alpha1.CredentialIssuerConfigKubeConfigInfo{
|
configToUpdate.Status.KubeConfigInfo = &configv1alpha1.CredentialIssuerConfigKubeConfigInfo{
|
||||||
CertificateAuthorityData: "some-ca-value",
|
CertificateAuthorityData: "some-ca-value",
|
||||||
@ -54,7 +54,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
)
|
)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, configName)
|
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, credentialIssuerConfigResourceName)
|
||||||
|
|
||||||
expectedCreateAction := coretesting.NewCreateAction(
|
expectedCreateAction := coretesting.NewCreateAction(
|
||||||
credentialIssuerConfigGVR,
|
credentialIssuerConfigGVR,
|
||||||
@ -62,7 +62,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuerConfig{
|
&configv1alpha1.CredentialIssuerConfig{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: configName,
|
Name: credentialIssuerConfigResourceName,
|
||||||
Namespace: installationNamespace,
|
Namespace: installationNamespace,
|
||||||
},
|
},
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
||||||
@ -86,7 +86,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns an error", func() {
|
it("returns an error", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {},
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {},
|
||||||
)
|
)
|
||||||
r.EqualError(err, "could not create or update credentialissuerconfig: create failed: error on create")
|
r.EqualError(err, "could not create or update credentialissuerconfig: create failed: error on create")
|
||||||
@ -101,7 +101,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
existingConfig = &configv1alpha1.CredentialIssuerConfig{
|
existingConfig = &configv1alpha1.CredentialIssuerConfig{
|
||||||
TypeMeta: metav1.TypeMeta{},
|
TypeMeta: metav1.TypeMeta{},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: configName,
|
Name: credentialIssuerConfigResourceName,
|
||||||
Namespace: installationNamespace,
|
Namespace: installationNamespace,
|
||||||
},
|
},
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
||||||
@ -124,14 +124,14 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("updates the existing config to only apply the updates made by the func parameter", func() {
|
it("updates the existing config to only apply the updates made by the func parameter", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, configName)
|
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, credentialIssuerConfigResourceName)
|
||||||
|
|
||||||
// Only the edited field should be changed.
|
// Only the edited field should be changed.
|
||||||
expectedUpdatedConfig := existingConfig.DeepCopy()
|
expectedUpdatedConfig := existingConfig.DeepCopy()
|
||||||
@ -142,7 +142,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("avoids the cost of an update if the local updates made by the func parameter did not actually change anything", func() {
|
it("avoids the cost of an update if the local updates made by the func parameter did not actually change anything", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "initial-ca-value"
|
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "initial-ca-value"
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
)
|
)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, configName)
|
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, credentialIssuerConfigResourceName)
|
||||||
r.Equal([]coretesting.Action{expectedGetAction}, pinnipedAPIClient.Actions())
|
r.Equal([]coretesting.Action{expectedGetAction}, pinnipedAPIClient.Actions())
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns an error", func() {
|
it("returns an error", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {},
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {},
|
||||||
)
|
)
|
||||||
r.EqualError(err, "could not create or update credentialissuerconfig: get failed: error on get")
|
r.EqualError(err, "could not create or update credentialissuerconfig: get failed: error on get")
|
||||||
@ -181,7 +181,7 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("returns an error", func() {
|
it("returns an error", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||||
},
|
},
|
||||||
@ -215,14 +215,14 @@ func TestCreateOrUpdateCredentialIssuerConfig(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("retries updates on conflict", func() {
|
it("retries updates on conflict", func() {
|
||||||
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, pinnipedAPIClient,
|
err := CreateOrUpdateCredentialIssuerConfig(ctx, installationNamespace, credentialIssuerConfigResourceName, pinnipedAPIClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
configToUpdate.Status.KubeConfigInfo.CertificateAuthorityData = "new-ca-value"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, configName)
|
expectedGetAction := coretesting.NewGetAction(credentialIssuerConfigGVR, installationNamespace, credentialIssuerConfigResourceName)
|
||||||
|
|
||||||
// The first attempted update only includes its own edits.
|
// The first attempted update only includes its own edits.
|
||||||
firstExpectedUpdatedConfig := existingConfig.DeepCopy()
|
firstExpectedUpdatedConfig := existingConfig.DeepCopy()
|
||||||
|
@ -20,24 +20,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ClusterInfoNamespace = "kube-public"
|
ClusterInfoNamespace = "kube-public"
|
||||||
|
|
||||||
ConfigName = "pinniped-config"
|
|
||||||
|
|
||||||
clusterInfoName = "cluster-info"
|
clusterInfoName = "cluster-info"
|
||||||
clusterInfoConfigMapKey = "kubeconfig"
|
clusterInfoConfigMapKey = "kubeconfig"
|
||||||
)
|
)
|
||||||
|
|
||||||
type publisherController struct {
|
type publisherController struct {
|
||||||
namespace string
|
namespace string
|
||||||
serverOverride *string
|
credentialIssuerConfigResourceName string
|
||||||
pinnipedClient pinnipedclientset.Interface
|
serverOverride *string
|
||||||
configMapInformer corev1informers.ConfigMapInformer
|
pinnipedClient pinnipedclientset.Interface
|
||||||
credentialIssuerConfigInformer configv1alpha1informers.CredentialIssuerConfigInformer
|
configMapInformer corev1informers.ConfigMapInformer
|
||||||
|
credentialIssuerConfigInformer configv1alpha1informers.CredentialIssuerConfigInformer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPublisherController(
|
func NewPublisherController(namespace string,
|
||||||
namespace string,
|
credentialIssuerConfigResourceName string,
|
||||||
serverOverride *string,
|
serverOverride *string,
|
||||||
pinnipedClient pinnipedclientset.Interface,
|
pinnipedClient pinnipedclientset.Interface,
|
||||||
configMapInformer corev1informers.ConfigMapInformer,
|
configMapInformer corev1informers.ConfigMapInformer,
|
||||||
@ -48,11 +46,12 @@ func NewPublisherController(
|
|||||||
controllerlib.Config{
|
controllerlib.Config{
|
||||||
Name: "publisher-controller",
|
Name: "publisher-controller",
|
||||||
Syncer: &publisherController{
|
Syncer: &publisherController{
|
||||||
namespace: namespace,
|
credentialIssuerConfigResourceName: credentialIssuerConfigResourceName,
|
||||||
serverOverride: serverOverride,
|
namespace: namespace,
|
||||||
pinnipedClient: pinnipedClient,
|
serverOverride: serverOverride,
|
||||||
configMapInformer: configMapInformer,
|
pinnipedClient: pinnipedClient,
|
||||||
credentialIssuerConfigInformer: credentialIssuerConfigInformer,
|
configMapInformer: configMapInformer,
|
||||||
|
credentialIssuerConfigInformer: credentialIssuerConfigInformer,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
withInformer(
|
withInformer(
|
||||||
@ -62,7 +61,7 @@ func NewPublisherController(
|
|||||||
),
|
),
|
||||||
withInformer(
|
withInformer(
|
||||||
credentialIssuerConfigInformer,
|
credentialIssuerConfigInformer,
|
||||||
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(ConfigName, namespace),
|
pinnipedcontroller.NameAndNamespaceExactMatchFilterFactory(credentialIssuerConfigResourceName, namespace),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -112,7 +111,7 @@ func (c *publisherController) Sync(ctx controllerlib.Context) error {
|
|||||||
existingCredentialIssuerConfigFromInformerCache, err := c.credentialIssuerConfigInformer.
|
existingCredentialIssuerConfigFromInformerCache, err := c.credentialIssuerConfigInformer.
|
||||||
Lister().
|
Lister().
|
||||||
CredentialIssuerConfigs(c.namespace).
|
CredentialIssuerConfigs(c.namespace).
|
||||||
Get(ConfigName)
|
Get(c.credentialIssuerConfigResourceName)
|
||||||
notFound = k8serrors.IsNotFound(err)
|
notFound = k8serrors.IsNotFound(err)
|
||||||
if err != nil && !notFound {
|
if err != nil && !notFound {
|
||||||
return fmt.Errorf("could not get credentialissuerconfig: %w", err)
|
return fmt.Errorf("could not get credentialissuerconfig: %w", err)
|
||||||
@ -129,7 +128,7 @@ func (c *publisherController) Sync(ctx controllerlib.Context) error {
|
|||||||
ctx.Context,
|
ctx.Context,
|
||||||
existingCredentialIssuerConfigFromInformerCache,
|
existingCredentialIssuerConfigFromInformerCache,
|
||||||
notFound,
|
notFound,
|
||||||
ConfigName,
|
c.credentialIssuerConfigResourceName,
|
||||||
c.namespace,
|
c.namespace,
|
||||||
c.pinnipedClient,
|
c.pinnipedClient,
|
||||||
updateServerAndCAFunc)
|
updateServerAndCAFunc)
|
||||||
|
@ -30,6 +30,7 @@ import (
|
|||||||
|
|
||||||
func TestInformerFilters(t *testing.T) {
|
func TestInformerFilters(t *testing.T) {
|
||||||
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
|
spec.Run(t, "informer filters", func(t *testing.T, when spec.G, it spec.S) {
|
||||||
|
const credentialIssuerConfigResourceName = "some-resource-name"
|
||||||
const installedInNamespace = "some-namespace"
|
const installedInNamespace = "some-namespace"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
@ -44,6 +45,7 @@ func TestInformerFilters(t *testing.T) {
|
|||||||
credentialIssuerConfigInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().CredentialIssuerConfigs()
|
credentialIssuerConfigInformer := pinnipedinformers.NewSharedInformerFactory(nil, 0).Config().V1alpha1().CredentialIssuerConfigs()
|
||||||
_ = NewPublisherController(
|
_ = NewPublisherController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
credentialIssuerConfigResourceName,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
configMapInformer,
|
configMapInformer,
|
||||||
@ -109,10 +111,10 @@ func TestInformerFilters(t *testing.T) {
|
|||||||
it.Before(func() {
|
it.Before(func() {
|
||||||
subject = credentialIssuerConfigInformerFilter
|
subject = credentialIssuerConfigInformerFilter
|
||||||
target = &configv1alpha1.CredentialIssuerConfig{
|
target = &configv1alpha1.CredentialIssuerConfig{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: installedInNamespace},
|
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerConfigResourceName, Namespace: installedInNamespace},
|
||||||
}
|
}
|
||||||
wrongNamespace = &configv1alpha1.CredentialIssuerConfig{
|
wrongNamespace = &configv1alpha1.CredentialIssuerConfig{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "pinniped-config", Namespace: "wrong-namespace"},
|
ObjectMeta: metav1.ObjectMeta{Name: credentialIssuerConfigResourceName, Namespace: "wrong-namespace"},
|
||||||
}
|
}
|
||||||
wrongName = &configv1alpha1.CredentialIssuerConfig{
|
wrongName = &configv1alpha1.CredentialIssuerConfig{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace},
|
ObjectMeta: metav1.ObjectMeta{Name: "wrong-name", Namespace: installedInNamespace},
|
||||||
@ -162,6 +164,7 @@ func TestInformerFilters(t *testing.T) {
|
|||||||
|
|
||||||
func TestSync(t *testing.T) {
|
func TestSync(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 credentialIssuerConfigResourceName = "some-resource-name"
|
||||||
const installedInNamespace = "some-namespace"
|
const installedInNamespace = "some-namespace"
|
||||||
|
|
||||||
var r *require.Assertions
|
var r *require.Assertions
|
||||||
@ -185,7 +188,7 @@ func TestSync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
expectedCredentialIssuerConfig := &configv1alpha1.CredentialIssuerConfig{
|
expectedCredentialIssuerConfig := &configv1alpha1.CredentialIssuerConfig{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pinniped-config",
|
Name: credentialIssuerConfigResourceName,
|
||||||
Namespace: expectedNamespace,
|
Namespace: expectedNamespace,
|
||||||
},
|
},
|
||||||
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
Status: configv1alpha1.CredentialIssuerConfigStatus{
|
||||||
@ -205,6 +208,7 @@ func TestSync(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 = NewPublisherController(
|
subject = NewPublisherController(
|
||||||
installedInNamespace,
|
installedInNamespace,
|
||||||
|
credentialIssuerConfigResourceName,
|
||||||
serverOverride,
|
serverOverride,
|
||||||
pinnipedAPIClient,
|
pinnipedAPIClient,
|
||||||
kubeInformers.Core().V1().ConfigMaps(),
|
kubeInformers.Core().V1().ConfigMaps(),
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/controller/issuerconfig"
|
"go.pinniped.dev/internal/controller/issuerconfig"
|
||||||
"go.pinniped.dev/internal/controllerlib"
|
"go.pinniped.dev/internal/controllerlib"
|
||||||
"go.pinniped.dev/internal/provider"
|
"go.pinniped.dev/internal/provider"
|
||||||
|
"go.pinniped.dev/pkg/config/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,6 +36,7 @@ const (
|
|||||||
// Prepare the controllers and their informers and return a function that will start them when called.
|
// Prepare the controllers and their informers and return a function that will start them when called.
|
||||||
func PrepareControllers(
|
func PrepareControllers(
|
||||||
serverInstallationNamespace string,
|
serverInstallationNamespace string,
|
||||||
|
namesConfig api.NamesConfigSpec,
|
||||||
discoveryURLOverride *string,
|
discoveryURLOverride *string,
|
||||||
dynamicCertProvider provider.DynamicTLSServingCertProvider,
|
dynamicCertProvider provider.DynamicTLSServingCertProvider,
|
||||||
servingCertDuration time.Duration,
|
servingCertDuration time.Duration,
|
||||||
@ -51,15 +53,12 @@ func PrepareControllers(
|
|||||||
kubePublicNamespaceK8sInformers, installationNamespaceK8sInformers, installationNamespacePinnipedInformers :=
|
kubePublicNamespaceK8sInformers, installationNamespaceK8sInformers, installationNamespacePinnipedInformers :=
|
||||||
createInformers(serverInstallationNamespace, k8sClient, pinnipedClient)
|
createInformers(serverInstallationNamespace, k8sClient, pinnipedClient)
|
||||||
|
|
||||||
// This string must match the name of the Service declared in the deployment yaml.
|
|
||||||
const serviceName = "pinniped-api"
|
|
||||||
|
|
||||||
// Create controller manager.
|
// Create controller manager.
|
||||||
controllerManager := controllerlib.
|
controllerManager := controllerlib.
|
||||||
NewManager().
|
NewManager().
|
||||||
WithController(
|
WithController(
|
||||||
issuerconfig.NewPublisherController(
|
issuerconfig.NewPublisherController(serverInstallationNamespace,
|
||||||
serverInstallationNamespace,
|
namesConfig.CredentialIssuerConfig,
|
||||||
discoveryURLOverride,
|
discoveryURLOverride,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
kubePublicNamespaceK8sInformers.Core().V1().ConfigMaps(),
|
kubePublicNamespaceK8sInformers.Core().V1().ConfigMaps(),
|
||||||
@ -71,19 +70,21 @@ func PrepareControllers(
|
|||||||
WithController(
|
WithController(
|
||||||
apicerts.NewCertsManagerController(
|
apicerts.NewCertsManagerController(
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
namesConfig.ServingCertificateSecret,
|
||||||
k8sClient,
|
k8sClient,
|
||||||
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
controllerlib.WithInitialEvent,
|
controllerlib.WithInitialEvent,
|
||||||
servingCertDuration,
|
servingCertDuration,
|
||||||
"Pinniped CA",
|
"Pinniped CA",
|
||||||
serviceName,
|
namesConfig.APIService,
|
||||||
),
|
),
|
||||||
singletonWorker,
|
singletonWorker,
|
||||||
).
|
).
|
||||||
WithController(
|
WithController(
|
||||||
apicerts.NewAPIServiceUpdaterController(
|
apicerts.NewAPIServiceUpdaterController(
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
namesConfig.ServingCertificateSecret,
|
||||||
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
loginv1alpha1.SchemeGroupVersion.Version+"."+loginv1alpha1.GroupName,
|
||||||
aggregatorClient,
|
aggregatorClient,
|
||||||
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
||||||
@ -94,6 +95,7 @@ func PrepareControllers(
|
|||||||
WithController(
|
WithController(
|
||||||
apicerts.NewCertsObserverController(
|
apicerts.NewCertsObserverController(
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
namesConfig.ServingCertificateSecret,
|
||||||
dynamicCertProvider,
|
dynamicCertProvider,
|
||||||
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -103,6 +105,7 @@ func PrepareControllers(
|
|||||||
WithController(
|
WithController(
|
||||||
apicerts.NewCertsExpirerController(
|
apicerts.NewCertsExpirerController(
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
namesConfig.ServingCertificateSecret,
|
||||||
k8sClient,
|
k8sClient,
|
||||||
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
installationNamespaceK8sInformers.Core().V1().Secrets(),
|
||||||
controllerlib.WithInformer,
|
controllerlib.WithInformer,
|
||||||
@ -177,7 +180,7 @@ func createClients() (
|
|||||||
return nil, nil, nil, fmt.Errorf("could not initialize pinniped client: %w", err)
|
return nil, nil, nil, fmt.Errorf("could not initialize pinniped client: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint: nakedret
|
//nolint: nakedret // Short function. Makes the order of return values more clear.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func (a *App) runServer(ctx context.Context) error {
|
|||||||
serverInstallationNamespace := podInfo.Namespace
|
serverInstallationNamespace := podInfo.Namespace
|
||||||
|
|
||||||
// Load the Kubernetes cluster signing CA.
|
// Load the Kubernetes cluster signing CA.
|
||||||
k8sClusterCA, shutdownCA, err := getClusterCASigner(ctx, serverInstallationNamespace)
|
k8sClusterCA, shutdownCA, err := getClusterCASigner(ctx, serverInstallationNamespace, cfg.NamesConfig.CredentialIssuerConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -133,6 +133,7 @@ func (a *App) runServer(ctx context.Context) error {
|
|||||||
// post start hook of the aggregated API server.
|
// post start hook of the aggregated API server.
|
||||||
startControllersFunc, err := controllermanager.PrepareControllers(
|
startControllersFunc, err := controllermanager.PrepareControllers(
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
cfg.NamesConfig,
|
||||||
cfg.DiscoveryInfo.URL,
|
cfg.DiscoveryInfo.URL,
|
||||||
dynamicCertProvider,
|
dynamicCertProvider,
|
||||||
time.Duration(*cfg.APIConfig.ServingCertificateConfig.DurationSeconds)*time.Second,
|
time.Duration(*cfg.APIConfig.ServingCertificateConfig.DurationSeconds)*time.Second,
|
||||||
@ -164,7 +165,10 @@ func (a *App) runServer(ctx context.Context) error {
|
|||||||
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
|
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
|
||||||
}
|
}
|
||||||
|
|
||||||
func getClusterCASigner(ctx context.Context, serverInstallationNamespace string) (credentialrequest.CertIssuer, kubecertauthority.ShutdownFunc, error) {
|
func getClusterCASigner(
|
||||||
|
ctx context.Context, serverInstallationNamespace string,
|
||||||
|
credentialIssuerConfigResourceName string,
|
||||||
|
) (credentialrequest.CertIssuer, kubecertauthority.ShutdownFunc, error) {
|
||||||
// Load the Kubernetes client configuration.
|
// Load the Kubernetes client configuration.
|
||||||
kubeConfig, err := restclient.InClusterConfig()
|
kubeConfig, err := restclient.InClusterConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -195,6 +199,7 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string)
|
|||||||
err = issuerconfig.CreateOrUpdateCredentialIssuerConfig(
|
err = issuerconfig.CreateOrUpdateCredentialIssuerConfig(
|
||||||
ctx,
|
ctx,
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
credentialIssuerConfigResourceName,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.Strategies = []configv1alpha1.CredentialIssuerConfigStrategy{
|
configToUpdate.Status.Strategies = []configv1alpha1.CredentialIssuerConfigStrategy{
|
||||||
@ -216,6 +221,7 @@ func getClusterCASigner(ctx context.Context, serverInstallationNamespace string)
|
|||||||
if updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig(
|
if updateErr := issuerconfig.CreateOrUpdateCredentialIssuerConfig(
|
||||||
ctx,
|
ctx,
|
||||||
serverInstallationNamespace,
|
serverInstallationNamespace,
|
||||||
|
credentialIssuerConfigResourceName,
|
||||||
pinnipedClient,
|
pinnipedClient,
|
||||||
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
func(configToUpdate *configv1alpha1.CredentialIssuerConfig) {
|
||||||
configToUpdate.Status.Strategies = []configv1alpha1.CredentialIssuerConfigStrategy{
|
configToUpdate.Status.Strategies = []configv1alpha1.CredentialIssuerConfigStrategy{
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
package api
|
package api
|
||||||
|
|
||||||
// Config contains knobs to setup an instance of pinniped.
|
// Config contains knobs to setup an instance of Pinniped.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DiscoveryInfo DiscoveryInfoSpec `json:"discovery"`
|
DiscoveryInfo DiscoveryInfoSpec `json:"discovery"`
|
||||||
APIConfig APIConfigSpec `json:"api"`
|
APIConfig APIConfigSpec `json:"api"`
|
||||||
|
NamesConfig NamesConfigSpec `json:"names"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscoveryInfoSpec contains configuration knobs specific to
|
// DiscoveryInfoSpec contains configuration knobs specific to
|
||||||
@ -18,12 +19,19 @@ type DiscoveryInfoSpec struct {
|
|||||||
URL *string `json:"url,omitempty"`
|
URL *string `json:"url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIConfigSpec contains configuration knobs for the pinniped API.
|
// APIConfigSpec contains configuration knobs for the Pinniped API.
|
||||||
//nolint: golint
|
//nolint: golint
|
||||||
type APIConfigSpec struct {
|
type APIConfigSpec struct {
|
||||||
ServingCertificateConfig ServingCertificateConfigSpec `json:"servingCertificate"`
|
ServingCertificateConfig ServingCertificateConfigSpec `json:"servingCertificate"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamesConfigSpec configures the names of some Kubernetes resources for Pinniped.
|
||||||
|
type NamesConfigSpec struct {
|
||||||
|
ServingCertificateSecret string `json:"servingCertificateSecret"`
|
||||||
|
CredentialIssuerConfig string `json:"credentialIssuerConfig"`
|
||||||
|
APIService string `json:"apiService"`
|
||||||
|
}
|
||||||
|
|
||||||
// ServingCertificateConfigSpec contains the configuration knobs for the API's
|
// ServingCertificateConfigSpec contains the configuration knobs for the API's
|
||||||
// serving certificate, i.e., the x509 certificate that it uses for the server
|
// serving certificate, i.e., the x509 certificate that it uses for the server
|
||||||
// certificate in inbound TLS connections.
|
// certificate in inbound TLS connections.
|
||||||
@ -34,10 +42,10 @@ type ServingCertificateConfigSpec struct {
|
|||||||
// CA certificate.
|
// CA certificate.
|
||||||
DurationSeconds *int64 `json:"durationSeconds,omitempty"`
|
DurationSeconds *int64 `json:"durationSeconds,omitempty"`
|
||||||
|
|
||||||
// RenewBeforeSeconds is the period of time, in seconds, that pinniped will
|
// RenewBeforeSeconds is the period of time, in seconds, that Pinniped will
|
||||||
// wait before rotating the serving certificate. This period of time starts
|
// wait before rotating the serving certificate. This period of time starts
|
||||||
// upon issuance of the serving certificate. This must be less than
|
// upon issuance of the serving certificate. This must be less than
|
||||||
// DurationSeconds. By default, pinniped begins rotation after 23328000
|
// DurationSeconds. By default, Pinniped begins rotation after 23328000
|
||||||
// seconds (about 9 months).
|
// seconds (about 9 months).
|
||||||
RenewBeforeSeconds *int64 `json:"renewBeforeSeconds,omitempty"`
|
RenewBeforeSeconds *int64 `json:"renewBeforeSeconds,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"sigs.k8s.io/yaml"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
@ -44,6 +45,10 @@ func FromPath(path string) (*api.Config, error) {
|
|||||||
return nil, fmt.Errorf("validate api: %w", err)
|
return nil, fmt.Errorf("validate api: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := validateNames(&config.NamesConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("validate names: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +62,27 @@ func maybeSetAPIDefaults(apiConfig *api.APIConfigSpec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateNames(names *api.NamesConfigSpec) error {
|
||||||
|
missingNames := []string{}
|
||||||
|
if names == nil {
|
||||||
|
missingNames = append(missingNames, "servingCertificateSecret", "credentialIssuerConfig", "apiService")
|
||||||
|
} else {
|
||||||
|
if names.ServingCertificateSecret == "" {
|
||||||
|
missingNames = append(missingNames, "servingCertificateSecret")
|
||||||
|
}
|
||||||
|
if names.CredentialIssuerConfig == "" {
|
||||||
|
missingNames = append(missingNames, "credentialIssuerConfig")
|
||||||
|
}
|
||||||
|
if names.APIService == "" {
|
||||||
|
missingNames = append(missingNames, "apiService")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(missingNames) > 0 {
|
||||||
|
return constable.Error("missing required names: " + strings.Join(missingNames, ", "))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func validateAPI(apiConfig *api.APIConfigSpec) error {
|
func validateAPI(apiConfig *api.APIConfigSpec) error {
|
||||||
if *apiConfig.ServingCertificateConfig.DurationSeconds < *apiConfig.ServingCertificateConfig.RenewBeforeSeconds {
|
if *apiConfig.ServingCertificateConfig.DurationSeconds < *apiConfig.ServingCertificateConfig.RenewBeforeSeconds {
|
||||||
return constable.Error("durationSeconds cannot be smaller than renewBeforeSeconds")
|
return constable.Error("durationSeconds cannot be smaller than renewBeforeSeconds")
|
||||||
|
@ -4,23 +4,38 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"go.pinniped.dev/internal/here"
|
||||||
"go.pinniped.dev/pkg/config/api"
|
"go.pinniped.dev/pkg/config/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromPath(t *testing.T) {
|
func TestFromPath(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
path string
|
yaml string
|
||||||
wantConfig *api.Config
|
wantConfig *api.Config
|
||||||
wantError string
|
wantError string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Happy",
|
name: "Happy",
|
||||||
path: "testdata/happy.yaml",
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
discovery:
|
||||||
|
url: https://some.discovery/url
|
||||||
|
api:
|
||||||
|
servingCertificate:
|
||||||
|
durationSeconds: 3600
|
||||||
|
renewBeforeSeconds: 2400
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
wantConfig: &api.Config{
|
wantConfig: &api.Config{
|
||||||
DiscoveryInfo: api.DiscoveryInfoSpec{
|
DiscoveryInfo: api.DiscoveryInfoSpec{
|
||||||
URL: stringPtr("https://some.discovery/url"),
|
URL: stringPtr("https://some.discovery/url"),
|
||||||
@ -31,11 +46,22 @@ func TestFromPath(t *testing.T) {
|
|||||||
RenewBeforeSeconds: int64Ptr(2400),
|
RenewBeforeSeconds: int64Ptr(2400),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
NamesConfig: api.NamesConfigSpec{
|
||||||
|
ServingCertificateSecret: "pinniped-api-tls-serving-certificate",
|
||||||
|
CredentialIssuerConfig: "pinniped-config",
|
||||||
|
APIService: "pinniped-api",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Default",
|
name: "When only the required fields are present, causes other fields to be defaulted",
|
||||||
path: "testdata/default.yaml",
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
wantConfig: &api.Config{
|
wantConfig: &api.Config{
|
||||||
DiscoveryInfo: api.DiscoveryInfoSpec{
|
DiscoveryInfo: api.DiscoveryInfoSpec{
|
||||||
URL: nil,
|
URL: nil,
|
||||||
@ -46,28 +72,112 @@ func TestFromPath(t *testing.T) {
|
|||||||
RenewBeforeSeconds: int64Ptr(60 * 60 * 24 * 30 * 9), // about 9 months
|
RenewBeforeSeconds: int64Ptr(60 * 60 * 24 * 30 * 9), // about 9 months
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
NamesConfig: api.NamesConfigSpec{
|
||||||
|
ServingCertificateSecret: "pinniped-api-tls-serving-certificate",
|
||||||
|
CredentialIssuerConfig: "pinniped-config",
|
||||||
|
APIService: "pinniped-api",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "InvalidDurationRenewBefore",
|
name: "Empty",
|
||||||
path: "testdata/invalid-duration-renew-before.yaml",
|
yaml: here.Doc(``),
|
||||||
|
wantError: "validate names: missing required names: servingCertificateSecret, credentialIssuerConfig, apiService",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Missing apiService name",
|
||||||
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
`),
|
||||||
|
wantError: "validate names: missing required names: apiService",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Missing credentialIssuerConfig name",
|
||||||
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
|
wantError: "validate names: missing required names: credentialIssuerConfig",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Missing servingCertificateSecret name",
|
||||||
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
names:
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
|
wantError: "validate names: missing required names: servingCertificateSecret",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidDurationRenewBefore",
|
||||||
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
api:
|
||||||
|
servingCertificate:
|
||||||
|
durationSeconds: 2400
|
||||||
|
renewBeforeSeconds: 3600
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
wantError: "validate api: durationSeconds cannot be smaller than renewBeforeSeconds",
|
wantError: "validate api: durationSeconds cannot be smaller than renewBeforeSeconds",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "NegativeRenewBefore",
|
name: "NegativeRenewBefore",
|
||||||
path: "testdata/negative-renew-before.yaml",
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
api:
|
||||||
|
servingCertificate:
|
||||||
|
durationSeconds: 2400
|
||||||
|
renewBeforeSeconds: -10
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
wantError: "validate api: renewBefore must be positive",
|
wantError: "validate api: renewBefore must be positive",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ZeroRenewBefore",
|
name: "ZeroRenewBefore",
|
||||||
path: "testdata/zero-renew-before.yaml",
|
yaml: here.Doc(`
|
||||||
|
---
|
||||||
|
api:
|
||||||
|
servingCertificate:
|
||||||
|
durationSeconds: 2400
|
||||||
|
renewBeforeSeconds: -10
|
||||||
|
names:
|
||||||
|
servingCertificateSecret: pinniped-api-tls-serving-certificate
|
||||||
|
credentialIssuerConfig: pinniped-config
|
||||||
|
apiService: pinniped-api
|
||||||
|
`),
|
||||||
wantError: "validate api: renewBefore must be positive",
|
wantError: "validate api: renewBefore must be positive",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
test := test
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
config, err := FromPath(test.path)
|
// Write yaml to temp file
|
||||||
|
f, err := ioutil.TempFile("", "pinniped-test-config-yaml-*")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() {
|
||||||
|
err := os.Remove(f.Name())
|
||||||
|
require.NoError(t, err)
|
||||||
|
}()
|
||||||
|
_, err = f.WriteString(test.yaml)
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = f.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Test FromPath()
|
||||||
|
config, err := FromPath(f.Name())
|
||||||
|
|
||||||
if test.wantError != "" {
|
if test.wantError != "" {
|
||||||
require.EqualError(t, err, test.wantError)
|
require.EqualError(t, err, test.wantError)
|
||||||
} else {
|
} else {
|
||||||
|
1
pkg/config/testdata/default.yaml
vendored
1
pkg/config/testdata/default.yaml
vendored
@ -1 +0,0 @@
|
|||||||
---
|
|
7
pkg/config/testdata/happy.yaml
vendored
7
pkg/config/testdata/happy.yaml
vendored
@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
discovery:
|
|
||||||
url: https://some.discovery/url
|
|
||||||
api:
|
|
||||||
servingCertificate:
|
|
||||||
durationSeconds: 3600
|
|
||||||
renewBeforeSeconds: 2400
|
|
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
api:
|
|
||||||
servingCertificate:
|
|
||||||
durationSeconds: 2400
|
|
||||||
renewBeforeSeconds: 3600
|
|
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
api:
|
|
||||||
servingCertificate:
|
|
||||||
durationSeconds: 2400
|
|
||||||
renewBeforeSeconds: -10
|
|
5
pkg/config/testdata/zero-renew-before.yaml
vendored
5
pkg/config/testdata/zero-renew-before.yaml
vendored
@ -1,5 +0,0 @@
|
|||||||
---
|
|
||||||
api:
|
|
||||||
servingCertificate:
|
|
||||||
durationSeconds: 2400
|
|
||||||
renewBeforeSeconds: -10
|
|
@ -21,6 +21,8 @@ import (
|
|||||||
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
||||||
library.SkipUnlessIntegration(t)
|
library.SkipUnlessIntegration(t)
|
||||||
|
|
||||||
|
const defaultServingCertResourceName = "pinniped-api-tls-serving-certificate"
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
forceRotation func(context.Context, kubernetes.Interface, string) error
|
forceRotation func(context.Context, kubernetes.Interface, string) error
|
||||||
@ -36,7 +38,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
return kubeClient.
|
return kubeClient.
|
||||||
CoreV1().
|
CoreV1().
|
||||||
Secrets(namespace).
|
Secrets(namespace).
|
||||||
Delete(ctx, "api-serving-cert", metav1.DeleteOptions{})
|
Delete(ctx, defaultServingCertResourceName, metav1.DeleteOptions{})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -51,7 +53,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
secret, err := kubeClient.
|
secret, err := kubeClient.
|
||||||
CoreV1().
|
CoreV1().
|
||||||
Secrets(namespace).
|
Secrets(namespace).
|
||||||
Get(ctx, "api-serving-cert", metav1.GetOptions{})
|
Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,7 +85,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
const apiServiceName = "v1alpha1.login.pinniped.dev"
|
const apiServiceName = "v1alpha1.login.pinniped.dev"
|
||||||
|
|
||||||
// Get the initial auto-generated version of the Secret.
|
// Get the initial auto-generated version of the Secret.
|
||||||
secret, err := kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, "api-serving-cert", metav1.GetOptions{})
|
secret, err := kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
initialCACert := secret.Data["caCertificate"]
|
initialCACert := secret.Data["caCertificate"]
|
||||||
initialPrivateKey := secret.Data["tlsPrivateKey"]
|
initialPrivateKey := secret.Data["tlsPrivateKey"]
|
||||||
@ -102,7 +104,7 @@ func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
|
|||||||
|
|
||||||
// Expect that the Secret comes back right away with newly minted certs.
|
// Expect that the Secret comes back right away with newly minted certs.
|
||||||
secretIsRegenerated := func() bool {
|
secretIsRegenerated := func() bool {
|
||||||
secret, err = kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, "api-serving-cert", metav1.GetOptions{})
|
secret, err = kubeClient.CoreV1().Secrets(namespaceName).Get(ctx, defaultServingCertResourceName, metav1.GetOptions{})
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
assert.Eventually(t, secretIsRegenerated, 10*time.Second, 250*time.Millisecond)
|
assert.Eventually(t, secretIsRegenerated, 10*time.Second, 250*time.Millisecond)
|
||||||
|
@ -130,7 +130,7 @@ func runKubectlCLI(t *testing.T, kubeConfig, namespaceName, username string) str
|
|||||||
err = f.Close()
|
err = f.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
//nolint: gosec
|
//nolint: gosec // It's okay that we are passing f.Name() to an exec command here. It was created above.
|
||||||
output, err := exec.Command(
|
output, err := exec.Command(
|
||||||
"kubectl",
|
"kubectl",
|
||||||
"get",
|
"get",
|
||||||
|
Loading…
Reference in New Issue
Block a user