Rework "pinniped get kubeconfig" so that --concierge-mode can be used even when auto-discovering other parameters.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
parent
49ec16038c
commit
389cd3486b
@ -7,6 +7,8 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// conciergeMode represents the method by which we should connect to the Concierge on a cluster during login.
|
// conciergeMode represents the method by which we should connect to the Concierge on a cluster during login.
|
||||||
@ -25,7 +27,7 @@ func (c *conciergeMode) String() string {
|
|||||||
switch *c {
|
switch *c {
|
||||||
case modeImpersonationProxy:
|
case modeImpersonationProxy:
|
||||||
return "ImpersonationProxy"
|
return "ImpersonationProxy"
|
||||||
case modeTokenCredentialRequestAPI, modeUnknown:
|
case modeTokenCredentialRequestAPI:
|
||||||
return "TokenCredentialRequestAPI"
|
return "TokenCredentialRequestAPI"
|
||||||
default:
|
default:
|
||||||
return "TokenCredentialRequestAPI"
|
return "TokenCredentialRequestAPI"
|
||||||
@ -51,3 +53,15 @@ func (c *conciergeMode) Set(s string) error {
|
|||||||
func (c *conciergeMode) Type() string {
|
func (c *conciergeMode) Type() string {
|
||||||
return "mode"
|
return "mode"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchesFrontend returns true iff the flag matches the type of the provided frontend.
|
||||||
|
func (c *conciergeMode) MatchesFrontend(frontend *configv1alpha1.CredentialIssuerFrontend) bool {
|
||||||
|
switch *c {
|
||||||
|
case modeImpersonationProxy:
|
||||||
|
return frontend.Type == configv1alpha1.ImpersonationProxyFrontendType
|
||||||
|
case modeTokenCredentialRequestAPI:
|
||||||
|
return frontend.Type == configv1alpha1.TokenCredentialRequestAPIFrontendType
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,17 +7,25 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConciergeModeFlag(t *testing.T) {
|
func TestConciergeModeFlag(t *testing.T) {
|
||||||
var m conciergeMode
|
var m conciergeMode
|
||||||
require.Equal(t, "mode", m.Type())
|
require.Equal(t, "mode", m.Type())
|
||||||
require.Equal(t, modeUnknown, m)
|
require.Equal(t, modeUnknown, m)
|
||||||
|
require.NoError(t, m.Set(""))
|
||||||
|
require.Equal(t, modeUnknown, m)
|
||||||
require.EqualError(t, m.Set("foo"), `invalid mode "foo", valid modes are TokenCredentialRequestAPI and ImpersonationProxy`)
|
require.EqualError(t, m.Set("foo"), `invalid mode "foo", valid modes are TokenCredentialRequestAPI and ImpersonationProxy`)
|
||||||
|
require.True(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.TokenCredentialRequestAPIFrontendType}))
|
||||||
|
require.True(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.ImpersonationProxyFrontendType}))
|
||||||
|
|
||||||
require.NoError(t, m.Set("TokenCredentialRequestAPI"))
|
require.NoError(t, m.Set("TokenCredentialRequestAPI"))
|
||||||
require.Equal(t, modeTokenCredentialRequestAPI, m)
|
require.Equal(t, modeTokenCredentialRequestAPI, m)
|
||||||
require.Equal(t, "TokenCredentialRequestAPI", m.String())
|
require.Equal(t, "TokenCredentialRequestAPI", m.String())
|
||||||
|
require.True(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.TokenCredentialRequestAPIFrontendType}))
|
||||||
|
require.False(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.ImpersonationProxyFrontendType}))
|
||||||
|
|
||||||
require.NoError(t, m.Set("tokencredentialrequestapi"))
|
require.NoError(t, m.Set("tokencredentialrequestapi"))
|
||||||
require.Equal(t, modeTokenCredentialRequestAPI, m)
|
require.Equal(t, modeTokenCredentialRequestAPI, m)
|
||||||
@ -26,6 +34,8 @@ func TestConciergeModeFlag(t *testing.T) {
|
|||||||
require.NoError(t, m.Set("ImpersonationProxy"))
|
require.NoError(t, m.Set("ImpersonationProxy"))
|
||||||
require.Equal(t, modeImpersonationProxy, m)
|
require.Equal(t, modeImpersonationProxy, m)
|
||||||
require.Equal(t, "ImpersonationProxy", m.String())
|
require.Equal(t, "ImpersonationProxy", m.String())
|
||||||
|
require.False(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.TokenCredentialRequestAPIFrontendType}))
|
||||||
|
require.True(t, m.MatchesFrontend(&configv1alpha1.CredentialIssuerFrontend{Type: configv1alpha1.ImpersonationProxyFrontendType}))
|
||||||
|
|
||||||
require.NoError(t, m.Set("impersonationproxy"))
|
require.NoError(t, m.Set("impersonationproxy"))
|
||||||
require.Equal(t, modeImpersonationProxy, m)
|
require.Equal(t, modeImpersonationProxy, m)
|
||||||
|
@ -283,43 +283,56 @@ func runGetKubeconfig(ctx context.Context, out io.Writer, deps kubeconfigDeps, f
|
|||||||
}
|
}
|
||||||
|
|
||||||
func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authenticator metav1.Object, flags *getKubeconfigParams, v1Cluster *clientcmdapi.Cluster, oidcCABundle *string, execConfig *clientcmdapi.ExecConfig, log logr.Logger) error {
|
func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authenticator metav1.Object, flags *getKubeconfigParams, v1Cluster *clientcmdapi.Cluster, oidcCABundle *string, execConfig *clientcmdapi.ExecConfig, log logr.Logger) error {
|
||||||
var conciergeCABundleData []byte
|
|
||||||
|
|
||||||
// Autodiscover the --concierge-mode.
|
// Autodiscover the --concierge-mode.
|
||||||
if flags.concierge.mode == modeUnknown { //nolint:nestif
|
frontend, err := getConciergeFrontend(credentialIssuer, flags.concierge.mode)
|
||||||
strategyLoop:
|
if err != nil {
|
||||||
for _, strategy := range credentialIssuer.Status.Strategies {
|
return err
|
||||||
if strategy.Status != configv1alpha1.SuccessStrategyStatus || strategy.Frontend == nil {
|
}
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch strategy.Frontend.Type {
|
|
||||||
case configv1alpha1.TokenCredentialRequestAPIFrontendType:
|
|
||||||
log.Info("detected Concierge in TokenCredentialRequest API mode")
|
|
||||||
flags.concierge.mode = modeTokenCredentialRequestAPI
|
|
||||||
break strategyLoop
|
|
||||||
case configv1alpha1.ImpersonationProxyFrontendType:
|
|
||||||
|
|
||||||
flags.concierge.mode = modeImpersonationProxy
|
// Auto-set --concierge-mode if it wasn't explicitly set.
|
||||||
flags.concierge.endpoint = strategy.Frontend.ImpersonationProxyInfo.Endpoint
|
if flags.concierge.mode == modeUnknown {
|
||||||
var err error
|
switch frontend.Type {
|
||||||
conciergeCABundleData, err = base64.StdEncoding.DecodeString(strategy.Frontend.ImpersonationProxyInfo.CertificateAuthorityData)
|
case configv1alpha1.TokenCredentialRequestAPIFrontendType:
|
||||||
if err != nil {
|
log.Info("discovered Concierge operating in TokenCredentialRequest API mode")
|
||||||
return fmt.Errorf("autodiscovered Concierge CA bundle is invalid: %w", err)
|
flags.concierge.mode = modeTokenCredentialRequestAPI
|
||||||
}
|
case configv1alpha1.ImpersonationProxyFrontendType:
|
||||||
log.Info("detected Concierge in impersonation proxy mode", "endpoint", strategy.Frontend.ImpersonationProxyInfo.Endpoint)
|
log.Info("discovered Concierge operating in impersonation proxy mode")
|
||||||
break strategyLoop
|
flags.concierge.mode = modeImpersonationProxy
|
||||||
default:
|
}
|
||||||
// Skip any unknown frontend types.
|
}
|
||||||
}
|
|
||||||
}
|
// Auto-set --concierge-endpoint if it wasn't explicitly set.
|
||||||
if flags.concierge.mode == modeUnknown {
|
if flags.concierge.endpoint == "" {
|
||||||
// Fall back to deprecated field for backwards compatibility.
|
switch frontend.Type {
|
||||||
if credentialIssuer.Status.KubeConfigInfo != nil {
|
case configv1alpha1.TokenCredentialRequestAPIFrontendType:
|
||||||
flags.concierge.mode = modeTokenCredentialRequestAPI
|
flags.concierge.endpoint = v1Cluster.Server
|
||||||
} else {
|
case configv1alpha1.ImpersonationProxyFrontendType:
|
||||||
return fmt.Errorf("could not autodiscover --concierge-mode and none was provided")
|
flags.concierge.endpoint = frontend.ImpersonationProxyInfo.Endpoint
|
||||||
|
}
|
||||||
|
log.Info("discovered Concierge endpoint", "endpoint", flags.concierge.endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load specified --concierge-ca-bundle or autodiscover a value.
|
||||||
|
var conciergeCABundleData []byte
|
||||||
|
if flags.concierge.caBundlePath != "" {
|
||||||
|
caBundleString, err := loadCABundlePaths([]string{flags.concierge.caBundlePath})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not read --concierge-ca-bundle: %w", err)
|
||||||
|
}
|
||||||
|
conciergeCABundleData = []byte(caBundleString)
|
||||||
|
log.Info("loaded Concierge certificate authority bundle", "roots", countCACerts(conciergeCABundleData))
|
||||||
|
} else {
|
||||||
|
switch frontend.Type {
|
||||||
|
case configv1alpha1.TokenCredentialRequestAPIFrontendType:
|
||||||
|
conciergeCABundleData = v1Cluster.CertificateAuthorityData
|
||||||
|
case configv1alpha1.ImpersonationProxyFrontendType:
|
||||||
|
var err error
|
||||||
|
conciergeCABundleData, err = base64.StdEncoding.DecodeString(frontend.ImpersonationProxyInfo.CertificateAuthorityData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("autodiscovered Concierge CA bundle is invalid: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Info("discovered Concierge certificate authority bundle", "roots", countCACerts(conciergeCABundleData))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch auth := authenticator.(type) {
|
switch auth := authenticator.(type) {
|
||||||
@ -342,13 +355,13 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
|
|||||||
|
|
||||||
// If the --oidc-issuer flag was not set explicitly, default it to the spec.issuer field of the JWTAuthenticator.
|
// If the --oidc-issuer flag was not set explicitly, default it to the spec.issuer field of the JWTAuthenticator.
|
||||||
if flags.oidc.issuer == "" {
|
if flags.oidc.issuer == "" {
|
||||||
log.Info("detected OIDC issuer", "issuer", auth.Spec.Issuer)
|
log.Info("discovered OIDC issuer", "issuer", auth.Spec.Issuer)
|
||||||
flags.oidc.issuer = auth.Spec.Issuer
|
flags.oidc.issuer = auth.Spec.Issuer
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the --oidc-request-audience flag was not set explicitly, default it to the spec.audience field of the JWTAuthenticator.
|
// If the --oidc-request-audience flag was not set explicitly, default it to the spec.audience field of the JWTAuthenticator.
|
||||||
if flags.oidc.requestAudience == "" {
|
if flags.oidc.requestAudience == "" {
|
||||||
log.Info("detected OIDC audience", "audience", auth.Spec.Audience)
|
log.Info("discovered OIDC audience", "audience", auth.Spec.Audience)
|
||||||
flags.oidc.requestAudience = auth.Spec.Audience
|
flags.oidc.requestAudience = auth.Spec.Audience
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,29 +372,11 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", auth.Name, err)
|
return fmt.Errorf("tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator %s has invalid spec.tls.certificateAuthorityData: %w", auth.Name, err)
|
||||||
}
|
}
|
||||||
log.Info("detected OIDC CA bundle", "length", len(decoded))
|
log.Info("discovered OIDC CA bundle", "roots", countCACerts(decoded))
|
||||||
*oidcCABundle = string(decoded)
|
*oidcCABundle = string(decoded)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if flags.concierge.endpoint == "" {
|
|
||||||
log.Info("detected concierge endpoint", "endpoint", v1Cluster.Server)
|
|
||||||
flags.concierge.endpoint = v1Cluster.Server
|
|
||||||
}
|
|
||||||
|
|
||||||
if conciergeCABundleData == nil {
|
|
||||||
if flags.concierge.caBundlePath == "" {
|
|
||||||
log.Info("detected concierge CA bundle", "length", len(v1Cluster.CertificateAuthorityData))
|
|
||||||
conciergeCABundleData = v1Cluster.CertificateAuthorityData
|
|
||||||
} else {
|
|
||||||
caBundleString, err := loadCABundlePaths([]string{flags.concierge.caBundlePath})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not read --concierge-ca-bundle: %w", err)
|
|
||||||
}
|
|
||||||
conciergeCABundleData = []byte(caBundleString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append the flags to configure the Concierge credential exchange at runtime.
|
// Append the flags to configure the Concierge credential exchange at runtime.
|
||||||
execConfig.Args = append(execConfig.Args,
|
execConfig.Args = append(execConfig.Args,
|
||||||
"--enable-concierge",
|
"--enable-concierge",
|
||||||
@ -393,14 +388,53 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
|
|||||||
"--concierge-mode="+flags.concierge.mode.String(),
|
"--concierge-mode="+flags.concierge.mode.String(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// If we're in impersonation proxy mode, the main server endpoint for the kubeconfig also needs to point to the proxy
|
// Point kubectl at the concierge endpoint.
|
||||||
if flags.concierge.mode == modeImpersonationProxy {
|
v1Cluster.Server = flags.concierge.endpoint
|
||||||
log.Info("switching kubeconfig cluster to point at impersonation proxy endpoint", "endpoint", flags.concierge.endpoint)
|
v1Cluster.CertificateAuthorityData = conciergeCABundleData
|
||||||
v1Cluster.CertificateAuthorityData = conciergeCABundleData
|
return nil
|
||||||
v1Cluster.Server = flags.concierge.endpoint
|
}
|
||||||
|
|
||||||
|
func getConciergeFrontend(credentialIssuer *configv1alpha1.CredentialIssuer, mode conciergeMode) (*configv1alpha1.CredentialIssuerFrontend, error) {
|
||||||
|
for _, strategy := range credentialIssuer.Status.Strategies {
|
||||||
|
// Skip unhealthy strategies.
|
||||||
|
if strategy.Status != configv1alpha1.SuccessStrategyStatus {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backfill the .status.strategies[].frontend field from .status.kubeConfigInfo for backwards compatibility.
|
||||||
|
if strategy.Type == configv1alpha1.KubeClusterSigningCertificateStrategyType && strategy.Frontend == nil && credentialIssuer.Status.KubeConfigInfo != nil {
|
||||||
|
strategy = *strategy.DeepCopy()
|
||||||
|
strategy.Frontend = &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: credentialIssuer.Status.KubeConfigInfo.Server,
|
||||||
|
CertificateAuthorityData: credentialIssuer.Status.KubeConfigInfo.CertificateAuthorityData,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the strategy frontend is still nil, skip.
|
||||||
|
if strategy.Frontend == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip any unknown frontend types.
|
||||||
|
switch strategy.Frontend.Type {
|
||||||
|
case configv1alpha1.TokenCredentialRequestAPIFrontendType, configv1alpha1.ImpersonationProxyFrontendType:
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Skip strategies that don't match --concierge-mode.
|
||||||
|
if !mode.MatchesFrontend(strategy.Frontend) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return strategy.Frontend, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if mode == modeUnknown {
|
||||||
|
return nil, fmt.Errorf("could not autodiscover --concierge-mode")
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("could not find successful Concierge strategy matching --concierge-mode=%s", mode.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadCABundlePaths(paths []string) (string, error) {
|
func loadCABundlePaths(paths []string) (string, error) {
|
||||||
@ -614,3 +648,9 @@ func validateKubeconfig(ctx context.Context, flags getKubeconfigParams, kubeconf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func countCACerts(pemData []byte) int {
|
||||||
|
pool := x509.NewCertPool()
|
||||||
|
pool.AppendCertsFromPEM(pemData)
|
||||||
|
return len(pool.Subjects())
|
||||||
|
}
|
||||||
|
@ -36,8 +36,10 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
testOIDCCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
testOIDCCABundlePath := filepath.Join(tmpdir, "testca.pem")
|
||||||
require.NoError(t, ioutil.WriteFile(testOIDCCABundlePath, testOIDCCA.Bundle(), 0600))
|
require.NoError(t, ioutil.WriteFile(testOIDCCABundlePath, testOIDCCA.Bundle(), 0600))
|
||||||
|
|
||||||
|
testConciergeCA, err := certauthority.New(pkix.Name{CommonName: "Test Concierge CA"}, 1*time.Hour)
|
||||||
|
require.NoError(t, err)
|
||||||
testConciergeCABundlePath := filepath.Join(tmpdir, "testconciergeca.pem")
|
testConciergeCABundlePath := filepath.Join(tmpdir, "testconciergeca.pem")
|
||||||
require.NoError(t, ioutil.WriteFile(testConciergeCABundlePath, []byte("test-concierge-ca"), 0600))
|
require.NoError(t, ioutil.WriteFile(testConciergeCABundlePath, testConciergeCA.Bundle(), 0600))
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -324,7 +326,7 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantError: true,
|
wantError: true,
|
||||||
wantStderr: here.Doc(`
|
wantStderr: here.Doc(`
|
||||||
Error: could not autodiscover --concierge-mode and none was provided
|
Error: could not autodiscover --concierge-mode
|
||||||
`),
|
`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -375,6 +377,8 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in impersonation proxy mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://impersonation-endpoint"`,
|
||||||
},
|
},
|
||||||
wantError: true,
|
wantError: true,
|
||||||
wantStderr: here.Doc(`
|
wantStderr: here.Doc(`
|
||||||
@ -410,10 +414,10 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
`"level"=0 "msg"="detected Concierge in TokenCredentialRequest API mode"`,
|
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
|
||||||
`"level"=0 "msg"="detected concierge CA bundle" "length"=37`,
|
|
||||||
},
|
},
|
||||||
wantError: true,
|
wantError: true,
|
||||||
wantStderr: here.Doc(`
|
wantStderr: here.Doc(`
|
||||||
@ -433,11 +437,22 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
Server: "https://concierge-endpoint",
|
Server: "https://concierge-endpoint",
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
||||||
},
|
},
|
||||||
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
|
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||||
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
|
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||||
|
Message: "Successfully fetched key",
|
||||||
|
LastUpdateTime: metav1.Now(),
|
||||||
|
// Simulate a previous version of CredentialIssuer that's missing this Frontend field.
|
||||||
|
Frontend: nil,
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.JWTAuthenticator{
|
&conciergev1alpha1.JWTAuthenticator{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
||||||
Spec: conciergev1alpha1.JWTAuthenticatorSpec{
|
Spec: conciergev1alpha1.JWTAuthenticatorSpec{
|
||||||
|
Issuer: "https://test-issuer.example.com",
|
||||||
|
Audience: "some-test-audience",
|
||||||
TLS: &conciergev1alpha1.TLSSpec{
|
TLS: &conciergev1alpha1.TLSSpec{
|
||||||
CertificateAuthorityData: "invalid-base64",
|
CertificateAuthorityData: "invalid-base64",
|
||||||
},
|
},
|
||||||
@ -446,9 +461,12 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected OIDC issuer" "issuer"=""`,
|
`"level"=0 "msg"="discovered OIDC issuer" "issuer"="https://test-issuer.example.com"`,
|
||||||
`"level"=0 "msg"="detected OIDC audience" "audience"=""`,
|
`"level"=0 "msg"="discovered OIDC audience" "audience"="some-test-audience"`,
|
||||||
},
|
},
|
||||||
wantError: true,
|
wantError: true,
|
||||||
wantStderr: here.Doc(`
|
wantStderr: here.Doc(`
|
||||||
@ -469,10 +487,18 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.ImpersonationProxyStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.ListeningStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.ImpersonationProxyFrontendType,
|
||||||
|
ImpersonationProxyInfo: &configv1alpha1.ImpersonationProxyInfo{
|
||||||
|
Endpoint: "https://impersonation-proxy-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
||||||
@ -496,19 +522,28 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.ImpersonationProxyStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.ListeningStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.ImpersonationProxyFrontendType,
|
||||||
|
ImpersonationProxyInfo: &configv1alpha1.ImpersonationProxyInfo{
|
||||||
|
Endpoint: "https://impersonation-proxy-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in impersonation proxy mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://impersonation-proxy-endpoint.example.com"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=1`,
|
||||||
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
|
||||||
`"level"=0 "msg"="detected concierge CA bundle" "length"=37`,
|
|
||||||
},
|
},
|
||||||
wantError: true,
|
wantError: true,
|
||||||
wantStderr: here.Doc(`
|
wantStderr: here.Doc(`
|
||||||
@ -536,19 +571,28 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: "https://concierge-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
|
||||||
`"level"=0 "msg"="detected concierge CA bundle" "length"=37`,
|
|
||||||
},
|
},
|
||||||
wantStdout: here.Doc(`
|
wantStdout: here.Doc(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@ -597,19 +641,28 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: "https://concierge-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
|
||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered WebhookAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
|
||||||
`"level"=0 "msg"="detected concierge CA bundle" "length"=37`,
|
|
||||||
},
|
},
|
||||||
wantStdout: here.Doc(`
|
wantStdout: here.Doc(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@ -657,10 +710,18 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: "https://concierge-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.JWTAuthenticator{
|
&conciergev1alpha1.JWTAuthenticator{
|
||||||
@ -676,12 +737,13 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge operating in TokenCredentialRequest API mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
|
`"level"=0 "msg"="discovered OIDC issuer" "issuer"="https://example.com/issuer"`,
|
||||||
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
|
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||||
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
|
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||||
`"level"=0 "msg"="detected concierge endpoint" "endpoint"="https://fake-server-url-value"`,
|
|
||||||
`"level"=0 "msg"="detected concierge CA bundle" "length"=37`,
|
|
||||||
},
|
},
|
||||||
wantStdout: here.Docf(`
|
wantStdout: here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@ -731,7 +793,8 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
"--concierge-api-group-suffix", "tuna.io",
|
"--concierge-api-group-suffix", "tuna.io",
|
||||||
"--concierge-authenticator-type", "webhook",
|
"--concierge-authenticator-type", "webhook",
|
||||||
"--concierge-authenticator-name", "test-authenticator",
|
"--concierge-authenticator-name", "test-authenticator",
|
||||||
"--concierge-endpoint", "https://concierge-endpoint.example.com",
|
"--concierge-mode", "TokenCredentialRequestAPI",
|
||||||
|
"--concierge-endpoint", "https://explicit-concierge-endpoint.example.com",
|
||||||
"--concierge-ca-bundle", testConciergeCABundlePath,
|
"--concierge-ca-bundle", testConciergeCABundlePath,
|
||||||
"--oidc-issuer", "https://example.com/issuer",
|
"--oidc-issuer", "https://example.com/issuer",
|
||||||
"--oidc-skip-browser",
|
"--oidc-skip-browser",
|
||||||
@ -746,22 +809,33 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
KubeConfigInfo: &configv1alpha1.CredentialIssuerKubeConfigInfo{
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{{
|
||||||
Server: "https://concierge-endpoint",
|
Type: configv1alpha1.KubeClusterSigningCertificateStrategyType,
|
||||||
CertificateAuthorityData: "ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==",
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
},
|
Reason: configv1alpha1.FetchedKeyStrategyReason,
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: "https://concierge-endpoint.example.com",
|
||||||
|
CertificateAuthorityData: "dGVzdC10Y3ItYXBpLWNh",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.WebhookAuthenticator{
|
&conciergev1alpha1.WebhookAuthenticator{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
wantLogs: []string{
|
||||||
|
`"level"=0 "msg"="loaded Concierge certificate authority bundle" "roots"=1`,
|
||||||
|
},
|
||||||
wantStdout: here.Docf(`
|
wantStdout: here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
clusters:
|
clusters:
|
||||||
- cluster:
|
- cluster:
|
||||||
certificate-authority-data: ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ==
|
certificate-authority-data: %s
|
||||||
server: https://fake-server-url-value
|
server: https://explicit-concierge-endpoint.example.com
|
||||||
name: pinniped
|
name: pinniped
|
||||||
contexts:
|
contexts:
|
||||||
- context:
|
- context:
|
||||||
@ -783,8 +857,8 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
- --concierge-api-group-suffix=tuna.io
|
- --concierge-api-group-suffix=tuna.io
|
||||||
- --concierge-authenticator-name=test-authenticator
|
- --concierge-authenticator-name=test-authenticator
|
||||||
- --concierge-authenticator-type=webhook
|
- --concierge-authenticator-type=webhook
|
||||||
- --concierge-endpoint=https://concierge-endpoint.example.com
|
- --concierge-endpoint=https://explicit-concierge-endpoint.example.com
|
||||||
- --concierge-ca-bundle-data=dGVzdC1jb25jaWVyZ2UtY2E=
|
- --concierge-ca-bundle-data=%s
|
||||||
- --concierge-mode=TokenCredentialRequestAPI
|
- --concierge-mode=TokenCredentialRequestAPI
|
||||||
- --issuer=https://example.com/issuer
|
- --issuer=https://example.com/issuer
|
||||||
- --client-id=pinniped-cli
|
- --client-id=pinniped-cli
|
||||||
@ -798,22 +872,58 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
command: '.../path/to/pinniped'
|
command: '.../path/to/pinniped'
|
||||||
env: []
|
env: []
|
||||||
provideClusterInfo: true
|
provideClusterInfo: true
|
||||||
`, base64.StdEncoding.EncodeToString(testOIDCCA.Bundle())),
|
`,
|
||||||
|
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
base64.StdEncoding.EncodeToString(testOIDCCA.Bundle()),
|
||||||
|
),
|
||||||
wantAPIGroupSuffix: "tuna.io",
|
wantAPIGroupSuffix: "tuna.io",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "configure impersonation proxy with autodetected JWT authenticator",
|
name: "configure impersonation proxy with autodiscovered JWT authenticator",
|
||||||
args: []string{
|
args: []string{
|
||||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||||
"--concierge-ca-bundle", testConciergeCABundlePath,
|
|
||||||
"--concierge-endpoint", "https://impersonation-proxy-endpoint.test",
|
|
||||||
"--concierge-mode", "ImpersonationProxy",
|
"--concierge-mode", "ImpersonationProxy",
|
||||||
"--skip-validation",
|
"--skip-validation",
|
||||||
},
|
},
|
||||||
conciergeObjects: []runtime.Object{
|
conciergeObjects: []runtime.Object{
|
||||||
&configv1alpha1.CredentialIssuer{
|
&configv1alpha1.CredentialIssuer{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"},
|
||||||
Status: configv1alpha1.CredentialIssuerStatus{},
|
Status: configv1alpha1.CredentialIssuerStatus{
|
||||||
|
Strategies: []configv1alpha1.CredentialIssuerStrategy{
|
||||||
|
// This TokenCredentialRequestAPI strategy would normally be chosen, but
|
||||||
|
// --concierge-mode=ImpersonationProxy should force it to be skipped.
|
||||||
|
{
|
||||||
|
Type: "SomeType",
|
||||||
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
|
Reason: "SomeReason",
|
||||||
|
Message: "Some message",
|
||||||
|
LastUpdateTime: metav1.Now(),
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.TokenCredentialRequestAPIFrontendType,
|
||||||
|
TokenCredentialRequestAPIInfo: &configv1alpha1.TokenCredentialRequestAPIInfo{
|
||||||
|
Server: "https://token-credential-request-api-endpoint.test",
|
||||||
|
CertificateAuthorityData: "dGVzdC10Y3ItYXBpLWNh",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// The endpoint and CA from this impersonation proxy strategy should be autodiscovered.
|
||||||
|
{
|
||||||
|
Type: "SomeOtherType",
|
||||||
|
Status: configv1alpha1.SuccessStrategyStatus,
|
||||||
|
Reason: "SomeOtherReason",
|
||||||
|
Message: "Some other message",
|
||||||
|
LastUpdateTime: metav1.Now(),
|
||||||
|
Frontend: &configv1alpha1.CredentialIssuerFrontend{
|
||||||
|
Type: configv1alpha1.ImpersonationProxyFrontendType,
|
||||||
|
ImpersonationProxyInfo: &configv1alpha1.ImpersonationProxyInfo{
|
||||||
|
Endpoint: "https://impersonation-proxy-endpoint.test",
|
||||||
|
CertificateAuthorityData: base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&conciergev1alpha1.JWTAuthenticator{
|
&conciergev1alpha1.JWTAuthenticator{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"},
|
||||||
@ -828,17 +938,18 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://impersonation-proxy-endpoint.test"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=1`,
|
||||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
|
`"level"=0 "msg"="discovered OIDC issuer" "issuer"="https://example.com/issuer"`,
|
||||||
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
|
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||||
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
|
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||||
`"level"=0 "msg"="switching kubeconfig cluster to point at impersonation proxy endpoint" "endpoint"="https://impersonation-proxy-endpoint.test"`,
|
|
||||||
},
|
},
|
||||||
wantStdout: here.Docf(`
|
wantStdout: here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
clusters:
|
clusters:
|
||||||
- cluster:
|
- cluster:
|
||||||
certificate-authority-data: dGVzdC1jb25jaWVyZ2UtY2E=
|
certificate-authority-data: %s
|
||||||
server: https://impersonation-proxy-endpoint.test
|
server: https://impersonation-proxy-endpoint.test
|
||||||
name: pinniped
|
name: pinniped
|
||||||
contexts:
|
contexts:
|
||||||
@ -862,7 +973,7 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
- --concierge-authenticator-name=test-authenticator
|
- --concierge-authenticator-name=test-authenticator
|
||||||
- --concierge-authenticator-type=jwt
|
- --concierge-authenticator-type=jwt
|
||||||
- --concierge-endpoint=https://impersonation-proxy-endpoint.test
|
- --concierge-endpoint=https://impersonation-proxy-endpoint.test
|
||||||
- --concierge-ca-bundle-data=dGVzdC1jb25jaWVyZ2UtY2E=
|
- --concierge-ca-bundle-data=%s
|
||||||
- --concierge-mode=ImpersonationProxy
|
- --concierge-mode=ImpersonationProxy
|
||||||
- --issuer=https://example.com/issuer
|
- --issuer=https://example.com/issuer
|
||||||
- --client-id=pinniped-cli
|
- --client-id=pinniped-cli
|
||||||
@ -872,10 +983,14 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
command: '.../path/to/pinniped'
|
command: '.../path/to/pinniped'
|
||||||
env: []
|
env: []
|
||||||
provideClusterInfo: true
|
provideClusterInfo: true
|
||||||
`, base64.StdEncoding.EncodeToString(testOIDCCA.Bundle())),
|
`,
|
||||||
|
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
base64.StdEncoding.EncodeToString(testConciergeCA.Bundle()),
|
||||||
|
base64.StdEncoding.EncodeToString(testOIDCCA.Bundle()),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "autodetect impersonation proxy with autodetected JWT authenticator",
|
name: "autodetect impersonation proxy with autodiscovered JWT authenticator",
|
||||||
args: []string{
|
args: []string{
|
||||||
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
"--kubeconfig", "./testdata/kubeconfig.yaml",
|
||||||
"--skip-validation",
|
"--skip-validation",
|
||||||
@ -929,12 +1044,13 @@ func TestGetKubeconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantLogs: []string{
|
wantLogs: []string{
|
||||||
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
|
||||||
`"level"=0 "msg"="detected Concierge in impersonation proxy mode" "endpoint"="https://impersonation-proxy-endpoint.test"`,
|
`"level"=0 "msg"="discovered Concierge operating in impersonation proxy mode"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge endpoint" "endpoint"="https://impersonation-proxy-endpoint.test"`,
|
||||||
|
`"level"=0 "msg"="discovered Concierge certificate authority bundle" "roots"=0`,
|
||||||
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
|
||||||
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
|
`"level"=0 "msg"="discovered OIDC issuer" "issuer"="https://example.com/issuer"`,
|
||||||
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
|
`"level"=0 "msg"="discovered OIDC audience" "audience"="test-audience"`,
|
||||||
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
|
`"level"=0 "msg"="discovered OIDC CA bundle" "roots"=1`,
|
||||||
`"level"=0 "msg"="switching kubeconfig cluster to point at impersonation proxy endpoint" "endpoint"="https://impersonation-proxy-endpoint.test"`,
|
|
||||||
},
|
},
|
||||||
wantStdout: here.Docf(`
|
wantStdout: here.Docf(`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
|
Loading…
Reference in New Issue
Block a user