mirror of
https://github.com/kubernetes/client-go.git
synced 2025-08-09 19:27:35 +00:00
Merge pull request #105794 from margocrawf/master
--as-uid flag in kubectl and kubeconfigs. Kubernetes-commit: c9baa14d708415225ed030e520970b3e1b6e4349
This commit is contained in:
commit
6d69eb8ad6
4
go.mod
4
go.mod
@ -31,7 +31,7 @@ require (
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
google.golang.org/protobuf v1.26.0
|
||||
k8s.io/api v0.0.0-20211104203923-7979b39b3911
|
||||
k8s.io/apimachinery v0.0.0-20211104003341-94020522c95c
|
||||
k8s.io/apimachinery v0.0.0-20211105203412-d7e096fd217f
|
||||
k8s.io/klog/v2 v2.30.0
|
||||
k8s.io/kube-openapi v0.0.0-20210817084001-7fbd8d59e5b8
|
||||
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b
|
||||
@ -41,5 +41,5 @@ require (
|
||||
|
||||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20211104203923-7979b39b3911
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20211104003341-94020522c95c
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20211105203412-d7e096fd217f
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -600,8 +600,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
|
||||
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.0.0-20211104203923-7979b39b3911 h1:KKASx2y52X9MofhS6vOnUdLGgz+CH8/OxZrJsG7lnk4=
|
||||
k8s.io/api v0.0.0-20211104203923-7979b39b3911/go.mod h1:Y3aSuR3Z7RwvAGbnpQ1+oBIWgAIxvlHcaUCVUzOgpuo=
|
||||
k8s.io/apimachinery v0.0.0-20211104003341-94020522c95c h1:18i+Svc8AQt2tsHgUJjMgipgIRROqVsdttom0N2URHQ=
|
||||
k8s.io/apimachinery v0.0.0-20211104003341-94020522c95c/go.mod h1:NdmIf2dMPBkkSfPmCDRbThro3RAWWypv6x+CttBbMto=
|
||||
k8s.io/apimachinery v0.0.0-20211105203412-d7e096fd217f h1:GhfOaNapo86CszGIgYEv2kO136l13jxtg9Ollcge114=
|
||||
k8s.io/apimachinery v0.0.0-20211105203412-d7e096fd217f/go.mod h1:NdmIf2dMPBkkSfPmCDRbThro3RAWWypv6x+CttBbMto=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
|
||||
|
@ -124,7 +124,10 @@ type AuthInfo struct {
|
||||
// Impersonate is the username to act-as.
|
||||
// +optional
|
||||
Impersonate string `json:"act-as,omitempty"`
|
||||
// ImpersonateGroups is the groups to imperonate.
|
||||
// ImpersonateUID is the uid to impersonate.
|
||||
// +optional
|
||||
ImpersonateUID string `json:"act-as-uid,omitempty"`
|
||||
// ImpersonateGroups is the groups to impersonate.
|
||||
// +optional
|
||||
ImpersonateGroups []string `json:"act-as-groups,omitempty"`
|
||||
// ImpersonateUserExtra contains additional information for impersonated user.
|
||||
|
@ -111,10 +111,13 @@ type AuthInfo struct {
|
||||
// TokenFile is a pointer to a file that contains a bearer token (as described above). If both Token and TokenFile are present, Token takes precedence.
|
||||
// +optional
|
||||
TokenFile string `json:"tokenFile,omitempty"`
|
||||
// Impersonate is the username to imperonate. The name matches the flag.
|
||||
// Impersonate is the username to impersonate. The name matches the flag.
|
||||
// +optional
|
||||
Impersonate string `json:"as,omitempty"`
|
||||
// ImpersonateGroups is the groups to imperonate.
|
||||
// ImpersonateUID is the uid to impersonate.
|
||||
// +optional
|
||||
ImpersonateUID string `json:"as-uid,omitempty"`
|
||||
// ImpersonateGroups is the groups to impersonate.
|
||||
// +optional
|
||||
ImpersonateGroups []string `json:"as-groups,omitempty"`
|
||||
// ImpersonateUserExtra contains additional information for impersonated user.
|
||||
|
@ -167,6 +167,7 @@ func autoConvert_v1_AuthInfo_To_api_AuthInfo(in *AuthInfo, out *api.AuthInfo, s
|
||||
out.Token = in.Token
|
||||
out.TokenFile = in.TokenFile
|
||||
out.Impersonate = in.Impersonate
|
||||
out.ImpersonateUID = in.ImpersonateUID
|
||||
out.ImpersonateGroups = *(*[]string)(unsafe.Pointer(&in.ImpersonateGroups))
|
||||
out.ImpersonateUserExtra = *(*map[string][]string)(unsafe.Pointer(&in.ImpersonateUserExtra))
|
||||
out.Username = in.Username
|
||||
@ -201,6 +202,7 @@ func autoConvert_api_AuthInfo_To_v1_AuthInfo(in *api.AuthInfo, out *AuthInfo, s
|
||||
out.Token = in.Token
|
||||
out.TokenFile = in.TokenFile
|
||||
out.Impersonate = in.Impersonate
|
||||
out.ImpersonateUID = in.ImpersonateUID
|
||||
out.ImpersonateGroups = *(*[]string)(unsafe.Pointer(&in.ImpersonateGroups))
|
||||
out.ImpersonateUserExtra = *(*map[string][]string)(unsafe.Pointer(&in.ImpersonateUserExtra))
|
||||
out.Username = in.Username
|
||||
|
@ -181,6 +181,7 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
|
||||
if len(configAuthInfo.Impersonate) > 0 {
|
||||
clientConfig.Impersonate = restclient.ImpersonationConfig{
|
||||
UserName: configAuthInfo.Impersonate,
|
||||
UID: configAuthInfo.ImpersonateUID,
|
||||
Groups: configAuthInfo.ImpersonateGroups,
|
||||
Extra: configAuthInfo.ImpersonateUserExtra,
|
||||
}
|
||||
@ -255,6 +256,7 @@ func (config *DirectClientConfig) getUserIdentificationPartialConfig(configAuthI
|
||||
if len(configAuthInfo.Impersonate) > 0 {
|
||||
mergedConfig.Impersonate = restclient.ImpersonationConfig{
|
||||
UserName: configAuthInfo.Impersonate,
|
||||
UID: configAuthInfo.ImpersonateUID,
|
||||
Groups: configAuthInfo.ImpersonateGroups,
|
||||
Extra: configAuthInfo.ImpersonateUserExtra,
|
||||
}
|
||||
|
@ -217,6 +217,43 @@ func TestTLSServerNameClearsWhenServerNameSet(t *testing.T) {
|
||||
matchStringArg("", actualCfg.ServerName, t)
|
||||
}
|
||||
|
||||
func TestFullImpersonateConfig(t *testing.T) {
|
||||
config := createValidTestConfig()
|
||||
config.Clusters["clean"] = &clientcmdapi.Cluster{
|
||||
Server: "https://localhost:8443",
|
||||
}
|
||||
config.AuthInfos["clean"] = &clientcmdapi.AuthInfo{
|
||||
Impersonate: "alice",
|
||||
ImpersonateUID: "abc123",
|
||||
ImpersonateGroups: []string{"group-1"},
|
||||
ImpersonateUserExtra: map[string][]string{"some-key": {"some-value"}},
|
||||
}
|
||||
config.Contexts["clean"] = &clientcmdapi.Context{
|
||||
Cluster: "clean",
|
||||
AuthInfo: "clean",
|
||||
}
|
||||
config.CurrentContext = "clean"
|
||||
|
||||
clientBuilder := NewNonInteractiveClientConfig(*config, "clean", &ConfigOverrides{
|
||||
ClusterInfo: clientcmdapi.Cluster{
|
||||
Server: "http://something",
|
||||
},
|
||||
}, nil)
|
||||
|
||||
actualCfg, err := clientBuilder.ClientConfig()
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
matchStringArg("alice", actualCfg.Impersonate.UserName, t)
|
||||
matchStringArg("abc123", actualCfg.Impersonate.UID, t)
|
||||
matchIntArg(1, len(actualCfg.Impersonate.Groups), t)
|
||||
matchStringArg("group-1", actualCfg.Impersonate.Groups[0], t)
|
||||
matchIntArg(1, len(actualCfg.Impersonate.Extra), t)
|
||||
matchIntArg(1, len(actualCfg.Impersonate.Extra["some-key"]), t)
|
||||
matchStringArg("some-value", actualCfg.Impersonate.Extra["some-key"][0], t)
|
||||
}
|
||||
|
||||
func TestMergeContext(t *testing.T) {
|
||||
const namespace = "overridden-namespace"
|
||||
|
||||
@ -808,6 +845,12 @@ func matchByteArg(expected, got []byte, t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func matchIntArg(expected, got int, t *testing.T) {
|
||||
if expected != got {
|
||||
t.Errorf("Expected %d, got %d", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceOverride(t *testing.T) {
|
||||
config := &DirectClientConfig{
|
||||
overrides: &ConfigOverrides{
|
||||
|
@ -53,6 +53,7 @@ type AuthOverrideFlags struct {
|
||||
ClientKey FlagInfo
|
||||
Token FlagInfo
|
||||
Impersonate FlagInfo
|
||||
ImpersonateUID FlagInfo
|
||||
ImpersonateGroups FlagInfo
|
||||
Username FlagInfo
|
||||
Password FlagInfo
|
||||
@ -154,6 +155,7 @@ const (
|
||||
FlagEmbedCerts = "embed-certs"
|
||||
FlagBearerToken = "token"
|
||||
FlagImpersonate = "as"
|
||||
FlagImpersonateUID = "as-uid"
|
||||
FlagImpersonateGroup = "as-group"
|
||||
FlagUsername = "username"
|
||||
FlagPassword = "password"
|
||||
@ -179,6 +181,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"},
|
||||
ImpersonateUID: FlagInfo{prefix + FlagImpersonateUID, "", "", "UID to impersonate for the operation"},
|
||||
ImpersonateGroups: FlagInfo{prefix + FlagImpersonateGroup, "", "", "Group 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"},
|
||||
@ -219,6 +222,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.ImpersonateUID.BindStringFlag(flags, &authInfo.ImpersonateUID).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)
|
||||
|
@ -323,9 +323,9 @@ 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 or ImpersonateUserExtra should be requested with a user
|
||||
if (len(authInfo.ImpersonateGroups) > 0 || len(authInfo.ImpersonateUserExtra) > 0) && (len(authInfo.Impersonate) == 0) {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("requesting groups or user-extra for %v without impersonating a user", authInfoName))
|
||||
// ImpersonateUID, ImpersonateGroups or ImpersonateUserExtra should be requested with a user
|
||||
if (len(authInfo.ImpersonateUID) > 0 || len(authInfo.ImpersonateGroups) > 0 || len(authInfo.ImpersonateUserExtra) > 0) && (len(authInfo.Impersonate) == 0) {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("requesting uid, groups or user-extra for %v without impersonating a user", authInfoName))
|
||||
}
|
||||
return validationErrors
|
||||
}
|
||||
|
@ -508,6 +508,78 @@ func TestValidateAuthInfoExecInteractiveModeInvalid(t *testing.T) {
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoImpersonateUser(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
Impersonate: "user",
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
}
|
||||
test.testAuthInfo("user", t)
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoImpersonateEverything(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
Impersonate: "user",
|
||||
ImpersonateUID: "abc123",
|
||||
ImpersonateGroups: []string{"group-1", "group-2"},
|
||||
ImpersonateUserExtra: map[string][]string{"key": {"val1", "val2"}},
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
}
|
||||
test.testAuthInfo("user", t)
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoImpersonateGroupsWithoutUserInvalid(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
ImpersonateGroups: []string{"group-1", "group-2"},
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
`requesting uid, groups or user-extra for user without impersonating a user`,
|
||||
},
|
||||
}
|
||||
test.testAuthInfo("user", t)
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoImpersonateExtraWithoutUserInvalid(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
ImpersonateUserExtra: map[string][]string{"key": {"val1", "val2"}},
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
`requesting uid, groups or user-extra for user without impersonating a user`,
|
||||
},
|
||||
}
|
||||
test.testAuthInfo("user", t)
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoImpersonateUIDWithoutUserInvalid(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
ImpersonateUID: "abc123",
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
`requesting uid, groups or user-extra for user without impersonating a user`,
|
||||
},
|
||||
}
|
||||
test.testAuthInfo("user", t)
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
type configValidationTest struct {
|
||||
config *clientcmdapi.Config
|
||||
expectedErrorSubstring []string
|
||||
|
Loading…
Reference in New Issue
Block a user