--- # Deploy and configure HashiCorp Vault CE on TrueNAS Scale. # # Vault is deployed as a TrueNAS custom app (Docker Compose). # This playbook handles post-deploy configuration only — it does NOT install Vault. # See: docs/ for the TrueNAS compose YAML and vault.hcl required before running. # # Prerequisites: # - Vault running on TrueNAS and accessible at vault_url # - vault host/group in inventory with vault_url and vault_oidc_issuer set # # Keycloak OIDC prerequisites (--tags vault_configure_keycloak,vault_configure_oidc): # - Keycloak realm exists (configured via deploy_openshift.yml) # - vault_vault_oidc_client_secret in 1Password (or it will be generated and displayed) # - In host_vars for the vault host: # vault_url: "http://nas.lan.toal.ca:8200" # vault_oidc_issuer: "https://keycloak.apps../realms/" # # Play order: # Play 0: vault_configure_keycloak — Create Keycloak OIDC client for Vault # Play 1: vault_init — Initialize Vault, display keys for 1Password # Play 2: (default) — Unseal + configure OIDC authentication # # Usage: # ansible-navigator run playbooks/deploy_vault.yml --tags vault_configure_keycloak # ansible-navigator run playbooks/deploy_vault.yml --tags vault_init # ansible-navigator run playbooks/deploy_vault.yml # ansible-navigator run playbooks/deploy_vault.yml --tags vault_configure_keycloak,vault_init # --------------------------------------------------------------------------- # Play 0: Create Keycloak OIDC client for Vault (optional) # Runs on openshift hosts to access keycloak_url/keycloak_realm host vars. # Creates the OIDC client in Keycloak with the correct Vault callback URIs. # --------------------------------------------------------------------------- - name: Configure Keycloak OIDC client for Vault hosts: openshift gather_facts: false connection: local tags: - never - vault_configure_keycloak vars: __vault_keycloak_api_url: "{{ keycloak_url }}{{ keycloak_context | default('') }}" __vault_oidc_client_id: "{{ vault_oidc_client_id | default('vault') }}" __vault_url: "{{ hostvars[groups['vault'][0]]['vault_url'] | default('http://nas.lan.toal.ca:8200') }}" module_defaults: middleware_automation.keycloak.keycloak_client: auth_client_id: admin-cli auth_keycloak_url: "{{ __vault_keycloak_api_url }}" auth_realm: master auth_username: "{{ keycloak_admin_user }}" auth_password: "{{ vault_keycloak_admin_password }}" validate_certs: "{{ keycloak_validate_certs | default(true) }}" tasks: - name: Set Vault OIDC client secret (vault value or generated) ansible.builtin.set_fact: __vault_oidc_client_secret: "{{ vault_vault_oidc_client_secret | default(lookup('community.general.random_string', length=32, special=false)) }}" __vault_oidc_secret_generated: "{{ vault_vault_oidc_client_secret is not defined }}" no_log: true - name: Create Vault OIDC client in Keycloak middleware_automation.keycloak.keycloak_client: realm: "{{ keycloak_realm }}" client_id: "{{ __vault_oidc_client_id }}" name: "HashiCorp Vault" description: "OIDC client for Vault on TrueNAS" enabled: true protocol: openid-connect public_client: false standard_flow_enabled: true implicit_flow_enabled: false direct_access_grants_enabled: false service_accounts_enabled: false secret: "{{ __vault_oidc_client_secret }}" redirect_uris: - "{{ __vault_url }}/ui/vault/auth/oidc/oidc/callback" - "http://localhost:8250/oidc/callback" web_origins: - "+" protocol_mappers: - name: groups protocol: openid-connect protocolMapper: oidc-group-membership-mapper config: full.path: "false" id.token.claim: "true" access.token.claim: "true" userinfo.token.claim: "true" claim.name: groups state: present no_log: "{{ keycloak_no_log | default(true) }}" - name: Display generated client secret (save this to vault!) ansible.builtin.debug: msg: - "*** GENERATED VAULT OIDC CLIENT SECRET — SAVE THIS TO 1PASSWORD ***" - "vault_vault_oidc_client_secret: {{ __vault_oidc_client_secret }}" - "" - "Save to 1Password and reference as vault_vault_oidc_client_secret." when: __vault_oidc_secret_generated | bool - name: Display Keycloak Vault OIDC configuration summary ansible.builtin.debug: msg: - "Keycloak Vault OIDC client configured:" - " Realm : {{ keycloak_realm }}" - " Client : {{ __vault_oidc_client_id }}" - " Issuer : {{ __vault_keycloak_api_url }}/realms/{{ keycloak_realm }}" - "" - "Set in host_vars for the vault host:" - " vault_oidc_issuer: {{ __vault_keycloak_api_url }}/realms/{{ keycloak_realm }}" - "" - "Then run: --tags vault_init (if not done) then the default play." verbosity: 1 # --------------------------------------------------------------------------- # Play 1: Initialize Vault (optional, one-time) # Initializes Vault and displays root token + unseal keys for saving to 1Password. # Fails after init intentionally — save credentials then run the default play. # --------------------------------------------------------------------------- - name: Initialize Vault hosts: vault gather_facts: false connection: local tags: - never - vault_init tasks: - name: Run Vault init tasks ansible.builtin.include_role: name: vault_setup tasks_from: init.yml # --------------------------------------------------------------------------- # Play 2: Unseal and configure Vault OIDC authentication (default) # Requires vault_vault_root_token and vault_vault_oidc_client_secret in 1Password. # Optionally unseals if vault_unseal_keys is provided and Vault is sealed. # --------------------------------------------------------------------------- - name: Configure Vault OIDC authentication hosts: vault gather_facts: false connection: local roles: - role: vault_setup