Skip to content

Commit

Permalink
add --asgroup option to cli
Browse files Browse the repository at this point in the history
The usecase of this change:
When a super user grant some RBAC permissions to a group, he can use
--asgroup to test whether the group get the permissions.
  • Loading branch information
CaoShuFeng committed Mar 29, 2017
1 parent e457259 commit fcc7165
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 18 deletions.
3 changes: 3 additions & 0 deletions staging/src/k8s.io/client-go/tools/clientcmd/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ type AuthInfo struct {
// Impersonate is the username to act-as.
// +optional
Impersonate string `json:"act-as,omitempty"`
// ImpersonateGroups is the groups to imperonate.
// +optional
ImpersonateGroups []string `json:"act-as-groups,omitempty"`
// Username is the username for basic authentication to the kubernetes cluster.
// +optional
Username string `json:"username,omitempty"`
Expand Down
3 changes: 3 additions & 0 deletions staging/src/k8s.io/client-go/tools/clientcmd/api/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ type AuthInfo struct {
// Impersonate is the username to imperonate. The name matches the flag.
// +optional
Impersonate string `json:"as,omitempty"`
// ImpersonateGroups is the groups to imperonate.
// +optional
ImpersonateGroups []string `json:"as-groups,omitempty"`
// Username is the username for basic authentication to the kubernetes cluster.
// +optional
Username string `json:"username,omitempty"`
Expand Down
4 changes: 2 additions & 2 deletions staging/src/k8s.io/client-go/tools/clientcmd/client_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
clientConfig.Host = u.String()
}
if len(configAuthInfo.Impersonate) > 0 {
clientConfig.Impersonate = restclient.ImpersonationConfig{UserName: configAuthInfo.Impersonate}
clientConfig.Impersonate = restclient.ImpersonationConfig{UserName: configAuthInfo.Impersonate, Groups: configAuthInfo.ImpersonateGroups}
}

// only try to read the auth information if we are secure
Expand Down Expand Up @@ -217,7 +217,7 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
mergedConfig.BearerToken = string(tokenBytes)
}
if len(configAuthInfo.Impersonate) > 0 {
mergedConfig.Impersonate = restclient.ImpersonationConfig{UserName: configAuthInfo.Impersonate}
mergedConfig.Impersonate = restclient.ImpersonationConfig{UserName: configAuthInfo.Impersonate, Groups: configAuthInfo.ImpersonateGroups}
}
if len(configAuthInfo.ClientCertificate) > 0 || len(configAuthInfo.ClientCertificateData) > 0 {
mergedConfig.CertFile = configAuthInfo.ClientCertificate
Expand Down
50 changes: 34 additions & 16 deletions staging/src/k8s.io/client-go/tools/clientcmd/overrides.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package clientcmd

import (
"strconv"
"strings"

"github.com/spf13/pflag"

Expand Down Expand Up @@ -52,6 +53,7 @@ type AuthOverrideFlags struct {
ClientKey FlagInfo
Token FlagInfo
Impersonate FlagInfo
ImpersonateGroups FlagInfo
Username FlagInfo
Password FlagInfo
}
Expand Down Expand Up @@ -100,6 +102,19 @@ func (f FlagInfo) BindStringFlag(flags *pflag.FlagSet, target *string) FlagInfo
return f
}

// BindStringSliceFlag binds the flag based on the provided info. If LongName == "", nothing is registered
func (f FlagInfo) BindStringArrayFlag(flags *pflag.FlagSet, target *[]string) FlagInfo {
// you can't register a flag without a long name
if len(f.LongName) > 0 {
sliceVal := []string{}
if len(f.Default) > 0 {
sliceVal = strings.Split(f.Default, " ")
}
flags.StringArrayVarP(target, f.LongName, f.ShortName, sliceVal, f.Description)
}
return f
}

// BindBoolFlag binds the flag based on the provided info. If LongName == "", nothing is registered
func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
// you can't register a flag without a long name
Expand All @@ -116,22 +131,23 @@ func (f FlagInfo) BindBoolFlag(flags *pflag.FlagSet, target *bool) FlagInfo {
}

const (
FlagClusterName = "cluster"
FlagAuthInfoName = "user"
FlagContext = "context"
FlagNamespace = "namespace"
FlagAPIServer = "server"
FlagAPIVersion = "api-version"
FlagInsecure = "insecure-skip-tls-verify"
FlagCertFile = "client-certificate"
FlagKeyFile = "client-key"
FlagCAFile = "certificate-authority"
FlagEmbedCerts = "embed-certs"
FlagBearerToken = "token"
FlagImpersonate = "as"
FlagUsername = "username"
FlagPassword = "password"
FlagTimeout = "request-timeout"
FlagClusterName = "cluster"
FlagAuthInfoName = "user"
FlagContext = "context"
FlagNamespace = "namespace"
FlagAPIServer = "server"
FlagAPIVersion = "api-version"
FlagInsecure = "insecure-skip-tls-verify"
FlagCertFile = "client-certificate"
FlagKeyFile = "client-key"
FlagCAFile = "certificate-authority"
FlagEmbedCerts = "embed-certs"
FlagBearerToken = "token"
FlagImpersonate = "as"
FlagImpersonateGroups = "as-group"
FlagUsername = "username"
FlagPassword = "password"
FlagTimeout = "request-timeout"
)

// RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
Expand All @@ -153,6 +169,7 @@ func RecommendedAuthOverrideFlags(prefix string) AuthOverrideFlags {
ClientKey: FlagInfo{prefix + FlagKeyFile, "", "", "Path to a client key file for TLS"},
Token: FlagInfo{prefix + FlagBearerToken, "", "", "Bearer token for authentication to the API server"},
Impersonate: FlagInfo{prefix + FlagImpersonate, "", "", "Username to impersonate for the operation"},
ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroups, "", "", "Groups to impersonate for the operation, this flag can be repeated to specify multiple groups."},
Username: FlagInfo{prefix + FlagUsername, "", "", "Username for basic authentication to the API server"},
Password: FlagInfo{prefix + FlagPassword, "", "", "Password for basic authentication to the API server"},
}
Expand Down Expand Up @@ -192,6 +209,7 @@ func BindAuthInfoFlags(authInfo *clientcmdapi.AuthInfo, flags *pflag.FlagSet, fl
flagNames.ClientKey.BindStringFlag(flags, &authInfo.ClientKey).AddSecretAnnotation(flags)
flagNames.Token.BindStringFlag(flags, &authInfo.Token).AddSecretAnnotation(flags)
flagNames.Impersonate.BindStringFlag(flags, &authInfo.Impersonate).AddSecretAnnotation(flags)
flagNames.ImpersonateGroups.BindStringArrayFlag(flags, &authInfo.ImpersonateGroups).AddSecretAnnotation(flags)
flagNames.Username.BindStringFlag(flags, &authInfo.Username).AddSecretAnnotation(flags)
flagNames.Password.BindStringFlag(flags, &authInfo.Password).AddSecretAnnotation(flags)
}
Expand Down
4 changes: 4 additions & 0 deletions staging/src/k8s.io/client-go/tools/clientcmd/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@ func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []err
validationErrors = append(validationErrors, fmt.Errorf("more than one authentication method found for %v; found %v, only one is allowed", authInfoName, methods))
}

// ImpersonateGroups should be requested with a user
if (len(authInfo.ImpersonateGroups) > 0) && (len(authInfo.Impersonate) == 0) {
validationErrors = append(validationErrors, fmt.Errorf("requesting groups %v for %v without impersonating a user", authInfo.ImpersonateGroups, authInfoName))
}
return validationErrors
}

Expand Down

0 comments on commit fcc7165

Please sign in to comment.