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: