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

Create Admission Controller for user impersonation #189

Closed
alewitt2 opened this issue Jan 25, 2021 · 3 comments
Closed

Create Admission Controller for user impersonation #189

alewitt2 opened this issue Jan 25, 2021 · 3 comments
Assignees
Labels
enhancement New feature or request high severity

Comments

@alewitt2
Copy link
Member

Once we have the ability to do user impersonation, we will need a way to limit who is allowed to use it.

I think the most likely place to do that is in an Admission Controller. We will need the admission controller to know who is trying to make the request, and validate that they are authorized to do user impersonation (possibly via new config or rbac). If the user is allowed to do impersonation, allow whatever they put in the impersonate field to stay as is. If they arent allowed, the controller should inject the user's name in the impersonate field (whether they were trying to do impersonation or not).

Until this is implemented, we are limiting user impersonation only to razeedeploy resources created in the razeedeploy namespace. NOTE: For now, cluster owners should be aware that they should prevent their users from creating razeedeploy resources in the razeedeploy namespace if they want to prevent them from using user-impersonation.

@KHOIOHK87
Copy link
Contributor

KHOIOHK87 commented Feb 17, 2022

Here is an approach to discuss.

Since admission controllers intercept request after authentication/authorization has been applied, we can create a mutating admission webhook server to process requests related to Razee resources.

Example workflow:

  1. A user initiates a request to create a Razee resource, such as MustacheTemplate.
  2. Kube API server handles authentication/authorization.
  3. Mutating admission controller intercepts the request and sends a request to our webhook server.
  4. From the received request, the webhook server will extract info of the authenticated** user, query the user's (cluster) role bindings, get the (cluster) roles from the bindings, and determine if the user is granted impersonate permission. Note: if the authenticated user is the user used by razeedeploy, we can consider skipping querying permissions because razeedeploy user should already be granted impersonating permission.

Based on the outcome and the value clusterAuth.impersonateUser set by the authenticated user, the webhook server will do the followings:

Case 1: The authenticated user does not have impersonate permission:

  • If clusterAuth.impersonateUser is not set, set clusterAuth.impersonateUser to the authenticated user.
  • If clusterAuth.impersonateUser is set, set clusterAuth.impersonateUser to the authenticated user.

Case 2: The authenticated user has impersonate permission:

  • If clusterAuth.impersonateUser is not set, set clusterAuth.impersonateUser to the authenticated user.
  • If clusterAuth.impersonateUser is set, do not change.
  1. Downstream controllers, such as MustacheTemplate controller, use clusterAuth.impersonateUser to create resources under the impersonated user name. This is implemented in base controllers in RazeeDeployCore with some restriction. Once this webhook server is implemented, we can remove the restriction.

Concerns:

  • Step 4 should quickly return response to the mutating admission controller to avoid causing congestion in the request flow. This step may require querying many resources, such as role bindings, roles, user groups, etc. to determine user's permission. Aggregated roles will add more complexity. It looks like there is no API to do GET roles/{username}. Investigate better way (if available) to identify a user's granted permission.
  • Also, in step 4, need to investigate the user info received from the mutating admission controller. It's likely the info of authenticated user. However, need to confirm the case where the initiating user impersonates another user via http header or kubectl --as. Will the user info be of the initiating authenticated user or the impersonated user?
  • In the case of nested resources, we may need to carefully review the effect of impersonation to not cause confusion with RBAC or inadvertently bypass RBACs set by cluster admin.

For example, given the following nested resource tree:

  • MustacheTemplate: impersonateUser A
    • RemoteResource: impersonateUser B
      • RemoteResource: impersonateUser C
        • RemoteResource: impersonateUser D

If cluster admin allows the initiating/authenticated user to impersonate only user A, we will need an efficient way to pass this information downstream. Otherwise, razeedeploy will blindly impersonate user B, C, and D because this simple webhook server, processing subsequent requests made by razeedeploy to create child resources, will not know who created the root resource (Unless we track the tree. This will add more complexity and latency).

The cluster admin may be confused because he/she explicitly grants the authenticated user impersonate permission on user A only. The current implementation also causes this problem even we are limiting the effect of impersonation to a specific namespace, razeedeploy.

@alewitt2 @adamkingit Any thoughts?

@alewitt2
Copy link
Member Author

  • Example workflow sounds great!
  • Concerns
    • quickly return response: any delays you add, are delays preventing the resource getting applied to kube itself. Which obviously isnt great if its super long, but a delay here i think is better then a long delay in our internal processing further along in our controllers, because i user should be able to tell when kubectl has completed or not, vs them just blindly waiting for our controller to finish its processing
    • identify user permissions: ideally youd want to use userImpersonation to see if a user is allowed to do something, this is ideal because it delegates the security work to kube itself instead of trying to replicate it on our own. Unfortunately, i would guess its not possible to use impersonation to test impersonation. I did stumble upon something called SubjectAccessReview (heres where i found a reference to that) that might be useful. Im not sure if there is an api you can hit or if it has to be a kube resource you create and read the result from the yaml, but again it should allow you to delegate the authorization checking to kube, which should be optimized to do this job well.
    • nested resources: i think this is somewhat less of a concern. i would argue we leave this up to the cluster admin to configure the RBAC properly and they should only give user access to the correct things. I think best practices here are never give users ability to impersonate other users, only admins should really be doing this. If an admin decides to give user A ability to impersonate user B, they should understand they are giving them full right to impersonate user B and whatever that entails (specifically if in the past they let user B impersonate user C, they have also given user A that right). While this may open up a privilege escalation path, i think it is consistent with how RBAC functions, and we shouldnt change that behavior.

@KHOIOHK87
Copy link
Contributor

KHOIOHK87 commented May 26, 2022

New admission controller webhook created: https://github.com/razee-io/ImpersonationWebhook

With the introduction of this webhook, users will likely need to create and manage additional role bindings. Razee controllers (or razee deploy core) should be updated to give users options:

  • Go with the existing behavior (impersonation only allowed in razeedeploy namespace), so there is no need to deploy this new webhook and manage extra role bindings.
  • Opt to use the fully implemented impersonation support, by deploying this webhook and managing role bindings per actual monitoring/logging need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request high severity
Projects
None yet
Development

No branches or pull requests

3 participants