mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-11 13:17:07 +00:00
Keycloak stores the permanent admin's password in its own database. When the inventory value rotates, the next deploy renders a credential that authenticates against nothing, and the role cannot reach the instance it just restarted. The bootstrap account is no way back either: Keycloak writes KC_BOOTSTRAP_ADMIN_* once, on an empty database, and upstream states it is meant to be removed once a permanent admin exists. The role now keeps the credential its predecessor used. Before sys-stk-full re-renders the environment file with force: true, utils/capture_previous_admin.yml reads KEYCLOAK_PERMANENT_ADMIN_PASSWORD out of the copy still on disk. When the login after the restart is refused, utils/converge_previous_admin.yml signs in with that captured value and moves the account onto the newly rendered one, which the restarted container already carries in its environment. The bootstrap fallback stays what its name says: the path for an instance that has never been deployed. A host with no previous file captures nothing and goes straight there. Reading the file back needs the inverse of dotenv_quote, which did not exist. dotenv_unquote switches on the same DEPLOYMENT_MODE as the forward direction, so a value written in compose is unescaped and a value written in swarm is taken verbatim; dotenv_value pulls one assignment's raw right-hand side out of the rendered text. The password never reaches argv: the convergence login passes it through container exec -e plus the task's environment:. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Custom Filter Plugins for Infinito.Nexus
This directory contains custom Ansible filter plugins used within the Infinito.Nexus project.
When to Use a Filter Plugin
- Transform values: Use filters to transform, extract, reformat, or compute values from existing variables or facts.
- Inline data manipulation: Filters are designed for inline use in Jinja2 expressions (in templates, tasks, vars, etc.).
- No external lookups: Filters only operate on data you explicitly pass to them and cannot access external files, the Ansible inventory, or runtime context.
Examples
{{ role_name | entity_name }}
{{ my_list | unique }}
{{ user_email | regex_replace('^(.+)@.*$', '\\1') }}
When not to Use a Filter Plugin
- If you need to load data from an external source (e.g., file, environment, API), use a lookup plugin instead.
- If your logic requires access to inventory, facts, or host-level information that is not passed as a parameter.
Schema 🗺️
How csp_filters.py assembles one application's Content-Security-Policy. Scope is the header build, not the other filters in this directory.
flowchart TD
decl["meta/csp.yml<br/>whitelist, flags, hashes"]
svc["meta/services.yml<br/>services.logout.enabled"]
flags["csp_filters.py:136<br/>get_csp_flags"]
grant["csp_filters.py:354<br/>logout grant"]
wl["csp_filters.py:123<br/>get_csp_whitelist"]
inj["sys-front-inj-dashboard,<br/>-javascript, -matomo, -logout<br/>add_csp_hash"]
gate["csp_filters.py:365<br/>hash gate"]
build["csp_filters.py:203<br/>build_csp_header"]
header["set $csp<br/>nginx vhost"]
decl -->|"1. flags read by"| flags
flags -->|"2. tokens"| build
svc -->|"3. read by"| grant
grant -->|"4. adds 'unsafe-inline'<br/>to script-src-elem and -attr"| build
decl -->|"5. whitelist read by"| wl
wl -->|"6. tokens"| build
inj -->|"7. snippets"| gate
gate -->|"8. hashes, only when<br/>'unsafe-inline' is absent"| build
build -->|"9. joined string"| header
grant -.->|"TRIP-WIRE: the token it adds<br/>closes the gate below, so every<br/>registered hash is discarded"| gate
svc -.->|"TRIP-WIRE: the flag derives from<br/>group_names, so the script policy<br/>follows the round, not the app"| grant
grant -.->|"TRIP-WIRE: absent from the<br/>smart-defaults docstring, which<br/>names logout only for frame-ancestors"| build
Styles carry 'unsafe-inline' by default; scripts do not. The logout grant is the only path that puts it into a script directive.