opensearch-project / security-dashboards-plugin

🔐 Manage your internal users, roles, access control, and audit logs from OpenSearch Dashboards
https://opensearch.org/docs/latest/security-plugin/index/
Apache License 2.0
70 stars 152 forks source link

[BUG] Having Anonymous and SAML as sign in options does not work. SAML Login fails when Anonymous is enabled #1731

Closed cwperks closed 5 months ago

cwperks commented 8 months ago

What is the bug?

Its possible to configure OpenSearch Dashboards to use multiple sign in options including Sign in as Anonymous and Sign in with Single Sign on (SAML).

When both of SAML and Anonymous are enabled as sign in options, the SAML authentication will not work and does not redirect to the SAML IdP.

How can one reproduce the bug?

Configure OpenSearch-Dashboards to use Anonymous and SAML:

Sample opensearch_dashboards.yml ```yml opensearch_security.auth.type: ["basicauth", "saml"] opensearch_security.auth.multiple_auth_enabled: true opensearch_security.auth.anonymous_auth_enabled: true opensearch.hosts: [https://host.docker.internal:9200] opensearch.ssl.verificationMode: none opensearch.username: kibanaserver opensearch.password: kibanaserver opensearch.requestHeadersWhitelist: [authorization, securitytenant] # opensearch_security.multitenancy.enabled: true # opensearch_security.multitenancy.tenants.preferred: [Private, Global] opensearch_security.readonly_mode.roles: [kibana_read_only] # Use this setting if you are running opensearch-dashboards without https opensearch_security.cookie.secure: false server.host: '0.0.0.0' ```

Configure OpenSearch with SAML and anonymous enabled.

Sample config/opensearch-security/config.yml ```yml _meta: type: "config" config_version: 2 config: dynamic: kibana: # Kibana multitenancy #multitenancy_enabled: true #server_username: kibanaserver #index: '.kibana' http: anonymous_auth_enabled: true xff: enabled: false internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern authc: basic_internal_auth_domain: description: "Authenticate via HTTP Basic against internal users database" http_enabled: true transport_enabled: true order: 0 http_authenticator: type: basic challenge: false authentication_backend: type: intern saml_auth_domain: http_enabled: true transport_enabled: false order: 1 http_authenticator: type: saml challenge: true config: idp: entity_id: http://localhost:8080/simplesaml/saml2/idp/metadata.php metadata_file: "/path/to/metadata" # metadata_url: sp: entity_id: opensearch-dashboards kibana_url: http://localhost:5601/ roles_key: Role subject_key: NameID exchange_key: '' authentication_backend: type: noop ```

What is the expected behavior?

SAML and Login with Anonymous

Do you have any screenshots?

Screenshot 2024-01-10 at 11 58 26 AM

Do you have any additional context?

The fundamental problem is that Login with SAML relies on the authinfo request failing here. The unauthenticated response includes the information to dashboards on how to redirect to the SAML.

For example:

> GET /_plugins/_security/authinfo HTTP/1.1
> Host: localhost:9200
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< WWW-Authenticate: X-Security-IdP realm="OpenSearch Security" location="http://localhost:8080/simplesaml/saml2/idp/SSOService.php?SAMLRequest=fZJRb9sgFIX%2FisU7wWTUc1ASKWu6LVKWRHXWh75EGN%2FUSBgYF2%2Frv6%2FjdFInbX1BCM45nA%2BYo%2BpskKs%2Bte4efvSAKfvdWYdy3FiQPjrpFRqUTnWAMmlZrb5t5XSSyxB98tpb8sbyvkMhQkzGO5Jt1guy391t9182u1N9FkVZNjPK4cypKPgHOqs%2FCirqG5UXYjYTSpDsASIO3gUZooYAxB42DpNyaVjKp4LmnPL8yAs5LaQoH0m2HniMU2l0tSkFyZj1WtnWY5JlXuYMTRcsXKqzyzBlpgmsqvYVxJ9GwyS0gWSHV9JPxjXGPb0PWV9FKL8ejwd62FdHkq3%2BgN96h30H8TX%2B%2B%2F32H8Vuipyzkw8wBGGKnp0QdB9Neh47MqWRLOeXqRxvIS4vWgQVdUsbhW3tVWxwzt5K5ten3g19N%2BuDt0Y%2FZ5997FT6Pw6f8HHFNPQ8SmXvMIA2ZwPNQGWt%2F3UbQSVYkBR7IBlbXk%2F9%2B08tXwA%3D" requestId="ONELOGIN_bf4688d9-1ef1-4613-9b74-4b5a064994a4"
< content-type: text/plain; charset=UTF-8
< content-length: 0

When anonymous is enabled, this request does not fail and dashboards never redirects.

On inspection, another endpoint _plugins/security/api/authtoken may also need a special carve out when anonymous is enabled on the backend.

stephen-crawford commented 8 months ago

[Triage] Hi @cwperks thanks for filing this issue. This seems like a good edge case to correct. Thanks for point this out. We can close this issue when we have a fix to let the SAML and anonymous auth features be used side by side.

DarshitChanpura commented 6 months ago

Anonymous logout flow seems to be not working as expected. Here's how you can reproduce:

  1. Run the opensearch cluster with anonymous-auth enabled.
  2. Goto localhost:5601 and log in as anonymous user.
  3. Now, logout. This should redirect you to login page.
  4. Now refresh the page, it should still show login page.
  5. Open a new tab, and go to localhost:5601. This should automatically log you in as anonymous user.

Upon further debugging, I found that enabling anonymous auth in config.yml without adding the flag in opensearch_dashboards.yml is causing the saml redirect to fail with 500 status code.

If config.dynamic.http.anonymous_auth_enabled: false then SAML works fine.

DarshitChanpura commented 6 months ago

TLDR; This bug is not solvable at the moment.

Reason:

In current implementation, anonymous auth + any IdP call, expect credentials to be empty in order to follow correct path, and the current implementation skips check over auth domains if anonymous auth is enabled. Once the for loop completes it then enters this else block to assume anonymous user identity.

To solve this problem, we need to identify whether the request is coming as anonymous user or not. Following options were considered:

  1. Add a header { _auth_requesttype: anonymous } to incoming requests from anonymous. But this somehow got overwritten when a request was sent to read dashboards config. So this option was tabled.
  2. Add auth creds from front-end to let backend know that this request is coming as anonymous user. This allows differentiating auth provider requests with anonymous auth requests. (PR: https://github.com/opensearch-project/security/pull/4097). However, this approach would now need direct API calls with anonymous auth to pass a Basic Auth header, hence this approach was tabled as well.

Thus, at the moment, SAML auth is broken when anonymous auth is enabled as there is no way to identify whether the login request is coming as anonymous user or for SAML login since both requests are expected to have null credentials, and there is no way to fix it without a breaking change. (require an identifier header i.e. credentials OR rewrite backend to expect a new AuthType called anonymous).

DarshitChanpura commented 6 months ago

Update: A new approach has been proposed via https://github.com/opensearch-project/security/pull/4152/ and https://github.com/opensearch-project/security-dashboards-plugin/pull/1839 where instead of modifying Anonymous auth related request we instead modify SAML login requests.

This is done by passing a parameter ?auth_request_type=saml when fetching authinfo for SAML login. On backend, a check is added to ensure that a login request containing this parameter in the uri is not considered an anonymous request. This would allow a Saml IdP redirect location to be passed in www-authenticateDrive attribute of the initial error response to then eventually be redirected to SAML login page. More details can be found in the associated PRs.