-
Notifications
You must be signed in to change notification settings - Fork 31
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(security): add SecurityContext to recordings #1188
base: main
Are you sure you want to change the base?
Conversation
d4f6023
to
a3033a4
Compare
d0d0814
to
16682ba
Compare
Test image available:
|
16682ba
to
77c1b14
Compare
Test image available:
|
ccd276c
to
41d6dd2
Compare
Test image available:
|
Current issues:
Haven't been able to construct a scenario where there are actually users and targets across different namespaces and with different permissions to the namespaces, but for the current single-namespace deployment scenario this looks like a transparent change (as expected) other than the minor bugs listed above. |
@tthvo @maxcao13 this will be ready for proper review soon I think. This needs to also be tested with cryostatio/cryostat-web#707 . There are some basic instructions on that PR about how to do so, but it's pretty standard development workflow. Please give it a try and see if you can catch any more broken cases that I haven't run into yet. I can also talk through the high-level design here and how it is intended to solve the multi-namespace/multi-tenant security concerns. I'll fix the unit tests soon as well, I broke them in one of the last commits where I made things fail faster if the correct request security context could not be determined. |
c3a3c73
to
25c4b2d
Compare
Test image available:
|
Tests seem flakey, it looks like something might not be working properly or cleaning up properly perhaps. There is also at least one itest that I have |
Manually testing the PR on ocp and it seems I can't find anything so far in a normal workflow that's been broken, but I will continue to do so after the weekend. Looks good so far, I think @tthvo and I would definitely benefit from a walkthrough or writeup on how your changes are able to handle multi-namespace security concerns. |
So the concept is centered around that new The idea is that currently, on OpenShift, Cryostat only deploys into a single namespace, and every user who accesses Cryostat must already have some level of access to that namespace and the other resources (deployments, pods, endpoints) within. This has been baked into Cryostat and its integration with OpenShift RBAC for a long time. For other deployments that don't use the So, the goal is to extend the OpenShift platform implementation to support deployment into one namespace but talking to targets across other namespaces. If Cryostat is deployed into Namespace Z and there are target applications in Namespaces A and B, then recordings captured from Target A1 should somehow only be accessible to users who have permissions in Namespace A. For active recordings on presently-visible targets this is pretty easy - we know about the target, we know which Namespace we have observed it in, and so we can ask OpenShift if the auth token associated with the request has the correct permissions in Namespace A. This is already well-supported in Cryostat today. The difficulty comes from archived recordings. Here we take the data out of Target A and write it to a file on the PVC that Cryostat controls. Before this PR, this operation loses some critical information. We still know the JMX service URL of the target that this data was collected from, but we don't know the Namespace that the target was located in. If we are lucky that information may actually be embedded within the hostname of the JMX service URL but we can't necessarily rely on that. The Security Context is meant to be a small additional data packet that can contain this kind of information. In the OpenShift case, the required information is just that Namespace name, so the Okay, all that said, we already had a way to determine the Namespace that a target belongs to, and now we have a Security Context that can hold that information. That Security Context is added as a field of the recording Metadata object. I applied a Gson trick so that this field gets included when this metadata is serialized and we are going to write it to a file for preserving the metadata on disk, but excluded when we are serializing it to include in an API response. The metadata already gets copied and preserved along with the recording JFR data when an active recording is copied to the archives, so now the Security Context also follows the recording data around. Now we have that information attached to both active and archived recordings. The last thing that needs to be done is to make sure we actually check the requesting user's permissions against that Security Context. This is again implemented by the So, what about API requests that don't touch any target or archived recording? Those don't have any explicit namespacing. Things like simply pinging Cryostat on Lastly, there is one security hole in this implementation that I just figured out while typing this. Automated Rules allow permissions leaking across Namespaces which could end up looking like a privilege escalation. Users need the permissions I will think and experiment with this some more. I'm not sure what to do about this at face value. Rules should probably be able to apply across namespaces. We could include a list of namespaces along with the rule definition and check that the user has permissions in all of those namespaces at rule creation time, but it's possible that the user loses those permissions later on in the external RBAC system and then the rule "should" also lose permissions, but it would not. Maybe that's OK and we require the admin user (whoever removed the first user's permissions) to also manually go and clean up the rules. Or, since we already have a specific On the bright side, the targets and recordings still fall into the Security Context system described above, and so users would still need the appropriate permissions within the correct namespaces to actually be able to access any of the JFR data that would result from the rule. But, an unprivileged user should not be able to use rules to start recordings on targets, especially since recordings can incur performance overhead penalties depending on the selected event template. |
25c4b2d
to
bfadf54
Compare
src/main/java/io/cryostat/net/openshift/OpenShiftAuthManager.java
Outdated
Show resolved
Hide resolved
src/main/java/io/cryostat/net/openshift/OpenShiftAuthManager.java
Outdated
Show resolved
Hide resolved
} else { | ||
ns = ((OpenShiftSecurityContext) securityContext).getNamespace(); | ||
} | ||
// FIXME remove |
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.
remove? Or maybe logger.trace?
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.
Maybe setting it to trace
makes sense. I'll leave it as-is for now since it's handy during development.
src/main/java/io/cryostat/net/openshift/OpenShiftSecurityContext.java
Outdated
Show resolved
Hide resolved
JsonElement json, Type typeOfT, JsonDeserializationContext context) | ||
throws JsonParseException { | ||
if (!(auth.get() instanceof OpenShiftAuthManager)) { | ||
// FIXME actually deserialize, don't make this assumption |
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 these be fixed?
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.
Yes, I'll get around to that later. I think I'll need to add some logic or a migration script somewhere to upgrade existing stored metadata to include security contexts too.
src/main/java/io/cryostat/net/web/http/api/v2/TargetRecordingOptionsListGetHandler.java
Show resolved
Hide resolved
src/main/java/io/cryostat/net/web/http/api/v2/graph/AllArchivedRecordingsFetcher.java
Show resolved
Hide resolved
bfadf54
to
c913f6a
Compare
…n resource claim to determine security context
…s determined from resource claim URL
Signed-off-by: Andrew Azores <[email protected]>
Signed-off-by: Andrew Azores <[email protected]>
Signed-off-by: Andrew Azores <[email protected]>
Signed-off-by: Andrew Azores <[email protected]>
8fc929b
to
2cf3796
Compare
Test image available:
|
I've been able to track down why the OAuth grant is failing for multiple namespaces. Here is the OAuthClient derived from the Service Account in namespace metadata:
name: system:serviceaccount:c:clustercryostat-sample
additionalSecrets:
- <service_account_token>
redirectURIs:
- https://clustercryostat-sample-c.apps.example.com
grantMethod: prompt
scopeRestrictions:
- literals:
- user:info
- user:check-access
- user:list-scoped-projects
- user:list-projects
- clusterRole:
roleNames:
- '*'
namespaces:
- c
allowEscalation: true This is the error from ValidateScopeRestrictions when trying to create a scoped token for namespaces error: '[role:cryostat-operator-oauth-client:a not found in [user:info user:check-access user:list-scoped-projects user:list-projects], role:cryostat-operator-oauth-client:a does not use an approved namespace, role:cryostat-operator-oauth-client:b not found in [user:info user:check-access user:list-scoped-projects user:list-projects], role:cryostat-operator-oauth-client:b does not use an approved namespace]'
errorCauses:
- error: '[role:cryostat-operator-oauth-client:a not found in [user:info user:check-access user:list-scoped-projects user:list-projects], role:cryostat-operator-oauth-client:a does not use an approved namespace]'
errorCauses:
- error: role:cryostat-operator-oauth-client:a not found in [user:info user:check-access user:list-scoped-projects user:list-projects]
- error: role:cryostat-operator-oauth-client:a does not use an approved namespace
- error: '[role:cryostat-operator-oauth-client:b not found in [user:info user:check-access user:list-scoped-projects user:list-projects], role:cryostat-operator-oauth-client:b does not use an approved namespace]'
errorCauses:
- error: role:cryostat-operator-oauth-client:b not found in [user:info user:check-access user:list-scoped-projects user:list-projects]
- error: role:cryostat-operator-oauth-client:b does not use an approved namespace Looking at the OAuthClient, it has a scope restriction requiring the role scopes be in
It seems like in order to get a scoped token to work for multiple namespaces, we can't use the service account as an OAuth client. We would have to manage our own OAuthClient(s): https://docs.openshift.com/container-platform/4.12/authentication/configuring-oauth-clients.html#oauth-register-additional-client_configuring-oauth-clients. |
Nice digging, that's great information to have on hand. I think that definitely pushes me over the edge of saying that this PR and #1409 will be pushed to 2.4.0, since it expands the scope of work required to get this functionality properly working. I will put this PR on the backburner again until after 2.3.0 is out the door. |
This PR/issue depends on:
|
Related to #760
Fixes #1409
Depends on #1338