Wazuh & Keycloak using SAML


Use case:

Set up Keycloak for Authentication using SAML protocol in Wazuh.

Keycloak configuration:

  • Create a new client with the protocol set to saml :
  • Configure it to use the below options:
  • Add a role naming it Administrator:
  • Add a Role listmapper:
  • Navigate to Installation to generate the IDP and SP metadata files:
  • The idp.entity_id & exchange_keys are included in the idp-metadata.xml file:

Wazuh indexer configuration:

  • Place the content of idp-metadata.xml & sp-metadata.xml respectively within /etc/wazuh-indexer/certs/idp_metadata.xml & /etc/wazuh-indexer/certs/sp_metadata.xml setting the ownership to wazuh-indexer :
chown wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/certs/sp_metadata.xml
chown wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/certs/idp_metadata.xml
  • Configure the Wazuh indexer to use SAML by modifying /usr/share/wazuh-indexer/plugins/opensearch-security/securityconfig/config.yml :
---
_meta:
  type: "config"
  config_version: 2

config:
  dynamic:
    http:
      anonymous_auth_enabled: false
    authc:
      internal_auth:
        order: 0
        description: "HTTP basic authentication using the internal user database"
        http_enabled: true
        transport_enabled: true
        http_authenticator:
          type: basic
          challenge: false
        authentication_backend:
          type: internal
      saml_auth:
        order: 1
        description: "SAML provider"
        http_enabled: true
        transport_enabled: false
        http_authenticator:
          type: saml
          challenge: true
          config:
            idp:
              metadata_file: /etc/wazuh-indexer/certs/idp_metadata.xml
              entity_id: http://192.168.0.92:8080/realms/master
            sp:
              entity_id: WazuhSAMLID
              metadata_file: /etc/wazuh-indexer/certs/sp_metadata.xml
            kibana_url: https://192.168.0.144/
            roles_key: Roles
            exchange_key: 'MIICmzCCAYMCBgGEcsVHGzANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZtYXN0ZXIwHhcNMjIxMTEzMjA1MjIyWhcNMzIxMTEzMjA1NDAyWjARMQ8wDQYDVQQDDAZtYXN0ZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCPyuaYpgSOSiLFpj6u+TgGTEqspH/iBfBkHOwkEHlHXqkjLLZzzWMNxnzKxU/rjwpuxX6tNP0NQzzLe97Cq4hB9BLixcUJwzBdnlSDr3yI/kASSojqllPcrx94CTs6hMUC5RU6wNanAD5wu1OkI9DPUjN+0/3QCbVGDMjCzgT6u6PkRe9m9kg1Gp6MpdVmmfn8sVdp9HycbZM6gRCL0EU5DZubjHwO+QGmjZRCGmIAenuoTUDttCLC/TzzxeZ8dMHiUohiQYKtkavRLuhuqdCgHXASvE89BY9pv626TivUb3wx/LV9E4qeLb0LMmUSDtVH28M71cmaKClAOnZR0QUlAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADi/ylzDpO1c8HODIIKPzFi6wsbGYyiGzHwZQTFvb6mXBUCpgoRk10RMshlyvWu27MtvYl3ot6ayPxwcJfCFf0KNladmPCR/3cKUvGEr/2AuXbXXoJSniua/LGTHp42D8B1xVOP5v8dvKPar50KK2BXhbvRZqbyemZ7MXb6P6hPZz2cYdjAcN48Zq4obNznUqd46hcHqDHtzVxIXlgpeA1B2QbUR3NdxsVWT8hcoh6xfNxh1RpNmWRGMsnHkFovJOvs1QCgrEjQzf1x+6m7JF+BNI7B3EZoTuft9TsiqppTBzUkTp6B0/FMkfy2OeLcUitag3JbPmkvY2rTAkGBrpnI='
        authentication_backend:
          type: noop
  • Load the new security configuration:
export JAVA_HOME=/usr/share/wazuh-indexer/jdk &&  /usr/share/wazuh-indexer/plugins/opensearch-security/tools/securityadmin.sh -cd /usr/share/wazuh-indexer/plugins/opensearch-security/securityconfig/ -icl -key /etc/wazuh-indexer/certs/admin-key.pem -cert /etc/wazuh-indexer/certs/admin.pem -cacert /etc/wazuh-indexer/certs/root-ca.pem -h localhost -nhnv

Wazuh Dashboard configuration:

  • Set the authentication to saml by adding below to /etc/wazuh-dashboard/opensearch_dashboards.yml :
opensearch_security.auth.type: "saml"
server.xsrf.whitelist: ["/_opendistro/_security/saml/acs", "/_opendistro/_security/saml/acs/idpinitiated", "/_opendistro/_security/saml/logout"]

As this might be solved in future versions you should perform the next step only if you are facing logout issue (https://forum.opensearch.org/t/saml-issue-on-logout/5617/14).

  • Modify the logout endpoint in /usr/share/wazuh-dashboard/plugins/securityDashboards/server/auth/types/saml/routes.js by changing it from /auth/logout to /logout:
    this.router.get({
      path: `/logout`,
      validate: false
    }, async (context, request, response) => {
      try {
        const authInfo = await this.securityClient.authinfo(request);
        this.sessionStorageFactory.asScoped(request).clear(); // TODO: need a default logout page

        const redirectUrl = authInfo.sso_logout_url || this.coreSetup.http.basePath.serverBasePath || '/';
        return response.redirected({
          headers: {
            location: redirectUrl
          }
        });
      } catch (error) {
        context.security_plugin.logger.error(`SAML logout failed: ${error}`);
        return response.badRequest();
      }
    });
  }

}

exports.SamlAuthRoutes = SamlAuthRoutes;
  • Restart Wazuh dashboard: systemctl restart wazuh-dashboard

DEMO:

I hope you find it useful 🙂


Leave a Reply

Your email address will not be published. Required fields are marked *