235 lines
14 KiB
Markdown
Executable File
235 lines
14 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.
|
|
- `www_dex_client_secret`: matches the website's `DEX_CLIENT_SECRET`.
|
|
- `gitea_dex_client_secret`, `discourse_dex_client_secret`,
|
|
`peertube_dex_client_secret`, `mastodon_dex_client_secret`, and
|
|
`nextcloud_dex_client_secret`: one distinct confidential-client secret per app.
|
|
|
|
The site playbook now registers all seven clients explicitly in
|
|
`dex_static_clients` and disables the Matrix convenience client to avoid a
|
|
duplicate. None of these secrets is optional unless you deliberately remove its
|
|
client from your inventory/playbook. Existing secrets must be preserved, not
|
|
regenerated on each deploy. No real secrets are included in source control.
|
|
|
|
### Application configuration required after client registration
|
|
|
|
All applications use issuer **https://dex.eom.dev/** and discovery document
|
|
**https://dex.eom.dev/.well-known/openid-configuration**, with `openid profile
|
|
email` scopes (and `groups` only when used). Configure the matching ID/secret in
|
|
each service. Client creation in Dex **does not enable SSO in the application**.
|
|
|
|
| Application | Client ID | Exact callback / prerequisite |
|
|
| --- | --- | --- |
|
|
| Matrix Auth Service | Existing `matrix_dex_oidc_client_id` | Original `https://mas.eom.dev/upstream/callback/01K96AQEZKKABW34PY3R6BVNJ4` retained |
|
|
| www | `www-membership` | `https://www.eom.dev/members/oidc/callback/` |
|
|
| Gitea | `gitea` | `https://gitea.eom.dev/user/oauth2/dex/callback`; add OpenID Connect authentication source named **dex** |
|
|
| Discourse | `discourse` | `https://discourse.eom.dev/auth/oidc/callback`; enable discourse-openid-connect and confirm callback for your installed plugin version |
|
|
| PeerTube | `peertube` | `https://peertube.eom.dev/plugins/auth-openid-connect/router/code-cb`; install/configure official auth-openid-connect plugin |
|
|
| Mastodon | `mastodon` | `https://mastodon.eom.dev/auth/auth/openid_connect/callback`; retained from its configured OIDC_REDIRECT_URI; verify installed OIDC implementation supports that route |
|
|
| Nextcloud | `nextcloud` | `https://nextcloud.eom.dev/index.php/apps/user_oidc/code`; install **user_oidc**, not the OIDC provider app or oidc_login |
|
|
|
|
Callback paths are not interchangeable. Gitea's source name affects its URL;
|
|
Nextcloud's admin screen supplies the exact callback, which can omit index.php
|
|
when URL rewriting is enabled. If using **oidc_login** instead, explicitly replace
|
|
the callback with its `/apps/oidc_login/oidc` route rather than enabling both by
|
|
guesswork. The existing Mastodon deployment points to Google; changing it to Dex
|
|
is a separate app-side migration, not another set of automatically active OIDC
|
|
environment variables. Keep a tested administrator fallback and avoid automatic
|
|
email-only account linking when migrating existing users.
|
|
|
|
The eom.dev deployment uses one `ldap` connector for legacy POSIX accounts and
|
|
website `inetOrgPerson` accounts. It retains `idAttr: uid`, so existing OIDC
|
|
subjects remain stable. The website resolves the signed UID to LDAP and anchors
|
|
its account link to immutable `entryUUID`. Its combined user filter admits
|
|
`inetOrgPerson` entries throughout the configured search base; review that
|
|
authentication scope before deployment. Each relying application must still
|
|
implement its own authorization policy.
|
|
|
|
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 explicitly includes the existing Matrix client. Its original
|
|
redirect URI is explicit in `dex_static_clients`; 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/Dex Users filter branch plus
|
|
website `inetOrgPerson` accounts, 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 using the
|
|
single existing `ldap` connector. The Secret's `WWW_DEX_CLIENT_SECRET` must match
|
|
the website's `DEX_CLIENT_SECRET`; set `DEX_CONNECTOR_ID=ldap` and the exact
|
|
matching issuer. No client or additional connector is silently enabled by
|
|
default. Verify the combined search filter and scope 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.
|