Skip to content

Commit

Permalink
add support of the rest of login methods to exec input (#103)
Browse files Browse the repository at this point in the history
* add support of the rest of login methods to exec input, fixes #98
  • Loading branch information
weinong authored Jul 15, 2022
1 parent 3e4a78e commit 820e730
Show file tree
Hide file tree
Showing 2 changed files with 869 additions and 187 deletions.
294 changes: 189 additions & 105 deletions pkg/converter/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,44 +17,50 @@ const (
cfgEnvironment = "environment"
cfgConfigMode = "config-mode"

argClientID = "--client-id"
argServerID = "--server-id"
argTenantID = "--tenant-id"
argEnvironment = "--environment"
argClientSecret = "--client-secret"
argClientCert = "--client-certificate"
argIsLegacy = "--legacy"
argUsername = "--username"
argPassword = "--password"
argLoginMethod = "--login"

flagClientID = "client-id"
flagServerID = "server-id"
flagTenantID = "tenant-id"
flagEnvironment = "environment"
flagClientSecret = "client-secret"
flagClientCert = "client-certificate"
flagIsLegacy = "legacy"
flagUsername = "username"
flagPassword = "password"
flagLoginMethod = "login"
argClientID = "--client-id"
argServerID = "--server-id"
argTenantID = "--tenant-id"
argEnvironment = "--environment"
argClientSecret = "--client-secret"
argClientCert = "--client-certificate"
argIsLegacy = "--legacy"
argUsername = "--username"
argPassword = "--password"
argLoginMethod = "--login"
argIdentityResourceID = "--identity-resource-id"
argAuthorityHost = "--authority-host"
argFederatedTokenFile = "--federated-token-file"

flagClientID = "client-id"
flagServerID = "server-id"
flagTenantID = "tenant-id"
flagEnvironment = "environment"
flagClientSecret = "client-secret"
flagClientCert = "client-certificate"
flagIsLegacy = "legacy"
flagUsername = "username"
flagPassword = "password"
flagLoginMethod = "login"
flagIdentityResourceID = "identity-resource-id"
flagAuthorityHost = "authority-host"
flagFederatedTokenFile = "federated-token-file"

execName = "kubelogin"
getTokenCommand = "get-token"
execAPIVersion = "client.authentication.k8s.io/v1beta1"
)

func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientIDVal, argEnvironmentVal, argTenantIDVal, cfgConfigModeVal string) {
func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientIDVal, argEnvironmentVal, argTenantIDVal string, argIsLegacyConfigModeVal bool) {
if authInfo == nil {
return
}
authProviderBool := authInfo.AuthProvider != nil

isLegacyAuthProvider := isLegacyAzureAuth(authInfo)

if o.isSet(flagEnvironment) {
argEnvironmentVal = o.TokenOptions.Environment
} else if authProviderBool {
x, ok := authInfo.AuthProvider.Config[cfgEnvironment]
if ok {
} else if isLegacyAuthProvider {
if x, ok := authInfo.AuthProvider.Config[cfgEnvironment]; ok {
argEnvironmentVal = x
}
} else {
Expand All @@ -63,9 +69,8 @@ func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientI

if o.isSet(flagTenantID) {
argTenantIDVal = o.TokenOptions.TenantID
} else if authProviderBool {
x, ok := authInfo.AuthProvider.Config[cfgTenantID]
if ok {
} else if isLegacyAuthProvider {
if x, ok := authInfo.AuthProvider.Config[cfgTenantID]; ok {
argTenantIDVal = x
}
} else {
Expand All @@ -74,9 +79,8 @@ func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientI

if o.isSet(flagClientID) {
argClientIDVal = o.TokenOptions.ClientID
} else if authProviderBool {
x, ok := authInfo.AuthProvider.Config[cfgClientID]
if ok {
} else if isLegacyAuthProvider {
if x, ok := authInfo.AuthProvider.Config[cfgClientID]; ok {
argClientIDVal = x
}
} else {
Expand All @@ -85,29 +89,30 @@ func getArgValues(o Options, authInfo *api.AuthInfo) (argServerIDVal, argClientI

if o.isSet(flagServerID) {
argServerIDVal = o.TokenOptions.ServerID
} else if authProviderBool {
// .. is special, we look for cfgApiserverID
x, ok := authInfo.AuthProvider.Config[cfgApiserverID]
if ok {
} else if isLegacyAuthProvider {
if x, ok := authInfo.AuthProvider.Config[cfgApiserverID]; ok {
argServerIDVal = x
}
} else {
argServerIDVal = getExecArg(authInfo, argServerID)
}

// cfgConfigMode available only in authInfo.AuthProvider.Config,
// although the same precedence would work here as well.
if authProviderBool {
x, ok := authInfo.AuthProvider.Config[cfgConfigMode]
if ok {
cfgConfigModeVal = x
if o.isSet(flagIsLegacy) && o.TokenOptions.IsLegacy {
argIsLegacyConfigModeVal = true
} else if isLegacyAuthProvider {
if x := authInfo.AuthProvider.Config[cfgConfigMode]; x == "" || x == "0" {
argIsLegacyConfigModeVal = true
}
} else {
if found := getExecBoolArg(authInfo, argIsLegacy); found {
argIsLegacyConfigModeVal = true
}
}

return
}

func isLegacyAADAuth(authInfoPtr *api.AuthInfo) (ok bool) {
func isLegacyAzureAuth(authInfoPtr *api.AuthInfo) (ok bool) {
if authInfoPtr == nil {
return
}
Expand All @@ -134,18 +139,13 @@ func Convert(o Options) error {
return fmt.Errorf("unable to load kubeconfig: %s", err)
}

// MSI, AzureCLI, and WorkloadIdentity login bypass most login fields, so we'll check for them and exclude them
isMSI := o.TokenOptions.LoginMethod == token.MSILogin
isAzureCLI := o.TokenOptions.LoginMethod == token.AzureCLILogin
isWorkloadIdentity := o.TokenOptions.LoginMethod == token.WorkloadIdentityLogin
isAlternativeLogin := isMSI || isAzureCLI || isWorkloadIdentity
for _, authInfo := range config.AuthInfos {

// is it legacy aad auth or is it exec using kubelogin?
if !isExecUsingkubelogin(authInfo) && !isLegacyAADAuth(authInfo) {
if !isExecUsingkubelogin(authInfo) && !isLegacyAzureAuth(authInfo) {
continue
}
argServerIDVal, argClientIDVal, argEnvironmentVal, argTenantIDVal, cfgConfigModeVal := getArgValues(o, authInfo)
argServerIDVal, argClientIDVal, argEnvironmentVal, argTenantIDVal, isLegacyConfigMode := getArgValues(o, authInfo)
exec := &api.ExecConfig{
Command: execName,
Args: []string{
Expand All @@ -154,84 +154,150 @@ func Convert(o Options) error {
APIVersion: execAPIVersion,
}

if isExecUsingkubelogin(authInfo) {
if argServerIDVal == "" {
return fmt.Errorf("Err: Invalid arg %v", argServerID)
exec.Args = append(exec.Args, argLoginMethod)
exec.Args = append(exec.Args, o.TokenOptions.LoginMethod)

// all login methods require --server-id specified
if argServerIDVal == "" {
return fmt.Errorf("%s is required", argServerID)
}
exec.Args = append(exec.Args, argServerID)
exec.Args = append(exec.Args, argServerIDVal)

switch o.TokenOptions.LoginMethod {
case token.AzureCLILogin:

case token.DeviceCodeLogin:

if argClientIDVal == "" {
return fmt.Errorf("%s is required", argClientID)
}
switch o.TokenOptions.LoginMethod {
case token.AzureCLILogin:
exec.Args = append(exec.Args, argServerID)
exec.Args = append(exec.Args, argServerIDVal)
exec.Args = append(exec.Args, argLoginMethod)
exec.Args = append(exec.Args, o.TokenOptions.LoginMethod)
case token.DeviceCodeLogin:
exec.Args = append(exec.Args, argServerID)
exec.Args = append(exec.Args, argServerIDVal)
exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, argClientIDVal)
exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, argTenantIDVal)
exec.Args = append(exec.Args, argLoginMethod)
exec.Args = append(exec.Args, o.TokenOptions.LoginMethod)
default:
return fmt.Errorf("%q is not supported yet", o.TokenOptions.LoginMethod)

exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, argClientIDVal)

if argTenantIDVal == "" {
return fmt.Errorf("%s is required", argTenantID)
}
} else {
if !isAlternativeLogin && o.isSet(flagEnvironment) {
exec.Args = append(exec.Args, argEnvironment)
exec.Args = append(exec.Args, o.TokenOptions.Environment)
} else if !isAlternativeLogin && argEnvironmentVal != "" {

exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, argTenantIDVal)

if argEnvironmentVal != "" {
// environment is optional
exec.Args = append(exec.Args, argEnvironment)
exec.Args = append(exec.Args, argEnvironmentVal)
}
if o.isSet(flagServerID) {
exec.Args = append(exec.Args, argServerID)
exec.Args = append(exec.Args, o.TokenOptions.ServerID)
} else if argServerIDVal != "" {
exec.Args = append(exec.Args, argServerID)
exec.Args = append(exec.Args, argServerIDVal)

if isLegacyConfigMode {
exec.Args = append(exec.Args, argIsLegacy)
}
if o.isSet(flagClientID) {
exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, o.TokenOptions.ClientID)
} else if !isAlternativeLogin && argClientIDVal != "" {
// when MSI is enabled, the clientID in azure authInfo will be disregarded
exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, argClientIDVal)

case token.ServicePrincipalLogin:

if argClientIDVal == "" {
return fmt.Errorf("%s is required", argClientID)
}
if !isAlternativeLogin && o.isSet(flagTenantID) {
exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, o.TokenOptions.TenantID)
} else if !isAlternativeLogin && argTenantIDVal != "" {
exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, argTenantIDVal)

exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, argClientIDVal)

if argTenantIDVal == "" {
return fmt.Errorf("%s is required", argTenantID)
}
if !isAlternativeLogin && o.isSet(flagIsLegacy) && o.TokenOptions.IsLegacy {
exec.Args = append(exec.Args, argIsLegacy)
} else if !isAlternativeLogin && (cfgConfigModeVal == "" || cfgConfigModeVal == "0") {
exec.Args = append(exec.Args, argIsLegacy)

exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, argTenantIDVal)

if argEnvironmentVal != "" {
// environment is optional
exec.Args = append(exec.Args, argEnvironment)
exec.Args = append(exec.Args, argEnvironmentVal)
}
if !isAlternativeLogin && o.isSet(flagClientSecret) {

if o.isSet(flagClientSecret) {
exec.Args = append(exec.Args, argClientSecret)
exec.Args = append(exec.Args, o.TokenOptions.ClientSecret)
}
if !isAlternativeLogin && o.isSet(flagClientCert) {

if o.isSet(flagClientCert) {
exec.Args = append(exec.Args, argClientCert)
exec.Args = append(exec.Args, o.TokenOptions.ClientCert)
}
if !isAlternativeLogin && o.isSet(flagUsername) {

if isLegacyConfigMode {
exec.Args = append(exec.Args, argIsLegacy)
}

case token.MSILogin:

if o.isSet(flagClientID) {
exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, o.TokenOptions.ClientID)
} else if o.isSet(flagIdentityResourceID) {
exec.Args = append(exec.Args, argIdentityResourceID)
exec.Args = append(exec.Args, o.TokenOptions.IdentityResourceId)
}

case token.ROPCLogin:

if argClientIDVal == "" {
return fmt.Errorf("%s is required", argClientID)
}

exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, argClientIDVal)

if argTenantIDVal == "" {
return fmt.Errorf("%s is required", argTenantID)
}

exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, argTenantIDVal)

if argEnvironmentVal != "" {
// environment is optional
exec.Args = append(exec.Args, argEnvironment)
exec.Args = append(exec.Args, argEnvironmentVal)
}

if o.isSet(flagUsername) {
exec.Args = append(exec.Args, argUsername)
exec.Args = append(exec.Args, o.TokenOptions.Username)
}
if !isAlternativeLogin && o.isSet(flagPassword) {

if o.isSet(flagPassword) {
exec.Args = append(exec.Args, argPassword)
exec.Args = append(exec.Args, o.TokenOptions.Password)
}
if o.isSet(flagLoginMethod) {
exec.Args = append(exec.Args, argLoginMethod)
exec.Args = append(exec.Args, o.TokenOptions.LoginMethod)

if isLegacyConfigMode {
exec.Args = append(exec.Args, argIsLegacy)
}

case token.WorkloadIdentityLogin:

if o.isSet(flagClientID) {
exec.Args = append(exec.Args, argClientID)
exec.Args = append(exec.Args, o.TokenOptions.ClientID)
}

if o.isSet(flagTenantID) {
exec.Args = append(exec.Args, argTenantID)
exec.Args = append(exec.Args, o.TokenOptions.TenantID)
}

if o.isSet(flagAuthorityHost) {
exec.Args = append(exec.Args, argAuthorityHost)
exec.Args = append(exec.Args, o.TokenOptions.AuthorityHost)
}

if o.isSet(flagFederatedTokenFile) {
exec.Args = append(exec.Args, argFederatedTokenFile)
exec.Args = append(exec.Args, o.TokenOptions.FederatedTokenFile)
}
}

authInfo.Exec = exec
authInfo.AuthProvider = nil
}
Expand Down Expand Up @@ -259,3 +325,21 @@ func getExecArg(authInfoPtr *api.AuthInfo, someArg string) (resultStr string) {
}
return
}

func getExecBoolArg(authInfoPtr *api.AuthInfo, someArg string) bool {
if someArg == "" {
return false
}
if authInfoPtr == nil || authInfoPtr.Exec == nil || authInfoPtr.Exec.Args == nil {
return false
}
if len(authInfoPtr.Exec.Args) < 1 {
return false
}
for i := range authInfoPtr.Exec.Args {
if authInfoPtr.Exec.Args[i] == someArg {
return true
}
}
return false
}
Loading

0 comments on commit 820e730

Please sign in to comment.