-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
allow front proxy in front of API #12803
Conversation
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 reasonable
pkg/cmd/server/api/types.go
Outdated
// API instead of against the /oauth endpoint. | ||
type RequestHeaderAuthenticationOptions struct { | ||
// ClientCA is a file with the trusted signer certs. If empty, no request verification is done, and any direct request to the OAuth server can impersonate any identity from this provider, merely by setting a request header. | ||
ClientCA string |
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.
Require a value here? I wish we had for the RequestHeaderIdentityProvider as well.
edit: looks like validation is requiring it. Update godoc
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.
Add to file references function
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.
Needs to make it into the client ca pool used 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.
Needs to make it into the client ca pool used by the server
Yes, one step at a time I think. I'll open an issue, but I think the wiring was nasty until 1.6.
if err != nil { | ||
return nil, err | ||
} | ||
ret.Handlers = append([]authenticator.Request{requestHeaderAuthenticator}, ret.Handlers...) |
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.
Should be first inside the list of handlers in the group adder, right? Why not just add it to authenticators
first at the top of the method?
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.
cc @enj - might require additions to the integration test ensuring failures in the auth chain short-circuit
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.
Should be first inside the list of handlers in the group adder, right? Why not just add it to authenticators first at the top of the method?
I was going to make the front proxy tell us all the groups, but I don't feel strongly.
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 was going to make the front proxy tell us all the groups, but I don't feel strongly.
I changed my mind. I think I feel strongly. If the front proxy is telling us its user=system:anonymous, group=system:unauthenticated
, then we don't want to add system:authenticated
.
pkg/cmd/server/api/v1/types.go
Outdated
ClientCommonNames []string `json:"clientCommonNames"` | ||
|
||
// UsernameHeaders is the list of headers to check for user information. First hit wins. | ||
// X-Remote-User is the default |
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 defaults, right?
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 defaults, right?
Isn't this the default 80+% of the time? We can distinguish between nil
and []string
(or at least we should be able to), why make them specify things they likely want as default.
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.
When it comes to headers being used to convey auth, make them tell us
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.
When it comes to headers being used to convey auth, make them tell us
done.
/cc |
ba03e6c
to
7fc31b9
Compare
if len(config.RequestHeader.ClientCA) == 0 { | ||
validationResults.AddErrors(field.Required(fldPath.Child("requestHeader.clientCA"), "must be specified for a secure connection")) | ||
} | ||
if len(config.RequestHeader.ClientCommonNames) == 0 { |
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 supposed to be optional?
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's net new, so we can require it if we want. I'd rather start by requiring it and relax later if we want
requestHeaderAuthenticator, err := headerrequest.NewSecure( | ||
config.AuthConfig.RequestHeader.ClientCA, | ||
config.AuthConfig.RequestHeader.ClientCommonNames, | ||
config.AuthConfig.RequestHeader.UsernameHeaders, |
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 only gets defaulted if you round trip the config right?
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 only gets defaulted if you round trip the config right?
We do, don't we?
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 do not think we do so in integration tests (which is why I had to specify it directly).
Thanks to @enj for tests and the client-cert request wiring. [test] |
expectedProjects sets.String | ||
}{ | ||
{ | ||
name: "empty user", |
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.
Hmm this may be the wrong behavior. Should we expect the anonymous user or an unauthorized error when you do a GET
to the front proxy but it does not set any headers on your behalf? @liggitt
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.
Hmm this may be the wrong behavior. Should we expect the anonymous user or an unauthorized error when you do a GET to the front proxy but it does not set any headers on your behalf? @liggitt
The kube-aggregator won't ever send an empty user. In my head, going through a proxy and not having an identity was a failure, but I can see the case for a proxy only attaches credentials it knows about and sends the rest through.
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.
front proxies already have to set the system:authenticated
group explicitly. We should make them explicitly set system:anonymous
and system:unauthenticated
if they want to proxy an anonymous user
3c8d9b9
to
ad369ea
Compare
Defaulting removed, validation tightened. |
@@ -112,6 +113,17 @@ func BuildDefaultAPIServer(options configapi.MasterConfig) (*apiserveroptions.Se | |||
server.GenericServerRunOptions.TLSCertFile = options.ServingInfo.ServerCert.CertFile | |||
server.GenericServerRunOptions.TLSPrivateKeyFile = options.ServingInfo.ServerCert.KeyFile | |||
server.GenericServerRunOptions.ClientCAFile = options.ServingInfo.ClientCA | |||
|
|||
// TODO this is a terrible hack that should be removed in 1.6 |
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.
issue or it won't happen
data = append(data, fileBytes...) | ||
data = append(data, []byte(separator)...) | ||
} | ||
tmpFile, err := ioutil.TempFile("", prefix) |
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.
permissions on this file are important, given what write access to it allows
c39d81d
to
fb70686
Compare
@@ -542,3 +552,27 @@ func getAPIResourceConfig(options configapi.MasterConfig) genericapiserver.APIRe | |||
|
|||
return resourceConfig | |||
} | |||
|
|||
// TODO remove this func in 1.6 when we get rid of the hack above |
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.
Remove 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.
@deads2k you forgot to remove concatenateFiles
...
pkg/cmd/server/api/v1/types.go
Outdated
type RequestHeaderAuthenticationOptions struct { | ||
// ClientCA is a file with the trusted signer certs. It is required. | ||
ClientCA string `json:"clientCA"` | ||
// ClientCommonNames is an optional list of common names to require a match from. If empty, any client certificate validated against the clientCA bundle is considered authoritative. |
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.
Docs need to be updated to reflect tighter validation.
if err != nil { | ||
glog.Fatalf("Error setting up request header client certificates: %v", err) | ||
} | ||
if len(requestHeaderCACerts) > 0 { |
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 check is probably unnecessary.
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.
Eh, nvm that code will give you a nil
slice even with a nil
error.
@@ -81,8 +109,27 @@ func (a *requestHeaderAuthRequestHandler) AuthenticateRequest(req *http.Request) | |||
if len(name) == 0 { | |||
return nil, false, nil | |||
} | |||
groups := allHeaderValues(req.Header, a.groupHeaders) |
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.
Does this have to be updated to fail if the proxy sent no headers per @liggitt's comment?
Signed-off-by: Monis Khan <[email protected]>
Evaluated for origin test up to 76db97a |
continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/768/) (Base Commit: e019eb7) |
All comments addressed. If we have to revert the upstream pick (it was lgtm'ed) we can do that, but this is needed to move aggregation and aggregated API servers forward. [merge] |
continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/768/) (Image: devenv-rhel7_6027) |
Evaluated for origin merge up to 76db97a |
Ok, I'll squash it into the permissions commit for later today. |
This allows a front proxy to provide complete user information to our API server. This is needed to integrate smoothly with the
kube-aggregator
.WIP because I haven't written an integration test yet to handle the wiring. Let's make sure we all agree this roughly right first.
@liggitt @mfojtik
@openshift/api-review for the config api types
@mfojtik this is probably card worthy to get it tested.
@jwforres because you hit it.