-
Notifications
You must be signed in to change notification settings - Fork 22
Add certificate and token auth and authz on the POST API endpoint #177
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
Add certificate and token auth and authz on the POST API endpoint #177
Conversation
@echo "Copying the compliance API certificates locally" | ||
kubectl -n $(KIND_NAMESPACE) get secret compliance-api-cert -o json | jq -r '.data["tls.crt"]' | base64 -d > dev-tls.crt | ||
kubectl -n $(KIND_NAMESPACE) get secret compliance-api-cert -o json | jq -r '.data["ca.crt"]' | base64 -d >> dev-ca.crt | ||
kubectl -n $(KIND_NAMESPACE) get secret compliance-api-cert -o json | jq -r '.data["tls.key"]' | base64 -d > dev-tls.key |
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.
Where this secret is created?
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 defined in build/kind/postgres.yaml using CertManager.
if !allowed { | ||
var username string | ||
|
||
userInfo, err := getTokenUserInfo(req.Context(), authenticatedClient, token) |
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 is just for log.. do we really need?
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 changed it to try parsing the token locally as a best effort. It's important to log unauthorized access attempts for auditing.
allowed, err := canRecordComplianceEvent(cfg, authenticatedClient, authenticator, reqEvent.Cluster.Name, r) | ||
if err != nil { | ||
if errors.Is(err, ErrNotAuthorized) { | ||
writeErrMsgJSON(w, "Unauthorized", http.StatusUnauthorized) |
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 error is propagator SA doesn't have "CREATE
" for SubjectAccessReviews. I think it is StatusInternalServerError
.
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.
There's a problem with 401 Unauthorized, the HTTP status code for authentication errors. And that’s just it: it’s for authentication, not authorization. Receiving a 401 response is the server telling you, “you aren’t authenticated–either not authenticated at all or authenticated incorrectly–but please reauthenticate and try again.” To help you out, it will always include a WWW-Authenticate header that describes how to authenticate.
This is what I found. Here isn't about 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.
I think it's right. If the user provided credential (token or cert) does not allow us to get to the subject access review call, then it's unauthorized (bad authentication provided). If the subject access review says the user is not allowed then it should be a forbidden status 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.
subjectaccess
use propagator's SA, subjectaccess
throw err ErrNotAuthorized mean propagator SA don't have GET access
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.
Also you already wrote //+kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create
This won't fall into here
} | ||
|
||
// req.TLS.PeerCertificates will be empty if certificate authentication is not enabled (e.g. endpoint is not HTTPS) | ||
if req.TLS != nil && len(req.TLS.PeerCertificates) > 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.
If not HTTPS will an error be returned?
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 not HTTPS then req.TLS
will be nil
so then only token based authentication is supported.
return false, ErrNotAuthorized | ||
} | ||
|
||
userClient, err := getClientFromToken(cfg, token) |
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.
Is the previous HTTPS check for certificate auth and this is handling token auth -- but both are HTTPS connections?
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.
Right... certificate auth is only checked if the connection is HTTPS and a certificate was provided for authentication.
If the connection is HTTP or is HTTPS + no certificate authentication was provided, then we fall back to token auth.
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 anything need the HTTP connection? Can we limit it to HTTPS only?
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 it's good to have an HTTP option in case you want a proxy to handle the TLS. In ACM, we never will though.
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 agree to both http
and https
. We have CSV endpoint too. I expect individual users would use CSV endpoint using Curl
If a certificate is provided, the HTTP server will run over HTTPS which enables certificate authentication. The authorization requires a user to have patch access to the policy status on the managed cluster namespace of the managed cluster that the compliance event is for. Relates: https://issues.redhat.com/browse/ACM-6866 Signed-off-by: mprahl <[email protected]>
pflag.StringVar( | ||
&complianceAPICert, "compliance-history-api-cert", "", | ||
"The path to the certificate the compliance history API will use for HTTPS (CA cert, if any, concatenated "+ | ||
"after server cert). If not set, HTTP will be used.", | ||
) | ||
pflag.StringVar( | ||
&complianceAPIKey, "compliance-history-api-key", "", | ||
"The path to the private key the compliance history API will use for HTTPS. If not set, HTTP will be used.", |
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.
Can we make these required? Basically requiring HTTPS
return strings.TrimSpace(strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer")) | ||
} | ||
|
||
// getClientFromToken will generate a Kubernetes client using the input config and token. No authentication data from |
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 we merge this PR first then merge mine? I want to reuse this funcs
} | ||
|
||
// getTokenUsername will parse the token and return the username. If the token is invalid, an empty string is returned. | ||
func getTokenUsername(token string) 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.
Oh?! This was changed?! it was token obj create?. am I dreaming?
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: mprahl, yiraeChristineKim 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 |
If a certificate is provided, the HTTP server will run over HTTPS which enables certificate authentication.
The authorization requires a user to have patch access to the policy status on the managed cluster namespace of the managed cluster that the compliance event is for.
Relates:
https://issues.redhat.com/browse/ACM-6866