Files
ansible-role-dex/README.md
T
2026-10-23 18:15:49 -04:00

195 lines
12 KiB
Markdown
Executable File

# ansible-role-dex
Dedicated Kubernetes/Helm role extracted from ansible-role-eom's Dex task.
Deploys Dex with local **Catppuccin Mocha / Latte** styles and an **eom.dev**
wordmark, retaining Dex's shipped authentication and consent templates.
## Generic defaults and eom.dev workflow
Role defaults now use example domains/DNs, blank credentials, a 10Gi optional
database request, no implicit Matrix client and disabled eom.dev branding.
Plaintext LDAP remains the default as requested; TLS remains opt-in.
Use [playbooks/deploy-eom.yml](playbooks/deploy-eom.yml) for the actual eom.dev
deployment. It calls this role and explicitly preserves the existing issuer,
namespace/releases, database settings/256Gi sizing, plaintext LDAP host, legacy
POSIX/group filter, `uid` subject mapping, Matrix callback, and Catppuccin logo.
Provide these existing variables through controller inventory/group_vars or an
Ansible Vault-encrypted vars file:
- `dex_admin_password`: existing Dex PostgreSQL password.
- `openldap_readonly_password`: existing LDAP search-account password.
- `matrix_dex_oidc_client_id` and `matrix_dex_oidc_client_secret`: existing MAS client.
- `postgresql_admin_password`: needed only if deliberately enabling DB management.
- Optional `www_dex_client_secret`: enables the website client and its separate
`www-ldap`/`entryUUID` connector, without changing legacy identities. It must
match the website's `DEX_CLIENT_SECRET`. Leave absent to preserve Matrix-only
behavior. Review and declare any other deployed clients before rollout.
Run the playbook on the controller with its kubeconfig and this role available
in `ANSIBLE_ROLES_PATH`. Load your encrypted variables with Ansible's `--extra-vars`
file option and `--ask-vault-pass` or your existing Vault identity configuration;
do not put plaintext credentials in this playbook or pass them on command lines.
This is an Ansible playbook, not a CI provider workflow, and is not automatically
triggered. The old EOM compatibility entry now uses generic defaults unless you
explicitly pass these site settings; prefer the site playbook for migration.
## Migration from ansible-role-eom
1. Back up the Dex PostgreSQL database and record the installed Dex/PostgreSQL
Helm release versions and current values in a secure location. Values contain
credentials; do not paste them into tickets, chat or unencrypted git files.
2. Install this role under `ansible-role-dex` in your controller's role search
path. Install [requirements.yml](requirements.yml) and the Kubernetes Python
client; Helm 3 and an authorized kubeconfig are required. Tested with Ansible
Core 2.18; role metadata minimum is 2.15.
3. Use the site workflow above or invoke `ansible-role-dex` with explicit site
variables in the existing playbook. The old
`ansible-role-eom/tasks/dex.yaml` is now a thin `include_role` compatibility
entry point. Use one entry point, not both. No global eom dependency was
added: its current main task only deploys Monero and remains unchanged.
4. Keep namespace `dex`, release `dex`, issuer **https://dex.eom.dev/** (including
trailing slash), database host `postgresql`, user/database `dex` and existing
credentials. A role extraction must not change OIDC issuer or existing client
secrets/redirect URIs, connector IDs or user-ID mappings.
5. Review the pinned Dex chart `0.26.0` (app `v2.46.0`) against your installed
release **before applying**. Override `dex_chart_version` and optionally
`dex_image_tag` if staging a different supported release. This role does not
discover/guess the installed version or perform a live migration by itself.
6. PostgreSQL management defaults to **false**: the existing release and PVC are
left untouched. Do not uninstall the old release or delete its volumes.
The extracted config corrects the old `databbase` typo to `database: dex`.
The site playbook maps legacy inventory variables explicitly:
| Old inventory variable | New role variable |
| --- | --- |
| `dex_admin_password` | `dex_postgres_password` (DB password, not a Dex UI admin) |
| `postgresql_admin_password` | `dex_postgres_admin_password` |
| `openldap_readonly_password` | `dex_ldap_bind_password` |
| `matrix_dex_oidc_client_id` / `matrix_dex_oidc_client_secret` | Existing Matrix Auth Service client |
The site playbook enables the existing Matrix client. Its original
redirect URI is explicit in `dex_matrix_redirect_uris`; override to match your
actual MAS configuration. Other clients previously added directly to Helm must
be declared in `dex_static_clients` before running this role. Helm values are
reset to this role's complete values: undeclared manual Helm customizations are
not implicitly preserved. The role's authoritative values must be reviewed.
## Main variables
See [defaults/main.yml](defaults/main.yml) for all options.
| Variable | Default / behavior |
| --- | --- |
| `dex_namespace`, `dex_release_name` | `dex`, `dex` |
| `dex_chart_version` | `0.26.0` (explicit, reviewed release) |
| `dex_issuer`, `dex_hostname` | `https://{{ dex_hostname }}/`, `dex.example.com` |
| `dex_ingress_class`, `dex_cluster_issuer` | `nginx`, `letsencrypt-prod` |
| `dex_theme_enabled`, `dex_brand_name` | false, `Dex` (site playbook enables eom.dev theme) |
| `dex_static_clients` | Additional Dex static client objects; default empty |
| `dex_additional_connectors` | Additional complete connector objects; default empty |
| `dex_env_secret_name` | Optional existing environment Secret in Dex namespace |
| `dex_ca_secret_name` | Optional existing CA Secret mounted at `/etc/dex-ca` |
| `dex_postgres_manage` | false; reuse existing DB without changing its release |
| `dex_postgres_ssl_mode` | `disable`, preserving internal DB behavior |
| `dex_image_pull_secrets` | Kubernetes imagePullSecrets list |
| `dex_extra_volumes`, `dex_extra_volume_mounts` | Optional additional mounts |
### LDAP: plaintext is the default, TLS is opt-in
As requested, default LDAP behavior remains `insecureNoSSL: true` against
`ldap.example.com:389` (the site playbook uses
`openldap.openldap.svc.cluster.local`). This exposes both service-bind and user
passwords to network observers. Restrict it to the trusted internal network with
your cluster's policies; no public LDAP exposure is created by this role.
The generic connector uses `inetOrgPerson` and DN-based group matching. The site
playbook retains ID `ldap`, `idAttr: uid`, its POSIX/group filter,
and `userAttr: cn` group matching. For `uniqueMember` values containing full DNs,
set `dex_ldap_group_user_attribute: DN` deliberately after testing. Changing
connector ID or idAttr changes OIDC subjects and can detach existing accounts.
For **StartTLS**, explicitly set `dex_ldap_insecure_no_ssl: false`,
`dex_ldap_start_tls: true`, and a host/port supporting StartTLS. For **LDAPS**,
set both flags false and use the server's TLS hostname with port 636. Certificate
verification remains enabled; no `insecureSkipVerify` bypass is offered. For a
private CA set `dex_ca_secret_name` and `dex_ldap_root_ca` to
`/etc/dex-ca/<secret-key>`. Verify certificate hostname, validity, SHA-2 signature,
strong keys and CA trust independently. Additional connectors have their own
transport settings and must be configured separately.
### Credentials and clients
Supply database and LDAP passwords from Vault/external lookups or the supported
legacy secret variables. Helm deployment and validation tasks are `no_log` and
diff-suppressed. Dex configuration is stored by the official chart in a Kubernetes
**Secret**, never in the theme ConfigMap. Helm stores release values, including
inline credentials, in its release Secrets: protect these with RBAC, encryption
at rest and encrypted backups. This role does not generate or rotate passwords.
Client `secretEnv` can refer to a key in `dex_env_secret_name`. LDAP connectors
support `$ENV_NAME` references, such as `bindPW: $DEX_LDAP_BIND_PASSWORD`. The
database password remains a protected Helm/Dex config value; it is not assumed
to support the same connector substitution. Never commit actual secrets.
[tests/example-vars.yml](tests/example-vars.yml) shows a www client and separate
`www-ldap` connector using `entryUUID`, `inetOrgPerson` and DN group matching.
This avoids breaking legacy subjects while supporting new free website users.
The Secret's `WWW_DEX_CLIENT_SECRET` must match the website's `DEX_CLIENT_SECRET`;
set the website's `DEX_CONNECTOR_ID=www-ldap` and exact matching issuer. No new
client or connector is silently enabled by default. Verify that this connector's
search base includes the website account OU before enabling public registration.
### Theme
[files/styles.css](files/styles.css) implements responsive Mocha dark mode and
Latte light mode using `prefers-color-scheme`, visible focus rings, local fonts,
inputs, errors, connector buttons and consent panels. [files/logo.svg](files/logo.svg)
extends the website's orbit mark into an eom.dev wordmark.
Only `themes/light/styles.css` and `themes/light/logo.svg` are mounted read-only
under the official image's `/srv/dex/web`; frontend selects that directory and
`theme/logo.svg`. All other version-matched templates, icons and static assets
come from the installed Dex image. No forms, OAuth parameters, redirects or
approval/security logic are replaced. This deliberately retains the shipped
favicon; logo/theme are local, with no third-party fonts or scripts.
A checksum of public theme assets triggers a rollout when they change (subPath
mounts do not hot-reload). Setting `dex_theme_enabled: false` restores Dex's
default frontend; the unused ConfigMap is retained. Existing environment Secret
or CA Secret rotations require a Dex rollout; the role does not expose or hash
their contents. Inspect log privacy at any upstream proxies too: ingress access
logs are disabled to avoid recording authorization codes and related URLs.
### Optional PostgreSQL management
For a new install or an explicitly reviewed DB upgrade, set
`dex_postgres_manage: true` and **pin `dex_postgres_chart_version`** to the intended
Bitnami release. Defaults retain release `postgresql`, 256Gi and `volumeName: data`
from the old task. Confirm existing PV/PVC binding, storage size, chart/image
availability and schema compatibility first; do not use this to switch major
database versions without a backup/restore plan. Changing Helm password values
does not automatically rotate an existing database password. Managed DB transport
is unchanged; configure external DB TLS/mesh separately if required.
## Validation
[tests/Dockerfile](tests/Dockerfile) installs the declared collection and Helm,
checks Ansible syntax, renders actual values and runs the pinned chart through
Helm and strict Kubernetes schemas. Fixtures verify legacy plaintext/subjects,
Matrix client, additional environment client, opt-in TLS, theme mounts, protected
Dex config and disabled/minimal variants. No cluster is contacted by these tests.
The theme was also exercised with the official Dex v2.46.0 image using isolated
SQLite/mock authentication. Verify real LDAP, client redirects and database
access in staging before rollout. Chart upgrades should repeat that image/theme
compatibility test. No production deployments or database changes are performed
as part of this extraction.
The editor's scanner flags high-severity findings in the validation runner's
upstream Python base image. That image is test-only and is not deployed by this
role. Review/update approved CI base-image digests with your image scanner;
these findings are not represented as resolved by the functional tests.