--- # 1Password CLI from 1Password's own signed package repository, never a # curl-piped binary. Mirrors https://developer.1password.com/docs/cli/get-started # (Linux, APT / YUM), with the signing key's fingerprint checked before apt or # dnf is allowed to trust it. - name: 1Password CLI | Require a supported OS family ansible.builtin.assert: that: - ansible_facts['os_family'] in ['Debian', 'RedHat'] fail_msg: >- The 1Password CLI install supports Debian- and RedHat-family hosts only (found {{ ansible_facts['os_family'] }}). Set multica_op_install: false. quiet: true # --- Debian / Ubuntu --------------------------------------------------------- - name: 1Password CLI | Install gnupg and debsig-verify ansible.builtin.apt: name: [gnupg, debsig-verify] state: present become: true when: ansible_facts['os_family'] == 'Debian' - name: 1Password CLI | Fetch the signing key ansible.builtin.get_url: url: "{{ multica_op_key_url }}" dest: /usr/share/keyrings/1password-archive-keyring.asc owner: root group: root mode: "0644" register: _multica_op_key_asc become: true when: ansible_facts['os_family'] == 'Debian' - name: 1Password CLI | Read the signing key's fingerprint ansible.builtin.command: argv: [gpg, --show-keys, --with-colons, /usr/share/keyrings/1password-archive-keyring.asc] register: _multica_op_key_info changed_when: false check_mode: false become: true when: - ansible_facts['os_family'] == 'Debian' - not (ansible_check_mode and _multica_op_key_asc is changed) # Under --check on a fresh host the key was only pretend-downloaded, so there is # nothing to read; the real run checks it. # A key that does not match is never dearmored, so apt never trusts it. - name: 1Password CLI | Require the expected signing key ansible.builtin.assert: that: - multica_op_key_fingerprint in (_multica_op_key_info.stdout_lines | select('match', '^fpr:') | map('split', ':') | map(attribute=9) | list) fail_msg: >- {{ multica_op_key_url }} is not the key with fingerprint {{ multica_op_key_fingerprint }}. Refusing to trust it. quiet: true when: - ansible_facts['os_family'] == 'Debian' - _multica_op_key_info is not skipped - name: 1Password CLI | Look for the dearmored keyrings ansible.builtin.stat: path: "{{ item }}" loop: - /usr/share/keyrings/1password-archive-keyring.gpg - /usr/share/debsig/keyrings/AC2D62742012EA22/debsig.gpg register: _multica_op_keyrings become: true when: ansible_facts['os_family'] == 'Debian' - name: 1Password CLI | Create the debsig policy and keyring directories ansible.builtin.file: path: "{{ item }}" state: directory owner: root group: root mode: "0755" loop: - /etc/debsig/policies/AC2D62742012EA22 - /usr/share/debsig/keyrings/AC2D62742012EA22 register: _multica_op_debsig_dirs become: true when: ansible_facts['os_family'] == 'Debian' # Same key, two consumers: apt (repository metadata) and debsig-verify (the # signature on each .deb). - name: 1Password CLI | Dearmor the key for apt and debsig ansible.builtin.command: argv: [gpg, --batch, --yes, --dearmor, --output, "{{ item.item }}", /usr/share/keyrings/1password-archive-keyring.asc] loop: "{{ _multica_op_keyrings.results }}" loop_control: label: "{{ item.item }}" when: - ansible_facts['os_family'] == 'Debian' - _multica_op_key_asc is changed or not item.stat.exists changed_when: true become: true - name: 1Password CLI | Install the debsig policy ansible.builtin.get_url: url: "{{ multica_op_debsig_policy_url }}" dest: /etc/debsig/policies/AC2D62742012EA22/1password.pol owner: root group: root mode: "0644" become: true when: - ansible_facts['os_family'] == 'Debian' - not (ansible_check_mode and _multica_op_debsig_dirs is changed) - name: 1Password CLI | Add the apt repository ansible.builtin.apt_repository: repo: >- deb [arch={{ _multica_arch }} signed-by=/usr/share/keyrings/1password-archive-keyring.gpg] {{ multica_op_apt_base_url }}/{{ _multica_arch }} stable main filename: 1password state: present update_cache: true register: _multica_op_repo_deb become: true when: ansible_facts['os_family'] == 'Debian' - name: 1Password CLI | Install the package ansible.builtin.apt: name: >- {{ '1password-cli=' ~ multica_op_version ~ '*' if multica_op_version | length > 0 else '1password-cli' }} state: "{{ 'present' if multica_op_version | length > 0 else 'latest' }}" allow_downgrade: "{{ multica_op_version | length > 0 }}" register: _multica_op_pkg_deb become: true when: - ansible_facts['os_family'] == 'Debian' - not (ansible_check_mode and _multica_op_repo_deb is changed) # --- EL ---------------------------------------------------------------------- - name: 1Password CLI | Add the yum repository ansible.builtin.yum_repository: name: 1password description: 1Password Stable Channel baseurl: "{{ multica_op_rpm_base_url }}/$basearch" gpgkey: "{{ multica_op_key_url }}" gpgcheck: true repo_gpgcheck: true enabled: true register: _multica_op_repo_rpm become: true when: ansible_facts['os_family'] == 'RedHat' - name: 1Password CLI | Install the package ansible.builtin.dnf: name: >- {{ '1password-cli-' ~ multica_op_version if multica_op_version | length > 0 else '1password-cli' }} state: "{{ 'present' if multica_op_version | length > 0 else 'latest' }}" allow_downgrade: "{{ multica_op_version | length > 0 }}" register: _multica_op_pkg_rpm become: true when: - ansible_facts['os_family'] == 'RedHat' - not (ansible_check_mode and _multica_op_repo_rpm is changed) # --- Verify ------------------------------------------------------------------ # As the daemon user, through its own environment: that is the context agents # call `op` from. - name: 1Password CLI | Check the installed version as the daemon user ansible.builtin.command: argv: [op, --version] become: true become_user: "{{ multica_user }}" environment: "{{ _multica_user_env }}" register: _multica_op_version_out changed_when: false check_mode: false failed_when: >- _multica_op_version_out.rc != 0 or (multica_op_version | length > 0 and _multica_op_version_out.stdout | trim != multica_op_version) # Under --check, only when the binary is already there to ask. when: >- not ansible_check_mode or (_multica_op_pkg_deb is not skipped and _multica_op_pkg_deb is not changed) or (_multica_op_pkg_rpm is not skipped and _multica_op_pkg_rpm is not changed)