chaos-mesh / chaos-mesh

A Chaos Engineering Platform for Kubernetes.
https://chaos-mesh.org
Apache License 2.0
6.72k stars 832 forks source link

Dashboard can support accepting cookies from the server side #1665

Open Gallardot opened 3 years ago

Gallardot commented 3 years ago

Feature Request

Is your feature request related to a problem? Please describe:

If the Dashboard has SecurityMode enabled, the user needs to enter the token manually.But this is not a friendly way to integrate with third-party systems.Because it is not possible to simulate user behavior on the client side.

Describe the feature you'd like:

Hopefully Dashboard can support accepting cookies from the server side. If the server returns set-cookies in the HttpHeader, Dashboard can set the token according to the cookies and save them to localStorage. In this way, we can add custom logic processing to such third party systems as Nginx when we do integration.

server {
    # ...

    location =/chaosmesh {
        add_header Set-Cookie "ChaosMesh-Authorization=YOUR_SECRET_TOKEN_HERE";
        add_header Set-Cookie "ChaosMesh-AuthRole=YOUR_ROLE_HERE";
        add_header Set-Cookie "ChaosMesh-Namespace=YOUR_DEFAULT_NAMESPACE_HERE";
        proxy_pass http://YOUR.DASHBOARD.SERVICE.URL.HERE;
    }
}

We can even implement anonymous user read-only based on this feature. If you have similar needs, please discuss them together.thank you.

Describe alternatives you've considered:

Teachability, Documentation, Adoption, Migration Strategy:

markandersontrocme commented 2 years ago

@cwen0 @Gallardot

I currently use oauth2_proxy with Auth0 to grant access to our kubernetes-dashboard. I would like to be able to achieve something similar for chaos-mesh.

Is it possible to implement something like this: https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/README.md#authorization-header?

markandersontrocme commented 2 years ago

I just did some testing and I have almost got it working. I am using oauth2-proxy so I am setting these annotations in the ingress of chaos-mesh:

  ingress:
    enabled: true
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: /
      nginx.ingress.kubernetes.io/auth-response-headers: Authorization
      nginx.ingress.kubernetes.io/auth-signin: >-
        https://${LOGIN_BASE_URL_EXT}/oauth2/start?rd=https://$host$request_uri
      nginx.ingress.kubernetes.io/auth-url: http://${LOGIN_BASE_URL}/oauth2/auth
      ingress.kubernetes.io/configuration-snippet: |
        auth_request_set $token $upstream_http_authorization;
        proxy_set_header Authorization $token;

After I login I am prompted to enter an RBAC token, here I can just enter anything I want (test, test) and I am able to use the dashboard as I am setting the Authorization header at the ingress level.

Is it possible to implement a flag to simply remove the pop up for RBAC token as this approach works?

Gallardot commented 2 years ago

I just did some testing and I have almost got it working. I am using oauth2-proxy so I am setting these annotations in the ingress of chaos-mesh:

  ingress:
    enabled: true
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: /
      nginx.ingress.kubernetes.io/auth-response-headers: Authorization
      nginx.ingress.kubernetes.io/auth-signin: >-
        https://${LOGIN_BASE_URL_EXT}/oauth2/start?rd=https://$host$request_uri
      nginx.ingress.kubernetes.io/auth-url: http://${LOGIN_BASE_URL}/oauth2/auth
      ingress.kubernetes.io/configuration-snippet: |
        auth_request_set $token $upstream_http_authorization;
        proxy_set_header Authorization $token;

After I login I am prompted to enter an RBAC token, here I can just enter anything I want (test, test) and I am able to use the dashboard as I am setting the Authorization header at the ingress level.

Is it possible to implement a flag to simply remove the pop up for RBAC token as this approach works?

@MarkAndersonTrocme I don't know the details of this part, so there may be a lot of work to do. But I agree with you. The current implementation is not very friendly for third-party system authentication integration.

WDYT. @cwen0 @g1eny0ung

g1eny0ung commented 2 years ago

Here's my take on the issue:

TL;DR

it's ok to support this. But there is not yet a definitive answer to how to achieve it.

Details

Since we currently support two ways to perform authorization: RBAC (bare) or Google OAuth (GCP), one needs you to input a token manually, this is nearly the same as the login view as Kubernetes dashboard, then we save it into localStorage for the next use.

But Google Oauth is different. The server will perform set-cookie in the response to store the token as cookies, and the frontend will extract it later and put it into the request headers (Also bearer token).

Now let's assume we need to support third-party authentication. In most cases, setting cookies through a reverse proxy and carrying them in subsequent requests is a very common practice. To implement this, we can borrow the current GCP implementation and use common cookie names.

The next question is how to avoid login pop-ups. I think we can tell the frontend that we don't need the login popup anymore and that you need to get the token from cookies by setting the environment variable in the same way as you set the securityMode.

I will discuss security next.

Security

If we use the cookie approach, we must guard against CSRF. This can be referred to: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#security.

But if we set httpOnly, we have to add more logic (modify the current middleware to be compatible with cookie authentication in the backend) because we can't get the cookie with js. Or we can generate the CSRF token through the backend, which also works.

Finally

So this is one way I thought of implementing it.

I also want to make it clear that supporting third-party authentication in this way is a hack. We can't guarantee the security of this approach in Chaos Mesh, and users need to protect themselves against possible dangers. It is also important to note that users will need to detect the login and handle the logout themselves, either by providing additional routes to detect the presence of cookies and clear cookies or by specifying redirect and logout routes in environment variables that are then invoked through the frontend.

markandersontrocme commented 2 years ago

@g1eny0ung

Is there not a simpler approach although a bit more hacky. The kubernetes-dashboard supports a feature to "enable skip login" which allows you to skip the login page. If something like that was implemented you would be able to hit "Skip" and it would log you in but you would not be able to do anything unless you had an Authorization header set with a token.

This would mean anyone that uses a reverse-proxy would be able to set the Authorization header and you would be able to just skip the RBAC pop up.

Right now with a reverse-proxy and setting the Authorization header, I am able to login by providing anything in the pop up, as the reverse-proxy is always setting the Authorization header.

image

g1eny0ung commented 2 years ago

@MarkAndersonTrocme I see what you mean, it's complicated in the way I was thinking. If that were the case, for now it would just be a matter of configuring the login popup to be turned off.

bumarcell commented 1 year ago

We're also interested in this! We're using oauth2proxy now and forwarding the ID token which is doing all the auth we want, but still have to click that login-popup away in the dashboard :/