Skip to content

Commit

Permalink
add --azure-config-dir in convert-kubeconfig subcommand (#263)
Browse files Browse the repository at this point in the history
  • Loading branch information
weinong authored Apr 26, 2023
1 parent b710de8 commit 9db7a7c
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 50 deletions.
7 changes: 7 additions & 0 deletions pkg/converter/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
argFederatedTokenFile = "--federated-token-file"
argTokenCacheDir = "--token-cache-dir"

flagAzureConfigDir = "azure-config-dir"
flagClientID = "client-id"
flagContext = "context"
flagServerID = "server-id"
Expand All @@ -53,6 +54,8 @@ const (
execName = "kubelogin"
getTokenCommand = "get-token"
execAPIVersion = "client.authentication.k8s.io/v1beta1"

azureConfigDir = "AZURE_CONFIG_DIR"
)

func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientIDVal, argEnvironmentVal, argTenantIDVal, argTokenCacheDirVal string, argIsLegacyConfigModeVal bool) {
Expand Down Expand Up @@ -193,6 +196,10 @@ func Convert(o Options, pathOptions *clientcmd.PathOptions) error {
switch o.TokenOptions.LoginMethod {
case token.AzureCLILogin:

if o.azureConfigDir != "" {
exec.Env = append(exec.Env, api.ExecEnvVar{Name: azureConfigDir, Value: o.azureConfigDir})
}

// when convert to azurecli login, tenantID from the input kubeconfig will be disregarded and
// will have to come from explicit flag `--tenant-id`.
// this is because azure cli logged in using MSI does not allow specifying tenant ID
Expand Down
46 changes: 40 additions & 6 deletions pkg/converter/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func TestConvert(t *testing.T) {
authorityHost = "https://login.microsoftonline.com/"
federatedTokenFile = "/tmp/file"
tokenCacheDir = "/tmp/token_dir"
azureCLIDir = "/tmp/foo"
)
testData := []struct {
name string
Expand All @@ -40,6 +41,7 @@ func TestConvert(t *testing.T) {
execArgItems []string
command string
expectedError string
expectedEnv []clientcmdapi.ExecEnvVar
}{
{
name: "non azure kubeconfig",
Expand Down Expand Up @@ -1078,6 +1080,32 @@ func TestConvert(t *testing.T) {
},
expectedError: "no context exists with the name: \"badContext\"",
},
{
name: "with --azure-config-dir specified, exec.Env should be set accordingly",
authProviderConfig: map[string]string{
cfgEnvironment: envName,
cfgApiserverID: serverID,
cfgClientID: clientID,
cfgTenantID: tenantID,
cfgConfigMode: "0",
},
overrideFlags: map[string]string{
flagLoginMethod: token.AzureCLILogin,
flagContext: clusterName1,
flagAzureConfigDir: azureCLIDir,
},
expectedArgs: []string{
getTokenCommand,
argServerID, serverID,
argLoginMethod, token.AzureCLILogin,
},
expectedEnv: []clientcmdapi.ExecEnvVar{
{
Name: azureConfigDir,
Value: azureCLIDir,
},
},
},
}
rootTmpDir, err := os.MkdirTemp("", "kubelogin-test")
if err != nil {
Expand Down Expand Up @@ -1134,13 +1162,13 @@ func TestConvert(t *testing.T) {
if o.context != "" {
// when --context is specified, convert-kubeconfig will convert only the targeted context
// hence, we expect the second auth info not to change
validate(t, clusterName1, config.AuthInfos[clusterName1], data.authProviderConfig, data.expectedArgs)
validate(t, clusterName1, config.AuthInfos[clusterName1], data.authProviderConfig, data.expectedArgs, data.expectedEnv)
validateAuthInfoThatShouldNotChange(t, clusterName2, config.AuthInfos[clusterName2], data.authProviderConfig)
} else {
// when --context is not specified, convert-kubeconfig will convert every auth info in the kubeconfig
// hence, we expect the second auth info to be converted in the same way as the first one
validate(t, clusterName1, config.AuthInfos[clusterName1], data.authProviderConfig, data.expectedArgs)
validate(t, clusterName2, config.AuthInfos[clusterName2], data.authProviderConfig, data.expectedArgs)
validate(t, clusterName1, config.AuthInfos[clusterName1], data.authProviderConfig, data.expectedArgs, data.expectedEnv)
validate(t, clusterName2, config.AuthInfos[clusterName2], data.authProviderConfig, data.expectedArgs, data.expectedEnv)
}
})
}
Expand Down Expand Up @@ -1191,6 +1219,7 @@ func validate(
authInfo *clientcmdapi.AuthInfo,
authProviderConfig map[string]string,
expectedArgs []string,
expectedEnv []clientcmdapi.ExecEnvVar,
) {
if expectedArgs == nil {
if authInfo.AuthProvider == nil {
Expand Down Expand Up @@ -1218,9 +1247,6 @@ func validate(
t.Fatalf("[context:%s]: expected exec command: %s, actual: %s", clusterName, execAPIVersion, exec.APIVersion)
}

if len(exec.Env) > 0 {
t.Fatalf("[context:%s]: expected 0 environment variable. actual: %d", clusterName, len(exec.Env))
}
if exec.Args[0] != getTokenCommand {
t.Fatalf("[context:%s]: expected %s as first argument. actual: %s", clusterName, getTokenCommand, exec.Args[0])
}
Expand All @@ -1232,6 +1258,14 @@ func validate(
t.Fatalf("[context:%s]: expected exec arg: %s not found in %v", clusterName, v, exec.Args)
}
}
if len(expectedEnv) != len(exec.Env) {
t.Fatalf("[context:%s]: expected Env has %d entries, got %d", clusterName, len(expectedEnv), len(exec.Env))
}
for i, v := range expectedEnv {
if exec.Env[i] != v {
t.Fatalf("[context:%s]: for exec.Env, expected %q at index %d, got %q", clusterName, v, i, exec.Env[i])
}
}
}

func validateAuthInfoThatShouldNotChange(
Expand Down
4 changes: 3 additions & 1 deletion pkg/converter/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ type Options struct {
configFlags genericclioptions.RESTClientGetter
TokenOptions token.Options
// context is the kubeconfig context name
context string
context string
azureConfigDir string
}

func stringptr(str string) *string { return &str }
Expand All @@ -29,6 +30,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
cf.AddFlags(fs)
}
fs.StringVar(&o.context, flagContext, "", "The name of the kubeconfig context to use")
fs.StringVar(&o.azureConfigDir, flagAzureConfigDir, "", "Azure CLI config path")
o.TokenOptions.AddFlags(fs)
}

Expand Down
24 changes: 1 addition & 23 deletions pkg/token/execCredentialPlugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ type execCredentialPlugin struct {

func New(o *Options) (ExecCredentialPlugin, error) {

logginOptionsObject := marshalOptionsForLogging(o)

klog.V(10).Info(logginOptionsObject)
klog.V(10).Info(o.ToString())
provider, err := newTokenProvider(o)
if err != nil {
return nil, err
Expand All @@ -51,26 +49,6 @@ func New(o *Options) (ExecCredentialPlugin, error) {
}, nil
}

func marshalOptionsForLogging(o *Options) KlogsLoggingPurposeOptions {
logginOptionsObject := KlogsLoggingPurposeOptions{
LoginMethod: o.LoginMethod,
ClientID: o.ClientID,
ClientCert: o.ClientCert,
Username: o.Username,
ServerID: o.ServerID,
TenantID: o.TenantID,
Environment: o.Environment,
IsLegacy: o.IsLegacy,
TokenCacheDir: o.TokenCacheDir,
tokenCacheFile: o.tokenCacheFile,
IdentityResourceID: o.IdentityResourceID,
FederatedTokenFile: o.FederatedTokenFile,
AuthorityHost: o.AuthorityHost,
UseAzureRMTerraformEnv: o.UseAzureRMTerraformEnv,
}
return logginOptionsObject
}

func (p *execCredentialPlugin) Do() error {
var (
token adal.Token
Expand Down
26 changes: 6 additions & 20 deletions pkg/token/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,6 @@ import (
"k8s.io/client-go/util/homedir"
)

type KlogsLoggingPurposeOptions struct {
LoginMethod string
ClientID string
ClientCert string
Username string
ServerID string
TenantID string
Environment string
IsLegacy bool
TokenCacheDir string
tokenCacheFile string
IdentityResourceID string
FederatedTokenFile string
AuthorityHost string
UseAzureRMTerraformEnv bool
}

type Options struct {
LoginMethod string
ClientID string
Expand Down Expand Up @@ -229,8 +212,9 @@ func (o *Options) UpdateFromEnv() {
}
}

func (o *Options) String() string {
return fmt.Sprintf("Login Method: %s, Environment: %s, TenantID: %s, ServerID: %s, ClientID: %s, IsLegacy: %t, msiResourceID: %s, tokenCacheDir: %s, tokenCacheFile: %s",
func (o *Options) ToString() string {
azureConfigDir := os.Getenv("AZURE_CONFIG_DIR")
return fmt.Sprintf("Login Method: %s, Environment: %s, TenantID: %s, ServerID: %s, ClientID: %s, IsLegacy: %t, msiResourceID: %s, tokenCacheDir: %s, tokenCacheFile: %s, AZURE_CONFIG_DIR: %s",
o.LoginMethod,
o.Environment,
o.TenantID,
Expand All @@ -239,7 +223,9 @@ func (o *Options) String() string {
o.IsLegacy,
o.IdentityResourceID,
o.TokenCacheDir,
o.tokenCacheFile)
o.tokenCacheFile,
azureConfigDir,
)
}

func getCacheFileName(o *Options) string {
Expand Down

0 comments on commit 9db7a7c

Please sign in to comment.