-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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
Support pulling requestheader CA from extension-apiserver-authentication ConfigMap without client CA #66394
Conversation
On the subject of the PR description, please remove the duplicated sections (you don't have to follow the template to the letter if you're duplicating description. It's probably worth explicitly mentioning a real-world use case where this comes up (e.g. we use all token-based auth in our cluster). Something like
More comments to come |
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.
comments inline. I think we might need a discussion around whether or not this needs a flag (I think it probably does, because you might still want to error out if you're expecting to get a client CA, but don't)
@@ -240,7 +240,8 @@ func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticati | |||
return nil, err | |||
} | |||
if incluster == nil { | |||
return nil, fmt.Errorf("cluster doesn't provide client-ca-file") | |||
glog.Warningf("cluster doesn't provide client-ca-file") |
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.
looks like your indentation has changed here. might want to double-check that.
Might also want to say cluster doesn't provide a client-ca file, so client certificate authentication won't work
.
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'll fix these in the next upload
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.
Made the warning message more explicit
@@ -240,7 +240,8 @@ func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticati | |||
return nil, err | |||
} | |||
if incluster == nil { |
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.
we should have an option like SkipInClusterClientCALookup
or something, similarly to SkipInClusterLookup
, or perhaps change the behavior of SkipInClusterLookup
@kubernetes/sig-api-machinery-pr-reviews WDYT?
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.
or maybe @kubernetes/sig-auth-pr-reviews
/cc @cheftako |
@@ -240,7 +240,8 @@ func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticati | |||
return nil, err | |||
} | |||
if incluster == nil { | |||
return nil, fmt.Errorf("cluster doesn't provide client-ca-file") | |||
glog.Warningf("cluster doesn't provide client-ca-file") |
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.
probably worth making this warning more explicit about what it was looking for, and what usually should be done in the main apiserver to populate that configmap. also worth warning that this is continuing without the ability to use x509-based authentication
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 getRequestHeader()
should be consistent with this as well... if we successfully look up the options from the configmap, and get no info, should getRequestHeader()
log a warning that we're continuing without request header auth, and continue?
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.
@liggitt I didn't make the same change for request header because as per my understanding delegated authentication requires the requestheader client CA to trust the aggregator, hence failing when it isn't present is the right behavior. @DirectXMan12 What do you think?
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.
Yeah, I think there's a lot more of an argument for "I want requestheader auth without normal client cert auth" than vice-versa (I don't see the case for auto-auth setup with only normal client cert auth).
Do agree with the warning being more explicit -- one of the reasons I actually suggested an option, so that you have to manually opt in to this behavior if you want it.
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'm open to making the log message more explicit as suggested though unsure why a new flag is necessary to opt in to building the extension API server without client-ca? What's the risk in that case?
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 think there's a lot more of an argument for "I want requestheader auth without normal client cert auth" than vice-versa
That's probably true. Forget I said anything.
fbc4063
to
ef7fe60
Compare
@@ -240,7 +240,8 @@ func (s *DelegatingAuthenticationOptions) getClientCA() (*ClientCertAuthenticati | |||
return nil, err | |||
} | |||
if incluster == nil { | |||
return nil, fmt.Errorf("cluster doesn't provide client-ca-file") | |||
glog.Warningf("cluster doesn't provide client-ca-file in configmap/%s in %s, so client certificate authentication to extension api-server won't work.", authenticationConfigMapName, authenticationConfigMapNamespace) |
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.
having glog warnings in funcs with error return type is an anti-pattern. Can't we return a better error and make sure it is printed in the caller's code?
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 code is switching an error at startup for a warning. I'm concerned that this will make debugging handshake issues with aggregated api-servers much harder. This only works if there is some external system enforcing the client-ca is kept consistent for all aggregated api-servers. I agree with @DirectXMan12, if we proceed with this it should be a deliberate decision to not look up config map rather than implied by it being empty.
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.
Are you suggesting a new flag like SkipInClusterClientCaLookup
to not look up client-ca in ConfigMap when set to true?
If so, I have two follow up questions:
- How do administrators reason between usage of existing
SkipInClusterLookup
and the newSkipInClusterClientCaLookup
? Won't that be confusing? - Isn't the recommendation to use an altogether separate CA for aggregator layer as a client? It will be nice to understand scenario in which extension API server needs to authenticate it's client using cluster's client CA.
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.
Sorry going to work on your questions out of order.
The aggregation system uses two sets of certs, 1 to authenticate incoming requests from the Kube API Server (KAS) and another as the client cert it uses to identify itself in mutual TLS when making requests to the Kube API Server (and possibly other systems such as webhooks). The cert obtained from the config map is the cert used to authenticate the requester is the KAS. The reference recommendation has to do with if the second cert could be relied on as being signed by the same CA. Currently we allow it to be different and allow the the CA being given to the KAS via API registration. Then the aggregated API server would normally load this cert from a location on disk. In the sample api server we specify this location with the flags --tls-cert-file and --tls-private-key-file.
On your first question I am not sure there should be a difference. However we passed a check for SkipInClusterLookup, so we know its not set. However I do not like the idea of the admin having configured the system to use in cluster certs but we do something else because the client ca file was missing.
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.
Details are under @sttts comments. I am a little concerned that the admin has set SkipInClusterLookup to false but that by not returning error on a missing cluster ca file we are effectively skipping the in cluster lookup.
Successful fetching of the configmap with an absent client-ca means the kube-apiserver was started without that option, right? Continuing with a warning in that case still seems like honoring the specified configuration to me, and doesn't impact the ability of the server to handle requests via the aggregator |
Successful fetching of the configmap with an absent client-ca means we failed to get a value for the extension-apiserver-authentication key from the config map. That probably means that the KAS was started without "--requestheader-client-ca-file" option. However than having the aggregator started with SkipInClusterLookup set to false seems like a misconfiguration across multiple servers. Having that misconfiguration cause the aggregator to try and read a local file which may or may not be correct/present for the CA seems dangerous. I also suspect that if its a misconfiguration then it won't actually work (the handshake at least) and that will be hard to debug. |
That's not what this PR is changing. This PR is tolerating a kube-apiserver started without --client-ca, which does not affect aggregation |
Unless I'm missing something this PR is changing the staging/src/k8s.io/apiserver/pkg/server/options.DelegatingAuthenticationOptions::getClientCA() method. This in turned is used by staging/src/k8s.io/apiserver/pkg/server/options.RecommendedOptions which is in turn used by staging/src/k8s.io/sample-apiserver/pkg/cmd/server.WardleServerOptions. This is the example we present of how to build an aggregated api-server and I believe it is the mechanism we intend our customers to use for establishing trust on aggregated api-servers. So I believe this does affect aggregation. |
delegating authentication configures two methods of authentication:
if no client ca is configured for the kube-apiserver, that does not affect aggregation |
/lgtm |
/test pull-kubernetes-integration |
@@ -394,3 +402,13 @@ func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authentication | |||
|
|||
return client.TokenReviews(), nil | |||
} | |||
|
|||
func IgnorableError(s string, args ...interface{}) ignorableError { |
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 pubilc constructor. Would prefer to not leak it.
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, fixed
@sttts Could you take a look at the latest revision again? |
@@ -394,3 +402,13 @@ func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authentication | |||
|
|||
return client.TokenReviews(), nil | |||
} | |||
|
|||
func newIgnorableError(s string, args ...interface{}) ignorableError { |
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.
simpler: type ignorable error
. Then we don't need a constructor or any func. Just the type wrapper.
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.
If I'm creating just a type wrapper, then I wasn't able to differentiate between ignorable error and non-ignorable error.
See: https://play.golang.org/p/T0hSRsyPKj9
I'm fairly new to golang so this may be due to something I'm missing.
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.
Compare https://goplay.space/#C2IONvrPbiH (which does not work, as you say) and https://goplay.space/#NfoDb-hUFtS which does.
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.
Done
Failed run looks unrelated to change, re-running /test pull-kubernetes-e2e-kops-aws |
@@ -394,3 +402,5 @@ func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authentication | |||
|
|||
return client.TokenReviews(), nil | |||
} | |||
|
|||
type ignorableError struct{ error } |
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.
👍
gofmt will not like this, will it?
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.
strange. isn't there a space missing?
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 likes it.
if _, ignorable := err.(ignorableError); !ignorable { | ||
return err | ||
} else { | ||
glog.Warningf("%s", err) |
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.
Warning(err)
…ion ConfigMap without client CA This commit prevents extension API server from erroring out during bootstrap when the core API server doesn't support certificate based authentication for it's clients i.e. client-ca isn't present in extension-apiserver-authentication ConfigMap in kube-system. This can happen in cluster setups where core API server uses Webhook token authentication. Fixes: kubernetes#65724
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: cheftako, rtripat, sttts 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. |
…te-extension-apiserver-authentication Automatic merge from submit-queue (batch tested with PRs 67694, 64973, 67902). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. kube-apiserver: always create configmap/extension-apiserver-authentication Other components (aggregated apiservers) read the configmap and fail hard if it does not exist. But they work without all fields being set (#66394). In the future, components like ctrl-manager and scheduler won't need kube-apiserver to authenticate with them at all. So, consequently we should always create the file, even if it is empty. ```release-note Always create configmaps/extensions-apiserver-authentication from kube-apiserver. ```
This commit prevents extension API server from erroring out during bootstrap when the core
API server doesn't support certificate based authentication for it's clients i.e. client-ca isn't
present in extension-apiserver-authentication ConfigMap in kube-system.
This can happen in cluster setups where core API server uses Webhook token authentication.
Fixes: #65724
Which issue(s) this PR fixes
Fixes #65724
Special notes for your reviewer:
Release note: