Can you use proxy authentication and basic auth together for OpenSearch dashboards?

Versions (relevant - OpenSearch/Dashboard/Server OS/Browser):

OpenSearch 2.9

Describe the issue:

I am using proxy-based authentication for my OpenSearch Dashboards, which is working great.

The problem I’m having is: how can I upload saved objects (index patterns, visualizations, etc) using the Dashboards API? Since my Dashboards are only configured to allow proxy-based authentication and there’s no easy way to script logging in via the proxy in order to upload via the API, I wanted to use basic authentication for these Dashboards API requests.

But based on my testing, I cannot seem to get proxy-based authentication and basic authentication working for the dashboards at the same time. The documentation about multi-auth for Dashboards implies that you can use OIDC, SAML, and basic authentication together, but not proxy-based authentication.

So is it possible to configure Dashboards to allow proxy-based and basic authentication at the same time? I tried this configuration snippet in opensearch_dashboards.yml, but it threw an error when trying to start up Dashboards:

opensearch_security.auth.multiple_auth_enabled: true
opensearch_security.auth.type: ["proxy", "basicauth"]

Configuration:

opensearch_dashboards.yml

server.name: opensearchDashboards
server.host: "0.0.0.0"
opensearch.hosts: [https://localhost:9200]

opensearch.ssl.verificationMode: none
opensearch.username: admin
opensearch.password: admin

opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: ["Private", "Global"]
opensearch_security.readonly_mode.roles: ["opensearch_dashboards_read_only"]

# Use this setting if you are running opensearch dashboards without https
opensearch_security.cookie.secure: false

data.search.usageTelemetry.enabled: false
opensearch.requestHeadersAllowlist: ["securitytenant","Authorization","x-forwarded-for","x-proxy-user","x-proxy-roles","x-proxy-ext-spaceids","x-proxy-ext-orgids"]

opensearch_security.proxycache.user_header: "x-proxy-user"
opensearch_security.proxycache.roles_header: "x-proxy-roles"

opensearch_security.auth.multiple_auth_enabled: true
opensearch_security.auth.type: "proxy"

opensearch_security/config.yml

---
_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    http:
      xff:
        enabled: true
        internalProxies: ".*"
        remoteIpHeader: "x-forwarded-for"
    authc:
      proxy_auth_domain:
        http_enabled: true
        transport_enabled: true
        order: 0
        http_authenticator:
          type: extended-proxy
          challenge: false
          config:
            user_header: "x-proxy-user"
            roles_header: "x-proxy-roles"
            attr_header_prefix: "x-proxy-ext-"
        authentication_backend:
          type: noop
      basic_internal_auth_domain:
        description: "Authenticate via HTTP Basic against internal users database"
        http_enabled: true
        transport_enabled: true
        order: 4
        http_authenticator:
          type: basic
          challenge: true
        authentication_backend:
          type: intern

Relevant Logs or Screenshots:

$ curl \
    -X POST \
    -H "content-type: application/json" \
    -u 'admin:admin' \
    -H "osd-xsrf: true" \
    http://localhost:5601/api/saved_objects/_import \
    -d '
    {
        "attributes": {
            "title": "logs-*",
            "timeFieldName": "@timestamp"
        }
    }' 
{"statusCode":401,"error":"Unauthorized","message":"Unauthorized"}%

Hi @mark.boyd,

You can try with similar as per below:

curl --location 'http://localhost:5601/api/saved_objects/_import' \
--header 'x-proxy-user: admin' \
--header 'x-proxy-roles: admin' \
--header 'x-forwarded-for: 0.0.0.0' \
--header 'Content-Type: application/json' \
--data-raw '{
        "attributes": {
            "title": "logs-*",
            "timeFieldName": "@timestamp"
        }
    }'

Best,
mj

Hi @mantas,

Thanks for the reply!

Am I correct in my understanding that setting the x-proxy-user and x-proxy-roles headers to admin is effectively sending a request to OpenSearch Dashboards directly that looks like it came through the proxy? Thus, you’re bypassing the proxy authentication.

I would assume that this approach is only secure if OpenSearch Dashboards is not directly exposed to the public internet.

Thanks,
Mark

Hi @mark.boyd,

The example above is to “illustrate” what header is expected for proxy authentication by OpenSearch how you add it, is completely up to you. You can bypass it or configure your reverse proxy to do so.

Isn’t bypassing proxy authentication what you are trying to achieve with “basic auth”, correct?

Note: proxy is unsupported with “multiple_auth” on Dashboards.

As for securing your cluster, I would strongly advise enabling TLS, see more here: Configuring TLS certificates - OpenSearch Documentation

Best,
mj

Hey @Mantas ,

Isn’t bypassing proxy authentication what you are trying to achieve with “basic auth”, correct?

Not exactly. I wanted to know if basic auth can be used to make requests to the Dashboards in addition to the proxy, because making a request directly to Dashboards using the proxy headers somehow feels wrong or insecure to me, but perhaps I’m mistaken.

Regardless, I think your statement that proxy is unsupported for multiple_auth on Dashboards answers my question.

So if you have Dashboards configured to use proxy authentication, it seems like the only way to make an authenticated request directly to the Dashboards saved objects API is by setting the expected proxy headers? And if so, my follow up question is whether that is secure?

I am using TLS for both the OpenSearch cluster and Dashboards.

Thanks for all the help,
Mark

You should be secure, as long as you secure all your communications with TLS.

Here are more details:

Best,
mj

@Mantas - Yeah, we are using TLS for OpenSearch and the Dashboards. Thanks!

1 Like