New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
client-go: add an exec-based client auth provider #59495
client-go: add an exec-based client auth provider #59495
Conversation
4694bec
to
8a2464e
Compare
8a2464e
to
e8c6647
Compare
cc @mikedanese |
cc @kubernetes/sig-auth-pr-reviews |
// Response defines metadata about a failed request, including HTTP status code and | ||
// response headers. | ||
type Response struct { | ||
// HTTP header returned by the server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/header/headers/
@@ -0,0 +1,4 @@ | |||
#!/bin/sh -e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather name it test-plugin.sh
.
@@ -0,0 +1,4 @@ | |||
#!/bin/sh -e | |||
|
|||
(>&2 echo "$KUBERNETES_EXEC_INFO") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a sub-shell here? And how it differs from echo >&2 "$KUBERNETES_EXEC_INFO"
that is easier to understand IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason. Updated.
4aeb04b
to
ffcd361
Compare
Flaking on #59426 /test pull-kubernetes-unit |
@@ -119,6 +119,9 @@ type AuthInfo struct { | |||
// AuthProvider specifies a custom authentication plugin for the kubernetes cluster. | |||
// +optional | |||
AuthProvider *AuthProviderConfig `json:"auth-provider,omitempty"` | |||
// Exec specifies a custom exec-based authentication plugin for the kubernetes cluster. | |||
// +optional | |||
Exec *ExecConfig `json:"exec,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you decide not to implement this as another AuthProvider?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was called out in the proposal. We know the structure and map[string]string is awkward for expressing things like a list of key/value environment variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
// +genclient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this?
) | ||
|
||
func Convert_clientauthentication_ExecCredentials_To_v1alpha1_ExecCredentials(in *clientauthentication.ExecInfo, out *ExecInfo, s conversion.Scope) error { | ||
return autoConvert_clientauthentication_ExecInfo_To_v1alpha1_ExecInfo(in, out, s) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this if it just calls autoConvert?
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object | ||
|
||
// ExecCredentials are credentials returned by the plugin. | ||
type ExecCredentials struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Request/response non-storage APIs have used a single type and spec/status in the past. Any reason to deviate from that convention?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I don't have a good reason. Switched to spec/status.
func (c *cache) get(s string) (*Authenticator, bool) { | ||
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
a, ok := c.m[s] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return c.m[s]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't seem like that works https://play.golang.org/p/2dzFfrrGBkR
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
if len(c.m) == 0 { | ||
c.m = make(map[string]*Authenticator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not expect this to happen on cache initialization?
) | ||
|
||
func cacheKey(c *api.ExecConfig) string { | ||
h := fnv.New32a() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hash map is already hashing. Do we need to double hash?
a.group, schema.GroupVersion{Group: gvk.Group, Version: gvk.Version}) | ||
} | ||
|
||
if !creds.Expiry.IsZero() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this if block the same as a.exp = creds.Expiry.Time
?
da3b7e9
to
08fedf5
Compare
LGTM |
/assign @smarterclayton For final approval |
type ExecCredentialStatus struct { | ||
// ExpirationTimestamp indicates a time when the provided credentials expire. | ||
// +optional | ||
ExpirationTimestamp metav1.Time `json:"expirationTimestamp,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this has to be a pointer if you actually want it omitted from serialization
} | ||
|
||
a := &Authenticator{ | ||
cmd: config.Command, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems like there are three possibilities for this path:
- relative (e.g.
./foo
) - absolute (e.g.
/path/to/foo
) - $PATH-based (e.g.
curl
)
Was there discussion about how to resolve the referenced command here?
There is already code for resolving files referenced from kubeconfig files so that relative paths are resolved relative to the kubeconfig file (see ResolvePaths and GetAuthInfoFileReferences).
My instinct would be to resolve explicitly relative paths ./foo
in GetAuthInfoFileReferences, leave absolute paths alone, and resolve bare commands (e.g. curl
) using $PATH. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like keeping the relative path logic the same as other files in kubeconfig files. Let me update this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess if you want $PATH
behavior you can invoke a local script
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess if you want $PATH behavior you can invoke a local script
exec.Command already does that: https://golang.org/pkg/os/exec/#Command
no other comments from me |
e89b3c0
to
36d94c5
Compare
36d94c5
to
01801ae
Compare
return []*string{&authInfo.ClientCertificate, &authInfo.ClientKey, &authInfo.TokenFile} | ||
s := []*string{&authInfo.ClientCertificate, &authInfo.ClientKey, &authInfo.TokenFile} | ||
// Only resolve exec command if it isn't PATH based. | ||
if authInfo.Exec != nil && strings.ContainsRune(authInfo.Exec.Command, filepath.Separator) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relative logic added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM... make sure this nuance makes it into the docs ("./foo
is relative to the kubeconfig file, foo
looks in the $PATH")
/lgtm |
(nits addressed) |
/approve
based on sig commentary
…On Wed, Feb 28, 2018 at 11:52 AM, Eric Chiang ***@***.***> wrote:
(nits addressed)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#59495 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABG_px_KPEqe1BIklvUf51IMQeGfx-2Qks5tZYQ4gaJpZM4R9MxO>
.
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ericchiang, liggitt, mikedanese, smarterclayton The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/test all [submit-queue is verifying that this PR is safe to merge] |
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions here. |
Hi @ericchiang is there any documentation that I can refer to to use this. I tried with 1.10 RC kubectl, but it does not seem to call my external command at all. |
…t out Matches Go client's behavior: kubernetes/kubernetes#59495 (comment) Distinguish 3 cases: - absolute (e.g. /path/to/foo) - $PATH-based (e.g. curl) - relative to config file's dir (e.g. ./foo) If base dir explicitly set to nil, refuse to execute external commands, matching existing opt-out from file lookups (ManageIQ#372). Document security aspects of credential plugins.
Updates kubernetes/enhancements#541
Implements kubernetes/community#1503
Closes #57164
/sig auth
/kind feature