From f7c25a0ed2f2c7e92e25dd7f6f1081e96874039e Mon Sep 17 00:00:00 2001 From: Menno van Leeuwen Date: Tue, 11 Mar 2025 21:09:47 +0100 Subject: [PATCH] refactor: update 1Password lookup syntax for consistency and clarity --- config/ansible/plugins/lookup/onepassword.py | 97 +++++-------------- .../services/golink/docker-compose.yml.j2 | 2 +- .../tasks/servers/services/hoarder/dotenv.j2 | 6 +- .../tasks/servers/services/services.yml | 2 +- .../ansible/tests/test-onepassword-lookup.yml | 11 +-- 5 files changed, 34 insertions(+), 84 deletions(-) diff --git a/config/ansible/plugins/lookup/onepassword.py b/config/ansible/plugins/lookup/onepassword.py index 7464082..a306cd9 100644 --- a/config/ansible/plugins/lookup/onepassword.py +++ b/config/ansible/plugins/lookup/onepassword.py @@ -7,39 +7,25 @@ DOCUMENTATION = """ version_added: "1.0" short_description: fetch secrets from 1Password description: - - Uses the 1Password CLI to fetch secrets from 1Password + - Uses the 1Password CLI to fetch secrets from 1Password using the op read command options: - item: - description: the item to fetch - required: false - field: - description: the field to fetch from the item - required: false - default: password - vault: - description: the vault to fetch from (name or ID) - required: false - reveal: - description: whether to reveal concealed fields - required: false - default: true - ref: - description: full 1Password reference (op://vault/item/field) - required: false + _terms: + description: 1Password reference string (op://vault/item/field) + required: true """ EXAMPLES = """ -- name: fetch password for an item +- name: fetch password using 1Password reference debug: - msg: "{{ lookup('onepassword', 'xxxx', field='password') }}" + msg: "{{ lookup('onepassword', 'op://vault/item/password') }}" -- name: fetch password from specific vault +- name: fetch username from item debug: - msg: "{{ lookup('onepassword', 'xxxx', field='password', vault='xxxx') }}" + msg: "{{ lookup('onepassword', 'op://vault/item/username') }}" -- name: fetch using full reference +- name: fetch custom field debug: - msg: "{{ lookup('onepassword', ref='op://vault/item/field') }}" + msg: "{{ lookup('onepassword', 'op://vault/item/custom_field') }}" """ RETURN = """ @@ -56,72 +42,37 @@ display = Display() class LookupModule(LookupBase): def run(self, terms, variables=None, **kwargs): - ref = kwargs.get('ref') + result = [] - if ref: - # If ref is provided, use op read command - cmd = ['op', 'read', ref] - display.vvv(f"Executing command with reference: {' '.join(cmd)}") + for term in terms: + if not term.startswith('op://'): + raise AnsibleError(f"1Password reference must start with 'op://', got: {term}") + + cmd = ['op', 'read', term] + display.vvv(f"Executing command: {' '.join(cmd)}") try: - result = subprocess.run( + process = subprocess.run( cmd, capture_output=True, text=True, check=True ) - output = result.stdout.strip() - display.vvv(f"1Password output for ref '{ref}': '{output}'") + output = process.stdout.strip() + display.vvv(f"1Password output for '{term}': '{output}'") if not output: - display.warning(f"1Password returned empty output for ref '{ref}'") + display.warning(f"1Password returned empty output for '{term}'") - return [output] + result.append(output) except subprocess.CalledProcessError as e: error_msg = e.stderr.strip() display.warning(f"Error executing 1Password CLI: {error_msg}") display.warning(f"Command used: {' '.join(cmd)}") if "not found" in error_msg: - return [f"Secret referenced by '{ref}' not found in 1Password"] + raise AnsibleError(f"Secret referenced by '{term}' not found in 1Password") raise AnsibleError(f"Error fetching from 1Password: {error_msg}") - # If no ref is provided, fall back to the original behavior - if len(terms) != 1: - raise AnsibleError("onepassword lookup expects exactly one argument when not using ref parameter") - - item = terms[0] - field = kwargs.get('field', 'password') - vault = kwargs.get('vault', '') - reveal = kwargs.get('reveal', True) - - cmd = ['op', 'item', 'get', item, '--field', field] - - # Add vault parameter if specified - if vault: - cmd.extend(['--vault', vault]) - - # Add reveal flag for concealed fields - if reveal and field.lower() in ['password', 'secret', 'token', 'key']: - cmd.append('--reveal') - - display.vvv(f"Executing command: {' '.join(cmd)}") - - try: - result = subprocess.run( - cmd, - capture_output=True, - text=True, - check=True - ) - return [result.stdout.strip()] - except subprocess.CalledProcessError as e: - error_msg = e.stderr.strip() - display.warning(f"Error executing 1Password CLI: {error_msg}") - display.warning(f"Command used: {' '.join(cmd)}") - - if "not found" in error_msg: - return [f"Secret '{item}' not found in 1Password"] - - raise AnsibleError(f"Error fetching from 1Password: {error_msg}") + return result diff --git a/config/ansible/tasks/servers/services/golink/docker-compose.yml.j2 b/config/ansible/tasks/servers/services/golink/docker-compose.yml.j2 index 340d699..5e05d5d 100644 --- a/config/ansible/tasks/servers/services/golink/docker-compose.yml.j2 +++ b/config/ansible/tasks/servers/services/golink/docker-compose.yml.j2 @@ -4,7 +4,7 @@ services: image: ghcr.io/tailscale/golink:main user: root environment: - - TS_AUTHKEY={{ lookup('onepassword', '4gsgavajnxfpcrjvbkqhoc4drm', field='TS_AUTHKEY', vault='j7nmhqlsjmp2r6umly5t75hzb4') }} + - TS_AUTHKEY={{ lookup('onepassword', "op://j7nmhqlsjmp2r6umly5t75hzb4/GoLink/TS_AUTHKEY") }} volumes: - {{ golink_data_dir }}:/home/nonroot restart: "unless-stopped" diff --git a/config/ansible/tasks/servers/services/hoarder/dotenv.j2 b/config/ansible/tasks/servers/services/hoarder/dotenv.j2 index 123c5d9..68dde83 100644 --- a/config/ansible/tasks/servers/services/hoarder/dotenv.j2 +++ b/config/ansible/tasks/servers/services/hoarder/dotenv.j2 @@ -7,6 +7,6 @@ NEXTAUTH_URL=http://localhost:3000 DATA_DIR=/data -NEXTAUTH_SECRET="{{ lookup('onepassword', ref='op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/NEXTAUTH_SECRET') }}" -MEILI_MASTER_KEY="{{ lookup('onepassword', ref='op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/MEILI_MASTER_KEY') }}" -OPENAI_API_KEY="{{ lookup('onepassword', ref='op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/OPENAI_API_KEY') }}" +NEXTAUTH_SECRET="{{ lookup('onepassword', 'op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/NEXTAUTH_SECRET') }}" +MEILI_MASTER_KEY="{{ lookup('onepassword', 'op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/MEILI_MASTER_KEY') }}" +OPENAI_API_KEY="{{ lookup('onepassword', 'op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/OPENAI_API_KEY') }}" diff --git a/config/ansible/tasks/servers/services/services.yml b/config/ansible/tasks/servers/services/services.yml index 44b90ac..8868159 100644 --- a/config/ansible/tasks/servers/services/services.yml +++ b/config/ansible/tasks/servers/services/services.yml @@ -8,4 +8,4 @@ when: hoarder_enabled|bool - name: Include immich tasks ansible.builtin.include_tasks: immich/immich.yml - when: immich_enabled|bool \ No newline at end of file + when: immich_enabled|bool diff --git a/config/ansible/tests/test-onepassword-lookup.yml b/config/ansible/tests/test-onepassword-lookup.yml index ac78abb..7db741f 100644 --- a/config/ansible/tests/test-onepassword-lookup.yml +++ b/config/ansible/tests/test-onepassword-lookup.yml @@ -6,17 +6,16 @@ vars: hoarder_data_dir: /mnt/storage-box/services/hoarder tasks: - - name: Test lookup with ref parameter + - name: Test lookup with direct reference ansible.builtin.debug: - msg: "{{ lookup('onepassword', ref='op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/OPENAI_API_KEY') }}" + msg: "{{ lookup('onepassword', 'op://j7nmhqlsjmp2r6umly5t75hzb4/Hoarder/OPENAI_API_KEY') }}" - name: Template with lookup ansible.builtin.template: - src: ../tasks/servers/services/hoarder/docker-compose.yml.j2 - dest: /tmp/docker-compose.yml + src: ../tasks/servers/services/hoarder/dotenv.j2 + dest: /tmp/.env register: op_direct - name: Print out the templated file ansible.builtin.debug: - msg: "{{ lookup('file', '/tmp/docker-compose.yml') }}" - + msg: "{{ lookup('file', '/tmp/.env') }}"