-
Notifications
You must be signed in to change notification settings - Fork 19
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
feat(auth): Add OAuth client to service account #292
Conversation
internal/controllers/common/resource_definitions/resource_definitions.go
Outdated
Show resolved
Hide resolved
974cef9
to
33fefbe
Compare
internal/controllers/common/resource_definitions/resource_definitions.go
Outdated
Show resolved
Hide resolved
d466f01
to
468b012
Compare
internal/controllers/common/resource_definitions/resource_definitions.go
Outdated
Show resolved
Hide resolved
It worked for me doing the following:
Normally, I'd use |
380589a
to
61e73c7
Compare
This PR is ready for review. I'd also appreciate it if you could confirm the ClusterRole permissions give the exact permissions that the web-UI needs and nothing more. |
61e73c7
to
4ef5b79
Compare
config/rbac/cryostat_role.yaml
Outdated
- authorization.k8s.io | ||
- "" | ||
resources: | ||
- selfsubjectaccessreviews | ||
- pods | ||
verbs: | ||
- create | ||
- get | ||
- apiGroups: | ||
- "" | ||
resources: | ||
- replicationcontrollers | ||
- endpoints | ||
verbs: | ||
- get | ||
- apiGroups: | ||
- operator.cryostat.io | ||
resources: | ||
- cryostats | ||
verbs: | ||
- create | ||
- delete | ||
- get | ||
- apiGroups: | ||
- operator.cryostat.io | ||
resources: | ||
- flightrecorders | ||
- recordings | ||
verbs: | ||
- create | ||
- delete | ||
- get | ||
- patch | ||
- apiGroups: | ||
- apps | ||
resources: | ||
- deployments | ||
verbs: | ||
- create | ||
- get | ||
- apiGroups: | ||
- apps | ||
resources: | ||
- daemonsets | ||
- replicasets | ||
- statefulsets | ||
verbs: | ||
- get |
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 we'll need to move these permissions to a new ClusterRole after all. When I initially suggested reusing this ClusterRole, I thought the permission you'd need to add would be to use the OAuthClient API. Since the purpose of this is for a role-scoped token, we should add another ClusterRole which we don't bind to Cryostat's ServiceAccount with a ClusterRoleBinding. As it stands, this would give Cryostat the ability to perform these actions in any namespace.
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.
Setting this PR to draft mode while I add the new ClusterRole
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've removed create TokenReviews
and create SelfSubjectAccessReviews
from the new ClusterRole. The backend can request a token with enough permissions using user:info user:check-access role:cryostat-operator-oauth-client:namespace
.
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.
Hey Janelle, I haven't tried it out yet, but do you know if the user:info
scope allows the backend to create a TokenReview, or does that code need to be changed to use the OpenShift users API? I assumed it was the latter.
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'm assuming the user:info
scope lets the backend create a TokenReview, because when I tested my latest image on OpenShift with the following ClusterRole permissions and scope=user%3Ainfo+user%3Acheck-access+role%3Acryostat-operator-oauth-client
as the role scope, I didn't see any errors on the frontend or in the cryostat-sample
logs.
Name: cryostat-operator-oauth-client
Labels: <none>
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
flightrecorders.operator.cryostat.io [] [] [create delete get patch]
recordings.operator.cryostat.io [] [] [create delete get patch]
cryostats.operator.cryostat.io [] [] [create delete get]
pods [] [] [create get]
deployments.apps [] [] [create get]
endpoints [] [] [get]
replicationcontrollers [] [] [get]
daemonsets.apps [] [] [get]
replicasets.apps [] [] [get]
statefulsets.apps [] [] [get]
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 what we're seeing is the TokenReview is being done using Cryostat's ServiceAccount: https://github.com/cryostatio/cryostat/blob/7c010b29b83677ba0a815315ddd50ada6afb5659/src/main/java/io/cryostat/net/OpenShiftAuthManager.java#L270-L288
It still has the create tokenreviews
permission from the existing ClusterRole. So the user:info
scope is not being used right now. Later on, if we change the TokenReview to an OpenShift user API query using the scoped token, the user:info
scope will be necessary. I think that's probably best saved for another PR 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.
Thanks for the clarification. I'll remove user:info
from the backend request then.
95dd1b9
to
4047316
Compare
4047316
to
e154aa1
Compare
Annotations: map[string]string{ | ||
"serviceaccounts.openshift.io/oauth-redirecturi.route": "https://", | ||
"serviceaccounts.openshift.io/oauth-redirectreference.route": string(ref), | ||
}, | ||
}, | ||
} |
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.
Although it's probably harmless, I think we should only set these annotations when running on OpenShift. A Kubernetes user might be confused why there are OpenShift annotations pointing to a non-existent Route. You can pass r.IsOpenShift
when calling this method like we do for NewDeploymentForCR
.
sa := &corev1.ServiceAccount{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: cr.Name, | ||
Namespace: cr.Namespace, | ||
Labels: map[string]string{ | ||
"app": "cryostat", | ||
}, | ||
Annotations: map[string]string{ | ||
"serviceaccounts.openshift.io/oauth-redirecturi.route": "https://", | ||
"serviceaccounts.openshift.io/oauth-redirectreference.route": string(ref), | ||
}, | ||
}, | ||
} | ||
return sa, nil | ||
} |
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.
Just one more suggestion to reduce duplication, you could:
- Create an empty annotations map
- Put the OAuth annotations in the map inside the OpenShift branch
- Return the ServiceAccount with annotations set to the map. In Kubernetes this will be empty, in OpenShift it'll contain the OAuth annotations
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 noticed one more thing, this new ClusterRole will need to be added to our operator bundle. Running make bundle
should copy it to the necessary place.
} | ||
|
||
annotations = map[string]string{ | ||
"serviceaccounts.openshift.io/oauth-redirecturi.route": "https://", |
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 perhaps we should remove this annotation. Right now the operator always creates Routes with some form of TLS enabled, but I think in the near future we may want to allow the user to customize the Routes we create like we do with Ingresses and now Services. In the interest of future-proofing this, I suggest we don't assume HTTPS here.
I tracked down the code that parses the route provided in the oauth-redirectreference.route
annotation:
https://github.com/openshift/library-go/blob/7a65fdb398e28782ee1650959a5e0419121e97ae/pkg/oauth/oauthserviceaccountclient/oauthclientregistry.go#L418-L441
It will use HTTPS for the scheme, unless the Route has no TLS configuration, which sounds like what we'd want. We should be fine to not override this behaviour by forcing HTTPS.
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 good, nice work!
Fixes #289
Lets the cryostat-sample service account access the OpenShift OAuth API by acting as an OAuth client. The redirect uri is created dynamically.
To request a scoped access token with the necessary permissions for the web-UI to create and manage recordings, I added permissions to the existing ClusterRole. The names of the ClusterRole and ServiceAccount are both referenced when making a backend request to the OAuth server in this PR: https://github.com/cryostatio/cryostat/pull/748
More info:
https://docs.openshift.com/container-platform/4.9/authentication/using-service-accounts-in-applications.html