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

Return appropriate status codes for rejected requests #97

Merged
merged 1 commit into from
Apr 24, 2019

Conversation

maxsmythe
Copy link
Contributor

Currently we are relying on the framework to set status codes, which always returns 200 OK, which is not okay in some situations.

This fixes a bug where rejected create requests appear to apply successfully and cause kubectl to return an exit code of zero.

Signed-off-by: Max Smythe smythe@google.com

Signed-off-by: Max Smythe <smythe@google.com>
@maxsmythe maxsmythe requested a review from ritazh April 24, 2019 22:15
@maxsmythe
Copy link
Contributor Author

@liggitt this should fix the return code on GK's side.

I think there may be some API tweaks needed in the controller-runtime library to allow the consumer of the webhook API to set the response code.

@liggitt
Copy link

liggitt commented Apr 24, 2019

lgtm

@liggitt
Copy link

liggitt commented Apr 24, 2019

at minimum, the controller-runtime library should be setting code to something >= 400 if allowed=false

I could see an additional helper that accepts a status reason and maps that to the standard code

@ritazh
Copy link
Member

ritazh commented Apr 24, 2019

LGTM

@maxsmythe maxsmythe merged commit 03d36b6 into open-policy-agent:master Apr 24, 2019
if vResp.Response.Result == nil {
vResp.Response.Result = &metav1.Status{}
}
vResp.Response.Result.Code = http.StatusForbidden
Copy link
Contributor

Choose a reason for hiding this comment

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

@maxsmythe

Don't you want to send back 422 (Unprocessable entity) instead of 403 (Forbidden)

403 is what is sent back in an RBAC/AUTH failure and this is going to confuse the living daylights out of users.

We use 422 in a number of other places to indicate validation failures:

e.g. https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto#L728

@brendandburns
Copy link
Contributor

@maxsmythe @ritazh

Quick comment, I don't think that 403 is the right response code in this case. 403 is an RBAC/Authn/Authz related code, I think 422 is what we typically use for "parseable, but invalid data"

@liggitt
Copy link

liggitt commented Apr 25, 2019

Is this invalid data, or valid data forbidden by policy? By the time we get here, the object has passed API validation and in the absence of this plugin, would be allowed.

I can see it both ways… as a point of reference, policy-type admission plugins in-tree return forbidden errors (e.g. https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/admission/security/podsecuritypolicy/admission.go#L149)

@liggitt
Copy link

liggitt commented Apr 25, 2019

I think the message that accompanies the forbidden error makes all the difference in helping the user understand the reason

@brendandburns
Copy link
Contributor

Hrm, I don't think that matches with the standard usage of HTTP codes.

I agree that the specification is vague enough that you could interpret it this way, I think in practice almost no one expects that a 403 means "I don't like that object"

The key sentence in the spec is:

... [403] indicates that the server understood the request but refuses to authorize it.

Do we really think of policy as 'authorizing' a request? I really think it is 'validating' a request.

@liggitt
Copy link

liggitt commented Apr 25, 2019

This is the bit that makes the most sense to me:

However, a request might be forbidden for reasons unrelated to the credentials.

400 and 422 have implications that don't seem quite right either (as if we don't understand their request or cannot accept their request… in this case, we understand it perfectly, and it would normally be considered valid, but a policy is forbidding it)

Like I said, I can see it both ways, I'm not sure any of them are a perfect match

@maxsmythe
Copy link
Contributor Author

My perspective is that constraints are a form of authorization in that they set boundaries on what users are allowed to do vs. what they theoretically could do on an unconstrained system. This implies 403.

There is certainly a lot of gray area here. I think the most correct code depends on the intent of the admin implementing the constraint, which we cannot know a priori.

Two examples:

If an admin creates a constraint that limits users to requesting amounts of RAM that are actually bookable, the most appropriate code seems to be 422

If an admin requires everyone to use a blessed container repository, then the appropriate code seems to be 403.

My guess is that the primary use case is policy-based (403) vs correctness-based (422), though I may be wrong.

@brendandburns
Copy link
Contributor

@maxsmythe I agree there's lots of gray.

What if the admin requires certain labels (e.g. team metadata like contact info) that feels more like 422 (e.g. the RAM example) vs the container registry (which is more like forbidden)

Anyway, I'm happy to drop this, we should probably document it somewhere, and definitely make sure that the error messages are on-point so that no one gets confused.

@maxsmythe maxsmythe deleted the http_status branch July 9, 2019 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants