Deliver vault_op_service_account_claude to the agent hosts and install a role-owned ~multica/.local/bin/op shim that exports OP_SERVICE_ACCOUNT_TOKEN to /usr/bin/op only. op run / op plugin run get env -u spliced after "--" so the child never sees the token. The daemon unit is untouched (WDWL-18). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
82 lines
2.8 KiB
YAML
82 lines
2.8 KiB
YAML
---
|
|
# Delivers the 1Password service account token to a file only the daemon user
|
|
# can read. It deliberately stops there: nothing here puts the token into the
|
|
# daemon's environment. The daemon's systemd user unit belongs to the multica
|
|
# CLI, so the role must not edit it, and exporting the token to the daemon
|
|
# would hand it to every agent process too. See the README.
|
|
|
|
# no_log: a failed assert would otherwise render the token it inspected.
|
|
- name: 1Password token | Require a service account token
|
|
ansible.builtin.assert:
|
|
that:
|
|
- multica_op_service_account_token | length > 0
|
|
- multica_op_service_account_token is match('^ops_')
|
|
fail_msg: >-
|
|
multica_op_deliver_token is true but multica_op_service_account_token is
|
|
not a 1Password service account token (ops_...).
|
|
quiet: true
|
|
no_log: true
|
|
|
|
- name: 1Password token | Create the token directory
|
|
ansible.builtin.file:
|
|
path: "{{ multica_op_token_file | dirname }}"
|
|
state: directory
|
|
owner: "{{ multica_user }}"
|
|
group: "{{ multica_group }}"
|
|
mode: "0700"
|
|
become: true
|
|
|
|
- name: 1Password token | Write the token file
|
|
ansible.builtin.copy:
|
|
dest: "{{ multica_op_token_file }}"
|
|
content: "{{ multica_op_service_account_token }}\n"
|
|
owner: "{{ multica_user }}"
|
|
group: "{{ multica_group }}"
|
|
mode: "0600"
|
|
no_log: true
|
|
become: true
|
|
|
|
# --- op shim -----------------------------------------------------------------
|
|
# `op` reads the token only from OP_SERVICE_ACCOUNT_TOKEN. The shim, first on
|
|
# the daemon unit's PATH, exports it for the real binary alone, so agents call
|
|
# plain `op` and the token never enters their shell environment. The daemon
|
|
# unit itself stays the CLI's (WDWL-18).
|
|
|
|
- name: 1Password token | Create the daemon user's bin directory
|
|
ansible.builtin.file:
|
|
path: "{{ multica_op_shim_path | dirname }}"
|
|
state: directory
|
|
owner: "{{ multica_user }}"
|
|
group: "{{ multica_group }}"
|
|
mode: "0755"
|
|
become: true
|
|
when: multica_op_shim | bool
|
|
|
|
- name: 1Password token | Install the op shim
|
|
ansible.builtin.template:
|
|
src: op-shim.sh.j2
|
|
dest: "{{ multica_op_shim_path }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
become: true
|
|
when: multica_op_shim | bool
|
|
|
|
# As the daemon user, through its own environment: plain `op` must resolve to
|
|
# the shim, and the token must not be in that environment.
|
|
- name: 1Password token | Check op resolves to the shim as the daemon user
|
|
ansible.builtin.shell:
|
|
cmd: 'command -v op; env | grep -c "^OP_SERVICE_ACCOUNT_TOKEN=" || true'
|
|
become: true
|
|
become_user: "{{ multica_user }}"
|
|
environment: "{{ _multica_user_env }}"
|
|
register: _multica_op_shim_check
|
|
changed_when: false
|
|
check_mode: false
|
|
failed_when: >-
|
|
_multica_op_shim_check.rc != 0
|
|
or _multica_op_shim_check.stdout_lines != [multica_op_shim_path, '0']
|
|
when:
|
|
- multica_op_shim | bool
|
|
- not ansible_check_mode
|