Skip to content
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

Merged
merged 6 commits into from
Mar 3, 2017

Conversation

deads2k
Copy link
Contributor

@deads2k deads2k commented Feb 3, 2017

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.

Copy link
Contributor

@liggitt liggitt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable

// 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
Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor Author

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...)
Copy link
Contributor

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?

Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

ClientCommonNames []string `json:"clientCommonNames"`

// UsernameHeaders is the list of headers to check for user information. First hit wins.
// X-Remote-User is the default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No defaults, right?

Copy link
Contributor Author

@deads2k deads2k Feb 6, 2017

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.

Copy link
Contributor

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

Copy link
Contributor Author

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.

@soltysh
Copy link
Contributor

soltysh commented Feb 7, 2017

/cc

@deads2k
Copy link
Contributor Author

deads2k commented Feb 15, 2017

rebased.

@enj @mfojtik do you think you could pick up integration tests for this pull?

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 {
Copy link
Contributor

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?

Copy link
Contributor

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,
Copy link
Contributor

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?

Copy link
Contributor Author

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?

Copy link
Contributor

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).

@deads2k deads2k changed the title [WIP] allow front proxy in front of API allow front proxy in front of API Feb 23, 2017
@deads2k
Copy link
Contributor Author

deads2k commented Feb 23, 2017

Thanks to @enj for tests and the client-cert request wiring.

[test]

expectedProjects sets.String
}{
{
name: "empty user",
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor

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

@deads2k
Copy link
Contributor Author

deads2k commented Feb 28, 2017

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
Copy link
Contributor

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)
Copy link
Contributor

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

@deads2k
Copy link
Contributor Author

deads2k commented Mar 1, 2017

@liggitt @enj updated the code to a field we added in the rebase for the client cert CA.

@deads2k deads2k force-pushed the auth-01-proxy branch 2 times, most recently from c39d81d to fb70686 Compare March 1, 2017 20:55
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

Copy link
Contributor

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...

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.
Copy link
Contributor

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 {
Copy link
Contributor

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.

Copy link
Contributor

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)
Copy link
Contributor

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?

@openshift-bot openshift-bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 2, 2017
@openshift-bot
Copy link
Contributor

Evaluated for origin test up to 76db97a

@openshift-bot openshift-bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 2, 2017
@openshift-bot
Copy link
Contributor

continuous-integration/openshift-jenkins/test SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/768/) (Base Commit: e019eb7)

@deads2k
Copy link
Contributor Author

deads2k commented Mar 3, 2017

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]

@openshift-bot
Copy link
Contributor

openshift-bot commented Mar 3, 2017

continuous-integration/openshift-jenkins/merge SUCCESS (https://ci.openshift.redhat.com/jenkins/job/test_pull_requests_origin_future/768/) (Image: devenv-rhel7_6027)

@openshift-bot
Copy link
Contributor

Evaluated for origin merge up to 76db97a

@openshift-bot openshift-bot merged commit a86ef13 into openshift:master Mar 3, 2017
@deads2k
Copy link
Contributor Author

deads2k commented Mar 3, 2017

@deads2k you forgot to remove concatenateFiles...

Ok, I'll squash it into the permissions commit for later today.

@deads2k deads2k deleted the auth-01-proxy branch August 3, 2017 19:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants