SAML SSO for Entra ID Failed to get saml header statuscode 401

433 views
Skip to first unread message

noah venema

unread,
Jan 9, 2025, 3:39:13 AM1/9/25
to Wazuh | Mailing List
Hello,

I try to set up SAML SSO for Entra ID. However, when I deploy my configuration and I choose for to login with SSO at the wazuh dashboard a blank space shows up with the error:

{
    "statusCode": 500,
    "error": "Internal Server Error",
    "message": "Internal Error"
}

Also when I check the logs at wazuh dashboard /var/log/messages I get the output:

Jan  8 16:18:19 wada1.domain.net opensearch-dashboards[1872670]: {"type":"log","@timestamp":"2025-01-08T16:18:19Z","tags":["error","plugins","securityDashboards"],"pid":1872670,"message":"Failed to get saml header: Authentication Exception :: {\"path\":\"/_plugins/_security/authinfo\",\"query\":{},\"statusCode\":401,\"response\":\"Authentication finally failed\"}"}
Jan  8 16:18:19 wada1.domain.net opensearch-dashboards[1872670]: {"type":"log","@timestamp":"2025-01-08T16:18:19Z","tags":["error","plugins","securityDashboards"],"pid":1872670,"message":"Failed to get saml header: Authentication Exception :: {\"path\":\"/_plugins/_security/authinfo\",\"query\":{},\"statusCode\":401,\"response\":\"Authentication finally failed\"}"}
Jan  8 16:18:19 wada1.domain.net opensearch-dashboards[1872670]: {"type":"error","@timestamp":"2025-01-08T16:18:19Z","tags":[],"pid":1872670,"level":"error","error":{"message":"Internal Server Error","name":"Error","stack":"Error: Internal Server Error\n    at HapiResponseAdapter.toError (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:127:19)\n    at HapiResponseAdapter.toHapiResponse (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:83:19)\n    at HapiResponseAdapter.handle (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:79:17)\n    at Router.handle (/usr/share/wazuh-dashboard/src/core/server/http/router/router.js:175:34)\n    at processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at handler (/usr/share/wazuh-dashboard/src/core/server/http/router/router.js:140:50)\n    at exports.Manager.execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/toolkit.js:60:28)\n    at Object.internals.handler (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/handler.js:46:20)\n    at exports.execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/handler.js:31:20)\n    at Request._lifecycle (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/request.js:371:32)\n    at Request._execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/request.js:281:9)"},"url":"https://wazuh.domain.net/auth/saml/login?nextUrl=%2F&redirectHash=false","message":"Internal Server Error"}
Jan  8 16:18:19 wada1.domain.net opensearch-dashboards[1872670]: {"type":"error","@timestamp":"2025-01-08T16:18:19Z","tags":[],"pid":1872670,"level":"error","error":{"message":"Internal Server Error","name":"Error","stack":"Error: Internal Server Error\n    at HapiResponseAdapter.toError (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:127:19)\n    at HapiResponseAdapter.toHapiResponse (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:83:19)\n    at HapiResponseAdapter.handle (/usr/share/wazuh-dashboard/src/core/server/http/router/response_adapter.js:79:17)\n    at Router.handle (/usr/share/wazuh-dashboard/src/core/server/http/router/router.js:175:34)\n    at processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at handler (/usr/share/wazuh-dashboard/src/core/server/http/router/router.js:140:50)\n    at exports.Manager.execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/toolkit.js:60:28)\n    at Object.internals.handler (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/handler.js:46:20)\n    at exports.execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/handler.js:31:20)\n    at Request._lifecycle (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/request.js:371:32)\n    at Request._execute (/usr/share/wazuh-dashboard/node_modules/@hapi/hapi/lib/request.js:281:9)"},"url":"https://wazuh.domain.net/auth/saml/login?nextUrl=%2F&redirectHash= Jan  8 16:18:19 wada1.domain.net opensearch-dashboards[1872670]: {"type":"log","@timestamp":"2025-01-08T16:18:19Z","tags":["error","plugins","securityDashboards"],"pid":1872670,"message":"Failed to get saml header: Authentication Exception :: {\"path\":\"/_plugins/_security/authinfo\",\"query\":{},\"statusCode\":401,\"response\":\"Authentication finally failed\"}"}

And Wazuh-indexer:

[2025-01-08T19:31:07,414][WARN ][o.o.s.a.BackendRegistry  ] [wadex2.domain.net] Authentication finally failed for null from x.x.x.x

I use the following opensearch-security config.yml configuration for wazuh indexer:

---

# This is the main OpenSearch Security configuration file where authentication
# and authorization is defined.
#
# You need to configure at least one authentication domain in the authc of this file.
# An authentication domain is responsible for extracting the user credentials from
# the request and for validating them against an authentication backend like Active Directory for example.
#
# If more than one authentication domain is configured the first one which succeeds wins.
# If all authentication domains fail then the request is unauthenticated.
# In this case an exception is thrown and/or the HTTP status is set to 401.
#
# After authentication authorization (authz) will be applied. There can be zero or more authorizers which collect
# the roles from a given backend for the authenticated user.
#
# Both, authc and auth can be enabled/disabled separately for REST and TRANSPORT layer. Default is true for both.
#        http_enabled: true
#        transport_enabled: true
#
# For HTTP it is possible to allow anonymous authentication. If that is the case then the HTTP authenticators try to
# find user credentials in the HTTP request. If credentials are found then the user gets regularly authenticated.
# If none can be found the user will be authenticated as an "anonymous" user. This user has always the username "anonymous"
# and one role named "anonymous_backendrole".
# If you enable anonymous authentication all HTTP authenticators will not challenge
#
#
# Note: If you define more than one HTTP authenticators make sure to put non-challenging authenticators like "proxy" or "clientcert"
# first and the challenging one last.
# Because it's not possible to challenge a client with two different authentication methods (for example
# Kerberos and Basic) only one can have the challenge flag set to true. You can cope with this situation
# by using pre-authentication, e.g. sending a HTTP Basic authentication header in the request.
#
# Default value of the challenge flag is true.
#
#
# HTTP
#   basic (challenging)
#   proxy (not challenging, needs xff)
#   kerberos (challenging)
#   clientcert (not challenging, needs https)
#   jwt (not challenging)
#   host (not challenging) #DEPRECATED, will be removed in a future version.
#                          host based authentication is configurable in roles_mapping
# Authc
#   internal
#   noop
#   ldap

# Authz
#   ldap
#   noop



_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    # Set filtered_alias_mode to 'disallow' to forbid more than 2 filtered aliases per index
    # Set filtered_alias_mode to 'warn' to allow more than 2 filtered aliases per index but warns about it (default)
    # Set filtered_alias_mode to 'nowarn' to allow more than 2 filtered aliases per index silently
    #filtered_alias_mode: warn
    #do_not_fail_on_forbidden: false
    #kibana:
    # Kibana multitenancy
    #multitenancy_enabled: true
    #private_tenant_enabled: true
    #default_tenant: ""
    #server_username: kibanaserver
    #index: '.kibana'
    http:
      anonymous_auth_enabled: false
      xff:
        enabled: false
        internalProxies: '192\.168\.0\.10|192\.168\.0\.11' # regex pattern
        #internalProxies: '.*' # trust all internal proxies, regex pattern
        #remoteIpHeader:  'x-forwarded-for'
        ###### see https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html for regex help
        ###### more information about XFF https://en.wikipedia.org/wiki/X-Forwarded-For
        ###### and here https://tools.ietf.org/html/rfc7239
        ###### and https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Remote_IP_Valve
    authc:
      kerberos_auth_domain:
        http_enabled: false
        transport_enabled: false
        order: 6
        http_authenticator:
          type: kerberos
          challenge: true
          config:
            # If true a lot of kerberos/security related debugging output will be logged to standard out
            krb_debug: false
            # If true then the realm will be stripped from the user name
            strip_realm_from_principal: true
        authentication_backend:
          type: noop
      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:
              metadata_file: "/etc/wazuh-indexer/opensearch-security/wazuh.xml"
              entity_id: https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/
            sp:
              entity_id: https://wazuh.domain.net
              kibana_url: https://wazuh.domain.net:443
              roles_key: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/Roles
              exchange_key: 'X.509 certificate'
        authentication_backend:
          type: noop

And this is wazuh-dashboards.yml config file:

server.host: 0.0.0.0
server.port: 443
opensearch.hosts: ["https://wadex1.domain.net:9200", "https://wadex2.domain.net:9200", "https://wadex3.domain.net:9200"]
opensearch.ssl.verificationMode: certificate
#opensearch.username:
#opensearch.password:
opensearch.requestHeadersAllowlist: ["securitytenant","Authorization"]
opensearch_security.multitenancy.enabled: false
opensearch_security.readonly_mode.roles: ["kibana_read_only"]
server.ssl.enabled: true
server.ssl.key: "{{ domain_nl_net_key_path }}"
server.ssl.certificate: "{{ domain_nl_net_crt_path }}"
opensearch.ssl.certificateAuthorities: ["{{ wazuh_domain_ca_root_path }}"]
uiSettings.overrides.defaultRoute: /app/wz-home
opensearch_security.auth.multiple_auth_enabled: true
opensearch_security.auth.type: ["basicauth", "saml"]
server.xsrf.allowlist: ["/_opendistro/_security/saml/acs/idpinitiated", "/_opendistro/_security/saml/acs", "/_opendistro/_security/saml/logout", "/_plugins/_security/authinfo"]
opensearch_security.session.keepalive: false

what do I miss in my configuration?

Antonio David Gutiérrez

unread,
Jan 9, 2025, 4:38:58 AM1/9/25
to Wazuh | Mailing List
The error seems to be a problem with the configuration of SAML.

What version of the Wazuh dashboard and the Wazuh indexer are you using?

The exchange_key value is different in 4.9.x and other versions.
- 4.9: 64 bits key
- < 4.9: <X509Certificate> value of SAML XML metadata

Related topic: https://github.com/wazuh/wazuh-dashboard/issues/302#issuecomment-2343313045

I see you are using a metadata_file instead of metadata_url as explained in the Wazuh SSO guides. I found a topic that suggested this solution when the OpenSearch Dashboards host has no connection with the SAML IDP: https://forum.opensearch.org/t/saml-not-working-failed-to-get-saml-header/8711/7. I guess this could be your use case or you prefer to use a local file instead of retrieving the information of IDP directly through the URL.

In the `config.yml` file of Wazuh indexer, I see the kibana, roles_key and exchange_key settings have a wrong identation. I am not sure if this was a problem in the posted message or the real configuration.

Review the documentation for configuring Microsoft Entra ID as SSO according to the Wazuh version you are using:
- Wazuh 4.9: https://documentation.wazuh.com/4.9/user-manual/user-administration/single-sign-on/administrator/microsoft-entra-id.html

If you are using another version, select your version from the top right version selector in the Wazuh documentation.

noah

unread,
Jan 9, 2025, 5:49:36 AM1/9/25
to Wazuh | Mailing List
Hey Antiono,

I use version 4.9.1 but I also tried this with 64 bits key with command openssl rand -hex 32  and used it but gives me the same result. And I used before metadata url and now file to see if i get different output from the logs but gives me the same result as well.

And what do you mean with this ?:  "In the `config.yml` file of Wazuh indexer, I see the kibana, roles_key and exchange_key settings have a wrong identation. I am not sure if this was a problem in the posted message or the real configuration"

can you give me an example of your config how your identation is configured?




Op donderdag 9 januari 2025 om 10:38:58 UTC+1 schreef Antonio David Gutiérrez:

Antonio David Gutiérrez

unread,
Jan 10, 2025, 6:51:44 AM1/10/25
to Wazuh | Mailing List
In the Wazuh guide to configure the Microsoft Entra ID as SSO, the configuration of Wazuh indexer has the kibana, roles_key and exchange_key are properties at the same identation level than sp: https://documentation.wazuh.com/4.9/user-manual/user-administration/single-sign-on/administrator/microsoft-entra-id.html#wazuh-indexer-configuration
Reply all
Reply to author
Forward
0 new messages