Add diagnostic logging to "pinniped get kubeconfig".

These stderr logs should help clarify all the autodetection logic that's happening in a particular run.

Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
Matt Moyer 2021-03-05 15:52:17 -06:00
parent c4f6fd5b3c
commit 36bc679142
No known key found for this signature in database
GPG Key ID: EAE88AD172C5AE2D
2 changed files with 134 additions and 10 deletions

View File

@ -10,20 +10,22 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/coreos/go-oidc/v3/oidc" "github.com/coreos/go-oidc/v3/oidc"
"github.com/go-logr/logr"
"github.com/go-logr/stdr"
"github.com/spf13/cobra" "github.com/spf13/cobra"
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/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
_ "k8s.io/client-go/plugin/pkg/client/auth" // Adds handlers for various dynamic auth plugins in client-go
conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1" conciergev1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1" configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned" conciergeclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
@ -34,6 +36,7 @@ import (
type kubeconfigDeps struct { type kubeconfigDeps struct {
getPathToSelf func() (string, error) getPathToSelf func() (string, error)
getClientset func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error) getClientset func(clientConfig clientcmd.ClientConfig, apiGroupSuffix string) (conciergeclientset.Interface, error)
log logr.Logger
} }
func kubeconfigRealDeps() kubeconfigDeps { func kubeconfigRealDeps() kubeconfigDeps {
@ -53,6 +56,7 @@ func kubeconfigRealDeps() kubeconfigDeps {
} }
return client.PinnipedConcierge, nil return client.PinnipedConcierge, nil
}, },
log: stdr.New(log.New(os.Stderr, "", 0)),
} }
} }
@ -181,7 +185,7 @@ func runGetKubeconfig(out io.Writer, deps kubeconfigDeps, flags getKubeconfigPar
} }
if !flags.concierge.disabled { if !flags.concierge.disabled {
credentialIssuer, err := lookupCredentialIssuer(clientset, flags.concierge.credentialIssuer) credentialIssuer, err := lookupCredentialIssuer(clientset, flags.concierge.credentialIssuer, deps.log)
if err != nil { if err != nil {
return err return err
} }
@ -190,12 +194,13 @@ func runGetKubeconfig(out io.Writer, deps kubeconfigDeps, flags getKubeconfigPar
clientset, clientset,
flags.concierge.authenticatorType, flags.concierge.authenticatorType,
flags.concierge.authenticatorName, flags.concierge.authenticatorName,
deps.log,
) )
if err != nil { if err != nil {
return err return err
} }
if err := configureConcierge(credentialIssuer, authenticator, &flags, cluster, &oidcCABundle, &execConfig); err != nil { if err := configureConcierge(credentialIssuer, authenticator, &flags, cluster, &oidcCABundle, &execConfig, deps.log); err != nil {
return err return err
} }
} }
@ -246,7 +251,7 @@ func runGetKubeconfig(out io.Writer, deps kubeconfigDeps, flags getKubeconfigPar
return writeConfigAsYAML(out, newExecKubeconfig(cluster, &execConfig)) return writeConfigAsYAML(out, newExecKubeconfig(cluster, &execConfig))
} }
func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authenticator metav1.Object, flags *getKubeconfigParams, v1Cluster *clientcmdapi.Cluster, oidcCABundle *string, execConfig *clientcmdapi.ExecConfig) 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 var conciergeCABundleData []byte
// Autodiscover the --concierge-mode. // Autodiscover the --concierge-mode.
@ -258,9 +263,11 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
} }
switch strategy.Frontend.Type { switch strategy.Frontend.Type {
case configv1alpha1.TokenCredentialRequestAPIFrontendType: case configv1alpha1.TokenCredentialRequestAPIFrontendType:
log.Info("detected Concierge in TokenCredentialRequest API mode")
flags.concierge.mode = modeTokenCredentialRequestAPI flags.concierge.mode = modeTokenCredentialRequestAPI
break strategyLoop break strategyLoop
case configv1alpha1.ImpersonationProxyFrontendType: case configv1alpha1.ImpersonationProxyFrontendType:
flags.concierge.mode = modeImpersonationProxy flags.concierge.mode = modeImpersonationProxy
flags.concierge.endpoint = strategy.Frontend.ImpersonationProxyInfo.Endpoint flags.concierge.endpoint = strategy.Frontend.ImpersonationProxyInfo.Endpoint
var err error var err error
@ -268,6 +275,7 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
if err != nil { if err != nil {
return fmt.Errorf("autodiscovered Concierge CA bundle is invalid: %w", err) return fmt.Errorf("autodiscovered Concierge CA bundle is invalid: %w", err)
} }
log.Info("detected Concierge in impersonation proxy mode", "endpoint", strategy.Frontend.ImpersonationProxyInfo.Endpoint)
break strategyLoop break strategyLoop
default: default:
// Skip any unknown frontend types. // Skip any unknown frontend types.
@ -288,6 +296,7 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
// If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set // If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set
// them to point at the discovered WebhookAuthenticator. // them to point at the discovered WebhookAuthenticator.
if flags.concierge.authenticatorType == "" && flags.concierge.authenticatorName == "" { if flags.concierge.authenticatorType == "" && flags.concierge.authenticatorName == "" {
log.Info("discovered WebhookAuthenticator", "name", auth.Name)
flags.concierge.authenticatorType = "webhook" flags.concierge.authenticatorType = "webhook"
flags.concierge.authenticatorName = auth.Name flags.concierge.authenticatorName = auth.Name
} }
@ -295,17 +304,20 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
// If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set // If the --concierge-authenticator-type/--concierge-authenticator-name flags were not set explicitly, set
// them to point at the discovered JWTAuthenticator. // them to point at the discovered JWTAuthenticator.
if flags.concierge.authenticatorType == "" && flags.concierge.authenticatorName == "" { if flags.concierge.authenticatorType == "" && flags.concierge.authenticatorName == "" {
log.Info("discovered JWTAuthenticator", "name", auth.Name)
flags.concierge.authenticatorType = "jwt" flags.concierge.authenticatorType = "jwt"
flags.concierge.authenticatorName = auth.Name flags.concierge.authenticatorName = auth.Name
} }
// 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)
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)
flags.oidc.requestAudience = auth.Spec.Audience flags.oidc.requestAudience = auth.Spec.Audience
} }
@ -316,16 +328,19 @@ 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))
*oidcCABundle = string(decoded) *oidcCABundle = string(decoded)
} }
} }
if flags.concierge.endpoint == "" { if flags.concierge.endpoint == "" {
log.Info("detected concierge endpoint", "endpoint", v1Cluster.Server)
flags.concierge.endpoint = v1Cluster.Server flags.concierge.endpoint = v1Cluster.Server
} }
if conciergeCABundleData == nil { if conciergeCABundleData == nil {
if flags.concierge.caBundlePath == "" { if flags.concierge.caBundlePath == "" {
log.Info("detected concierge CA bundle", "length", len(v1Cluster.CertificateAuthorityData))
conciergeCABundleData = v1Cluster.CertificateAuthorityData conciergeCABundleData = v1Cluster.CertificateAuthorityData
} else { } else {
caBundleString, err := loadCABundlePaths([]string{flags.concierge.caBundlePath}) caBundleString, err := loadCABundlePaths([]string{flags.concierge.caBundlePath})
@ -349,6 +364,7 @@ func configureConcierge(credentialIssuer *configv1alpha1.CredentialIssuer, authe
// If we're in impersonation proxy mode, the main server endpoint for the kubeconfig also needs to point to the proxy // If we're in impersonation proxy mode, the main server endpoint for the kubeconfig also needs to point to the proxy
if flags.concierge.mode == modeImpersonationProxy { if flags.concierge.mode == modeImpersonationProxy {
log.Info("switching kubeconfig cluster to point at impersonation proxy endpoint", "endpoint", flags.concierge.endpoint)
v1Cluster.CertificateAuthorityData = conciergeCABundleData v1Cluster.CertificateAuthorityData = conciergeCABundleData
v1Cluster.Server = flags.concierge.endpoint v1Cluster.Server = flags.concierge.endpoint
} }
@ -383,7 +399,7 @@ func newExecKubeconfig(cluster *clientcmdapi.Cluster, execConfig *clientcmdapi.E
} }
} }
func lookupCredentialIssuer(clientset conciergeclientset.Interface, name string) (*configv1alpha1.CredentialIssuer, error) { func lookupCredentialIssuer(clientset conciergeclientset.Interface, name string, log logr.Logger) (*configv1alpha1.CredentialIssuer, error) {
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20) ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
defer cancelFunc() defer cancelFunc()
@ -403,10 +419,13 @@ func lookupCredentialIssuer(clientset conciergeclientset.Interface, name string)
if len(results.Items) > 1 { if len(results.Items) > 1 {
return nil, fmt.Errorf("multiple CredentialIssuers were found, so the --concierge-credential-issuer flag must be specified") return nil, fmt.Errorf("multiple CredentialIssuers were found, so the --concierge-credential-issuer flag must be specified")
} }
return &results.Items[0], nil
result := &results.Items[0]
log.Info("discovered CredentialIssuer", "name", result.Name)
return result, nil
} }
func lookupAuthenticator(clientset conciergeclientset.Interface, authType, authName string) (metav1.Object, error) { func lookupAuthenticator(clientset conciergeclientset.Interface, authType, authName string, log logr.Logger) (metav1.Object, error) {
ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20) ctx, cancelFunc := context.WithTimeout(context.Background(), time.Second*20)
defer cancelFunc() defer cancelFunc()
@ -444,6 +463,12 @@ func lookupAuthenticator(clientset conciergeclientset.Interface, authType, authN
return nil, fmt.Errorf("no authenticators were found") return nil, fmt.Errorf("no authenticators were found")
} }
if len(results) > 1 { if len(results) > 1 {
for _, jwtAuth := range jwtAuths.Items {
log.Info("found JWTAuthenticator", "name", jwtAuth.Name)
}
for _, webhook := range webhooks.Items {
log.Info("found WebhookAuthenticator", "name", webhook.Name)
}
return nil, fmt.Errorf("multiple authenticators were found, so the --concierge-authenticator-type/--concierge-authenticator-name flags must be specified") return nil, fmt.Errorf("multiple authenticators were found, so the --concierge-authenticator-type/--concierge-authenticator-name flags must be specified")
} }
return results[0], nil return results[0], nil

View File

@ -26,6 +26,7 @@ import (
"go.pinniped.dev/internal/certauthority" "go.pinniped.dev/internal/certauthority"
"go.pinniped.dev/internal/here" "go.pinniped.dev/internal/here"
"go.pinniped.dev/internal/testutil" "go.pinniped.dev/internal/testutil"
"go.pinniped.dev/internal/testutil/testlogger"
) )
func TestGetKubeconfig(t *testing.T) { func TestGetKubeconfig(t *testing.T) {
@ -46,6 +47,7 @@ func TestGetKubeconfig(t *testing.T) {
getClientsetErr error getClientsetErr error
conciergeObjects []runtime.Object conciergeObjects []runtime.Object
conciergeReactions []kubetesting.Reactor conciergeReactions []kubetesting.Reactor
wantLogs []string
wantError bool wantError bool
wantStdout string wantStdout string
wantStderr string wantStderr string
@ -171,6 +173,9 @@ func TestGetKubeconfig(t *testing.T) {
conciergeObjects: []runtime.Object{ conciergeObjects: []runtime.Object{
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: webhookauthenticators.authentication.concierge.pinniped.dev "test-authenticator" not found Error: webhookauthenticators.authentication.concierge.pinniped.dev "test-authenticator" not found
@ -186,6 +191,9 @@ func TestGetKubeconfig(t *testing.T) {
conciergeObjects: []runtime.Object{ conciergeObjects: []runtime.Object{
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: jwtauthenticators.authentication.concierge.pinniped.dev "test-authenticator" not found Error: jwtauthenticators.authentication.concierge.pinniped.dev "test-authenticator" not found
@ -201,6 +209,9 @@ func TestGetKubeconfig(t *testing.T) {
conciergeObjects: []runtime.Object{ conciergeObjects: []runtime.Object{
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: invalid authenticator type "invalid", supported values are "webhook" and "jwt" Error: invalid authenticator type "invalid", supported values are "webhook" and "jwt"
@ -214,6 +225,9 @@ func TestGetKubeconfig(t *testing.T) {
conciergeObjects: []runtime.Object{ conciergeObjects: []runtime.Object{
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
conciergeReactions: []kubetesting.Reactor{ conciergeReactions: []kubetesting.Reactor{
&kubetesting.SimpleReactor{ &kubetesting.SimpleReactor{
Verb: "*", Verb: "*",
@ -245,6 +259,9 @@ func TestGetKubeconfig(t *testing.T) {
}, },
}, },
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: failed to list WebhookAuthenticator objects for autodiscovery: some list error Error: failed to list WebhookAuthenticator objects for autodiscovery: some list error
@ -258,6 +275,9 @@ func TestGetKubeconfig(t *testing.T) {
conciergeObjects: []runtime.Object{ conciergeObjects: []runtime.Object{
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: no authenticators were found Error: no authenticators were found
@ -275,6 +295,13 @@ func TestGetKubeconfig(t *testing.T) {
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator-3"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator-3"}},
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator-4"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator-4"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"level"=0 "msg"="found JWTAuthenticator" "name"="test-authenticator-1"`,
`"level"=0 "msg"="found JWTAuthenticator" "name"="test-authenticator-2"`,
`"level"=0 "msg"="found WebhookAuthenticator" "name"="test-authenticator-3"`,
`"level"=0 "msg"="found WebhookAuthenticator" "name"="test-authenticator-4"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: multiple authenticators were found, so the --concierge-authenticator-type/--concierge-authenticator-name flags must be specified Error: multiple authenticators were found, so the --concierge-authenticator-type/--concierge-authenticator-name flags must be specified
@ -289,6 +316,9 @@ func TestGetKubeconfig(t *testing.T) {
&configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}}, &configv1alpha1.CredentialIssuer{ObjectMeta: metav1.ObjectMeta{Name: "test-credential-issuer"}},
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
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 and none was provided
@ -340,6 +370,9 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: autodiscovered Concierge CA bundle is invalid: illegal base64 data at input byte 7 Error: autodiscovered Concierge CA bundle is invalid: illegal base64 data at input byte 7
@ -372,6 +405,13 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"level"=0 "msg"="detected Concierge in TokenCredentialRequest API mode"`,
`"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(`
Error: could not autodiscover --oidc-issuer and none was provided Error: could not autodiscover --oidc-issuer and none was provided
@ -401,6 +441,12 @@ func TestGetKubeconfig(t *testing.T) {
}, },
}, },
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
`"level"=0 "msg"="detected OIDC issuer" "issuer"=""`,
`"level"=0 "msg"="detected OIDC audience" "audience"=""`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator has invalid spec.tls.certificateAuthorityData: illegal base64 data at input byte 7 Error: tried to autodiscover --oidc-ca-bundle, but JWTAuthenticator test-authenticator has invalid spec.tls.certificateAuthorityData: illegal base64 data at input byte 7
@ -428,6 +474,9 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
},
wantError: true, wantError: true,
wantStderr: here.Doc(` wantStderr: here.Doc(`
Error: could not read --concierge-ca-bundle: open ./does/not/exist: no such file or directory Error: could not read --concierge-ca-bundle: open ./does/not/exist: no such file or directory
@ -452,6 +501,12 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"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(`
Error: only one of --static-token and --static-token-env can be specified Error: only one of --static-token and --static-token-env can be specified
@ -485,6 +540,12 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"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
clusters: clusters:
@ -539,6 +600,12 @@ func TestGetKubeconfig(t *testing.T) {
}, },
&conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}}, &conciergev1alpha1.WebhookAuthenticator{ObjectMeta: metav1.ObjectMeta{Name: "test-authenticator"}},
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"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
clusters: clusters:
@ -601,6 +668,15 @@ func TestGetKubeconfig(t *testing.T) {
}, },
}, },
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
`"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
clusters: clusters:
@ -645,9 +721,12 @@ func TestGetKubeconfig(t *testing.T) {
name: "autodetect nothing, set a bunch of options", name: "autodetect nothing, set a bunch of options",
args: []string{ args: []string{
"--kubeconfig", "./testdata/kubeconfig.yaml", "--kubeconfig", "./testdata/kubeconfig.yaml",
"--concierge-credential-issuer", "test-credential-issuer",
"--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-ca-bundle", testConciergeCABundlePath,
"--oidc-issuer", "https://example.com/issuer", "--oidc-issuer", "https://example.com/issuer",
"--oidc-skip-browser", "--oidc-skip-browser",
"--oidc-listen-port", "1234", "--oidc-listen-port", "1234",
@ -697,8 +776,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://fake-server-url-value - --concierge-endpoint=https://concierge-endpoint.example.com
- --concierge-ca-bundle-data=ZmFrZS1jZXJ0aWZpY2F0ZS1hdXRob3JpdHktZGF0YS12YWx1ZQ== - --concierge-ca-bundle-data=dGVzdC1jb25jaWVyZ2UtY2E=
- --concierge-mode=TokenCredentialRequestAPI - --concierge-mode=TokenCredentialRequestAPI
- --issuer=https://example.com/issuer - --issuer=https://example.com/issuer
- --client-id=pinniped-cli - --client-id=pinniped-cli
@ -739,6 +818,14 @@ func TestGetKubeconfig(t *testing.T) {
}, },
}, },
}, },
wantLogs: []string{
`"level"=0 "msg"="discovered CredentialIssuer" "name"="test-credential-issuer"`,
`"level"=0 "msg"="discovered JWTAuthenticator" "name"="test-authenticator"`,
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
`"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:
@ -831,6 +918,15 @@ func TestGetKubeconfig(t *testing.T) {
}, },
}, },
}, },
wantLogs: []string{
`"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 JWTAuthenticator" "name"="test-authenticator"`,
`"level"=0 "msg"="detected OIDC issuer" "issuer"="https://example.com/issuer"`,
`"level"=0 "msg"="detected OIDC audience" "audience"="test-audience"`,
`"level"=0 "msg"="detected OIDC CA bundle" "length"=587`,
`"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:
@ -875,6 +971,7 @@ func TestGetKubeconfig(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
tt := tt tt := tt
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
testLog := testlogger.New(t)
cmd := kubeconfigCommand(kubeconfigDeps{ cmd := kubeconfigCommand(kubeconfigDeps{
getPathToSelf: func() (string, error) { getPathToSelf: func() (string, error) {
if tt.getPathToSelfErr != nil { if tt.getPathToSelfErr != nil {
@ -897,6 +994,7 @@ func TestGetKubeconfig(t *testing.T) {
} }
return fake, nil return fake, nil
}, },
log: testLog,
}) })
require.NotNil(t, cmd) require.NotNil(t, cmd)
@ -910,6 +1008,7 @@ func TestGetKubeconfig(t *testing.T) {
} else { } else {
require.NoError(t, err) require.NoError(t, err)
} }
testLog.Expect(tt.wantLogs)
require.Equal(t, tt.wantStdout, stdout.String(), "unexpected stdout") require.Equal(t, tt.wantStdout, stdout.String(), "unexpected stdout")
require.Equal(t, tt.wantStderr, stderr.String(), "unexpected stderr") require.Equal(t, tt.wantStderr, stderr.String(), "unexpected stderr")
}) })