# wazuh-sso-rbac

Companion files for the lesson **Wazuh SSO and RBAC with Entra ID, Okta and Keycloak**:
<https://maheshtata.com/wazuh/wazuh-sso-rbac/>

Tested against: Wazuh 5.0 (beta5 documentation, Sep 2026), Ubuntu 24.04.
Not yet validated in a lab; treat every value as a starting point.

## Files

| File | What it is |
| --- | --- |
| `config.saml.yml` | Partial `authc` section for SAML, with the internal password login kept working behind it. Entra ID and Okta annotated inline. |
| `config.ldap.yml` | Partial `authc` and `authz` sections for Active Directory or LDAP over LDAPS. |
| `roles_mapping.fragment.yml` | Three mappings: administrators, read-only viewers, analysts. One identity-provider group per role. |
| `role-readonly.json` | The documented read-only recipe as a Security API body. |
| `role-analyst.json` | A duplicate-and-edit analyst role built from the shapes Wazuh already ships. |

All five are **fragments**. Merge them; do not replace the files they belong to.

## Order of operations

1. Back up the security directory:

   ```bash
   /usr/share/wazuh-indexer/bin/indexer-security-init.sh \
     --options "-backup /etc/wazuh-indexer/opensearch-security -icl -nhnv"
   ```

2. Configure the application and the group or app role on the identity
   provider side. Note the metadata URL and the issuer or identifier.
3. Generate the signing key: `openssl rand -hex 32` (at least 64 characters).
4. Merge `config.saml.yml` (or `config.ldap.yml`) into `config.yml` and load
   it with `securityadmin.sh`.
5. Create the roles from `role-readonly.json` and `role-analyst.json`.
6. Merge `roles_mapping.fragment.yml` into `roles_mapping.yml` and load it.
7. On the dashboard node, set `opensearch_security.auth.multiple_auth_enabled`,
   `opensearch_security.auth.type` and `server.xsrf.allowlist`, and confirm
   `run_as: true` under `wazuh_core.hosts`.
8. Create the matching Wazuh role mapping under
   **Server management > Security > Roles mapping**.
9. Restart `wazuh-dashboard`, clear browser cache and cookies, and test.

Every `securityadmin.sh` invocation is written out in the header comment of
the file it applies to.

## Break glass, before you need it

Three layers. Test all three on a lab cluster before enabling SSO in
production.

1. **The internal basic domain**, left at `order: 0` with `challenge: false`.
   `config.saml.yml` keeps it deliberately. Removing it removes your password
   login.
2. **A rotated internal administrator.** The bundled password hashes are
   documented as being for demo purposes, and nothing rotates them during
   installation. Change them immediately:

   ```bash
   bash wazuh-passwords-tool.sh -u admin -p <NEW_PASSWORD>
   ```

   The password needs 8 to 64 characters with at least one uppercase letter,
   one lowercase letter, one number and one of `.*+?-`. In a distributed
   deployment run it on any indexer node for indexer users, and on the manager
   master node with `-A -au <ADMIN_USER> -ap <ADMIN_PASSWORD>` for manager API
   users.
3. **The admin certificate.** `securityadmin.sh` authenticates with
   `admin.pem` and `admin-key.pem`, which still works when the security index
   itself is wrong. Store them as a root-level credential.

## Two constraints that catch people out

- **One identity-provider group per role.** The documentation states that each
  group generated in the identity provider can only be used as one backend
  role. Administrator and read-only access need two groups.
- **Case sensitivity.** OpenSearch and the SAML assertion are case-sensitive,
  so the value on the provider and the value in the indexer configuration must
  match exactly.

## One action to withhold from every role

`agent:read_secrets` on the manager API reads the agents' pre-shared keys from
`client.keys` in clear. It is not in any file here, and it should not be in any
role you create.
