Proxy Authentication not working

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

Describe the issue:

I have a Docker project running a 2-node OpenSearch cluster locally. For authentication, I’m using proxy authentication with Okta as the OIDC provider. The setup uses Nginx as a reverse proxy and Oauth2-Proxy as the authentication middleware.

Oauth2-Proxy is successfully authenticating users, and Nginx is correctly setting the x-proxy-user and x-proxy-roles headers. From the OpenSearch Dashboard logs, I can confirm that these headers are being received with the expected values.

However, the Dashboard still returns a 401 Unauthorized.

The x-proxy-user (e.g., user@example.com) belongs to the okta-admin group in Okta. This group is mapped in roles_mapping.yml to all_access, kibana_user, and read_all.

What configuration step might I be missing? Why is it not working?

Configuration:

Important parts from my roles_mapping.yml, security config.yml and opensearch_dashboards.yml

Roles Mapping: $OPENSEARCH_HOME/config/opensearch-security/roles_mapping.yml

all_access:
    reserved: false
    backend_roles:
    - “admin”
    - “okta-admin”
kibana_user:
    reserved: false
    backend_roles:
    - “admin”
    - “okta-admin”
readall:
    reserved: false
    backend_roles:
    - “admin”
    - “okta-admin”

Here is the full content of my security config file:

Security config: $OPENSEARCH_HOME/config/opensearch-security/config.yml

_meta:
  type: "config"
  config_version: 2

config:  
  dynamic:    
    http:      
      anonymous_auth_enabled: false      
      xff:        
        enabled: true        
        internalProxies: '.*'        
        remoteIpHeader: 'x-forwarded-for'    
    authc:      
      proxy_auth_domain:      
      http_enabled: true      
      transport_enabled: true      
      order: 0      
      http_authenticator:        
        type: proxy        
        challenge: false        
        config:          
          user_header: "x-proxy-user"          
          roles_header: "x-proxy-roles"      
      authentication_backend:        
        type: noop

Full content of my opensearch_dashboards.yml:

opensearch.hosts: ["https://localhost:9200"]
opensearch.ssl.verificationMode: none
opensearch.username:kibanauser
opensearch.password:<redacted>
opensearch.security.openid.base_redirect_url: "http://localhost:5601"
opensearch.requestHeadersAllowlist: ["securitytenant", "Authorization", "x-forwarded-for", "x-proxy-user", "x-proxy-roles"]

opensearch_security.auth.type: “proxy”
opensearch_security.proxycache.user_header: “x-proxy user”
opensearch_security.proxycache.roles_header: “x-proxy-roles”

opensearch_security.multitenancy.enabled: true
opensearch_security.multitenancy.tenants.preferred: [Private, Global]
opensearch_security.readonly_mode.roles: [kibana_read_only]
opensearch_security.cookie.secure: false
server.host: '0.0.0.0'

I also have two separate configuration files, node1-opensearch.yml and node2-opensearch.yml, which are mounted to /usr/share/opensearch/config/opensearch.yml on node1 and node2, respectively. The only difference between them is the server certificate and key they reference.

Here is the full content of node1-opensearch.yml for your reference:

cluster.name: "opensearch-cluster"
node.name: "opensearch-node1"
network.host: 0.0.0.0

discovery.see_hosts: ["opensearch-node1", "opensearch-node2"]
cluster.initial_cluster_manager_nodes: ["opensearch-node1", "opensearch-node2"]
plugins.security.ssl.transport.enabled_protocols:
  - "TLSv1"
  - "TLSv1.1"
  - "TLSv1.2"

plugins.security.ssl.transport.pemcert_filepath: /usr/share/opensearch/config/certs/node1.pem
plugins.security.ssl.transpost.pemkey_filepath: /usr/share/opensearch/config/certs/node1-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: /usr/share/opensearch/config/certs/root-ca.pem
plugins.security.ssl.transport.enforce_hostname_verification: false
plugins.security.ssl.transport.enabled: true
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: /usr/share/opensearch/config/certs/node1.pem
plugins.security.ssl.http.pemkey_filepath: /usr/share/opensearch/config/certs/node1-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: /usr/share/opensearch/config/certs/root-ca.pem
plugins.security.allow_unsafe_democertificates: true
plugins.security.allow_default_init_securityindex: true

plugins.security.authcz_admin_dn:
  - "CN=localhost,OU=IT,O=MyOrg,L=NYC,ST=NY,C=US"
plugins.security.nodes_dn:
  - "CN=localhost,OU=IT,O=MyOrg,L=NYC,ST=NY,C=US"

When I try to access OpenSearch directly from the browser using https://localhost:9200/, OpenSearch is sending a No ‘Authorization’ header, send 401 and ‘WWW-Authenticate Basic’ and I am getting the login form. When I try to login as admin using the password that I created in my docker-compose file (i.e. OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_INITIAL_ADMIN_PASSWORD}), it is simply not accepting the password.

What I am working on follows a fairly standard pattern: using Nginx as reverse proxy, Oauth2-Proxy as the authentication middleware and Okta as the OIDC provider. If anyone has a similar Docker project set up and wouldn’t mind sharing the code, I’d greatly appreciate that as a reference.

Relevant Logs or Screenshots:

@sdn Can you please provide your full opensearch_dashboards.yml file and config.yml, please redact any sensitive details.

Also, would you be able to run the following curl command against the opensearch directly and provide the result:

curl --insecure -H "x-proxy-user: <username>" -H "x-proxy-roles: <role>" -H "x-forwarded-for: 1.1.1.1" -XGET "https://<opensearch>:9200/_plugins/_security/authinfo?pretty"

Hello @Anthony , Thank you for the response. I edited my original post and provided the full content of the files you asked for. I have also provided the full content from the opensearch.yml file.

When I ran the following curl command—after replacing the placeholders with the correct values—it returned “Unauthorized”:

curl --insecure -H “x-proxy-user: ” -H “x-proxy-roles: ” -H “x-forwarded-for: 1.1.1.1” -XGET “https://:9200/_plugins/_security/authinfo?pretty”

Please let me know.

Thanks

@sdn There seems to be quite a few parts that are misconfigured:

  1. I would recommend to first get the basicauth working and OSD connecting properly.
    In order to do this you will need to enable basicauth in config.yml.
  2. Admin and node dns cannot be the same:
plugins.security.authcz_admin_dn:
  - "CN=localhost,OU=IT,O=MyOrg,L=NYC,ST=NY,C=US"
plugins.security.nodes_dn:
  - "CN=localhost,OU=IT,O=MyOrg,L=NYC,ST=NY,C=US"
  1. The following setting in opensearch.yml file is incorrect:
opensearch_security.multitenancy.enabled= true

Should be using :, not =.
4. Comment out the proxy configuration in opensearch_dashboards.yml file temporarily.

Once this is configured, can you start OSD and login with admin user?

1 Like

@Anthony Thank you for the suggestions. As for your suggestion #3 I inadvertently replaced : with = while fixing some formatting manually after I posted the content here. In my code I have it as

 opensearch_security.multitenancy.enabled: true

I edited my original post to fix it.

I will take this incremental approach and try to get the basic auth going first. Will get back to you.

1 Like