diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/config/config_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/config/config_test.go index 611b85e4dad..28603f261e0 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/config/config_test.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/config/config_test.go @@ -279,6 +279,91 @@ func TestEmbedClientCert(t *testing.T) { test.run(t) } +func TestExecPlugin(t *testing.T) { + fakeCertFile, _ := os.CreateTemp(os.TempDir(), "") + defer utiltesting.CloseAndRemove(t, fakeCertFile) + fakeData := []byte("fake-data") + err := os.WriteFile(fakeCertFile.Name(), fakeData, 0600) + if err != nil { + t.Errorf("unexpected error %v", err) + } + expectedConfig := newRedFederalCowHammerConfig() + authInfo := clientcmdapi.NewAuthInfo() + authInfo.Exec = &clientcmdapi.ExecConfig{ + Command: "example-client-go-exec-plugin", + Args: []string{"arg1", "arg2"}, + Env: []clientcmdapi.ExecEnvVar{ + { + Name: "FOO", + Value: "bar", + }, + }, + APIVersion: "client.authentication.k8s.io/v1", + ProvideClusterInfo: false, + InteractiveMode: "Never", + } + expectedConfig.AuthInfos["cred-exec-user"] = authInfo + + test := configCommandTest{ + args: []string{ + "set-credentials", + "cred-exec-user", + "--exec-api-version=client.authentication.k8s.io/v1", + "--exec-command=example-client-go-exec-plugin", + "--exec-arg=arg1,arg2", + "--exec-env=FOO=bar", + "--exec-interactive-mode=Never", + }, + startingConfig: newRedFederalCowHammerConfig(), + expectedConfig: expectedConfig, + } + + test.run(t) +} + +func TestExecPluginWithProveClusterInfo(t *testing.T) { + fakeCertFile, _ := os.CreateTemp(os.TempDir(), "") + defer utiltesting.CloseAndRemove(t, fakeCertFile) + fakeData := []byte("fake-data") + err := os.WriteFile(fakeCertFile.Name(), fakeData, 0600) + if err != nil { + t.Errorf("unexpected error %v", err) + } + expectedConfig := newRedFederalCowHammerConfig() + authInfo := clientcmdapi.NewAuthInfo() + authInfo.Exec = &clientcmdapi.ExecConfig{ + Command: "example-client-go-exec-plugin", + Args: []string{"arg1", "arg2"}, + Env: []clientcmdapi.ExecEnvVar{ + { + Name: "FOO", + Value: "bar", + }, + }, + APIVersion: "client.authentication.k8s.io/v1", + ProvideClusterInfo: true, + InteractiveMode: "Always", + } + expectedConfig.AuthInfos["cred-exec-user"] = authInfo + + test := configCommandTest{ + args: []string{ + "set-credentials", + "cred-exec-user", + "--exec-api-version=client.authentication.k8s.io/v1", + "--exec-command=example-client-go-exec-plugin", + "--exec-arg=arg1,arg2", + "--exec-env=FOO=bar", + "--exec-interactive-mode=Always", + "--exec-provide-cluster-info=true", + }, + startingConfig: newRedFederalCowHammerConfig(), + expectedConfig: expectedConfig, + } + + test.run(t) +} + func TestEmbedClientKey(t *testing.T) { fakeKeyFile, _ := os.CreateTemp(os.TempDir(), "") defer utiltesting.CloseAndRemove(t, fakeKeyFile) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/config/set_credentials.go b/staging/src/k8s.io/kubectl/pkg/cmd/config/set_credentials.go index 5bfd1186b5d..e982c518a9a 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/config/set_credentials.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/config/set_credentials.go @@ -48,21 +48,25 @@ type setCredentialsOptions struct { authProviderArgs map[string]string authProviderArgsToRemove []string - execCommand cliflag.StringFlag - execAPIVersion cliflag.StringFlag - execArgs []string - execEnv map[string]string - execEnvToRemove []string + execCommand cliflag.StringFlag + execAPIVersion cliflag.StringFlag + execInteractiveMode cliflag.StringFlag + execProvideClusterInfo bool + execArgs []string + execEnv map[string]string + execEnvToRemove []string } const ( flagAuthProvider = "auth-provider" flagAuthProviderArg = "auth-provider-arg" - flagExecCommand = "exec-command" - flagExecAPIVersion = "exec-api-version" - flagExecArg = "exec-arg" - flagExecEnv = "exec-env" + flagExecCommand = "exec-command" + flagExecAPIVersion = "exec-api-version" + flagExecArg = "exec-arg" + flagExecEnv = "exec-env" + flagExecInteractiveMode = "exec-interactive-mode" + flagExecProvideClusterInfo = "exec-provide-cluster-info" ) var ( @@ -105,6 +109,9 @@ var ( # Enable new exec auth plugin for the "cluster-admin" entry kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1 + # Enable new exec auth plugin for the "cluster-admin" entry with interactive mode + kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1 --exec-interactive-mode=Never + # Define new exec auth plugin arguments for the "cluster-admin" entry kubectl config set-credentials cluster-admin --exec-arg=arg1 --exec-arg=arg2 @@ -179,6 +186,8 @@ func newCmdConfigSetCredentials(out io.Writer, options *setCredentialsOptions) * cmd.Flags().StringSlice(flagAuthProviderArg, nil, "'key=value' arguments for the auth provider") cmd.Flags().Var(&options.execCommand, flagExecCommand, "Command for the exec credential plugin for the user entry in kubeconfig") cmd.Flags().Var(&options.execAPIVersion, flagExecAPIVersion, "API version of the exec credential plugin for the user entry in kubeconfig") + cmd.Flags().Var(&options.execInteractiveMode, flagExecInteractiveMode, "InteractiveMode of the exec credentials plugin for the user entry in kubeconfig") + cmd.Flags().BoolVar(&options.execProvideClusterInfo, flagExecProvideClusterInfo, options.execProvideClusterInfo, "ProvideClusterInfo of the exec credentials plugin for the user entry in kubeconfig") cmd.Flags().StringSlice(flagExecArg, nil, "New arguments for the exec credential plugin command for the user entry in kubeconfig") cmd.Flags().StringArray(flagExecEnv, nil, "'key=value' environment values for the exec credential plugin") f := cmd.Flags().VarPF(&options.embedCertData, clientcmd.FlagEmbedCerts, "", "Embed client cert/key for the user entry in kubeconfig") @@ -293,6 +302,8 @@ func (o *setCredentialsOptions) modifyAuthInfo(existingAuthInfo clientcmdapi.Aut // explicitly reset exec arguments modifiedAuthInfo.Exec.Args = nil } + + modifiedAuthInfo.Exec.ProvideClusterInfo = o.execProvideClusterInfo } // modify next values only if Exec exists, ignore these changes otherwise @@ -306,6 +317,10 @@ func (o *setCredentialsOptions) modifyAuthInfo(existingAuthInfo clientcmdapi.Aut modifiedAuthInfo.Exec.Args = o.execArgs } + if o.execInteractiveMode.Provided() { + modifiedAuthInfo.Exec.InteractiveMode = clientcmdapi.ExecInteractiveMode(o.execInteractiveMode.Value()) + } + // iterate over the existing exec env values and remove the specified if o.execEnvToRemove != nil { newExecEnv := []clientcmdapi.ExecEnvVar{} @@ -437,5 +452,14 @@ func (o setCredentialsOptions) validate() error { } } + if o.execInteractiveMode.Provided() { + interactiveMode := o.execInteractiveMode.Value() + if interactiveMode != string(clientcmdapi.IfAvailableExecInteractiveMode) && + interactiveMode != string(clientcmdapi.AlwaysExecInteractiveMode) && + interactiveMode != string(clientcmdapi.NeverExecInteractiveMode) { + return fmt.Errorf("invalid interactive mode type, can be only IfAvailable, Never, Always") + } + } + return nil }