Skip to content

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

Merged
merged 1 commit into from
Feb 13, 2024

Conversation

mprahl
Copy link
Member

@mprahl mprahl commented Feb 12, 2024

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

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

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?

Copy link
Member Author

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

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?

Copy link
Member Author

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

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.

Copy link
Contributor

@yiraeChristineKim yiraeChristineKim Feb 13, 2024

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.

Copy link
Member Author

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.

Copy link
Contributor

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

Copy link
Contributor

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

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?

Copy link
Member Author

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

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?

Copy link
Member Author

@mprahl mprahl Feb 13, 2024

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.

Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Contributor

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]>
Comment on lines +169 to +176
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.",
Copy link
Member

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

@yiraeChristineKim yiraeChristineKim Feb 13, 2024

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

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?

Copy link

openshift-ci bot commented Feb 13, 2024

[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:
  • OWNERS [mprahl,yiraeChristineKim]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

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.

3 participants