Get multiple items from the vault using Ansible loop

So, I am wondering if there is a way to get multiple items from the vault at once?

Here is the issue - I have a playbook with 20 or 30 secrets that are going to be stored inside 1Password. What I really want to avoid is writing the same item_info task 30 times.

Instead, I've made the following:

secrets:
  title: Random item
  fields:
    - var: some_label
      definition:
        label: Some Label
        value: "the value"
        section: "Personal Info"
        field_type: concealed
    - var: dashboard_password
      definition:
        label: Dashboard Password
        generate_value: on_create
        generator_recipe:
            length: 16
            include_symbols: no

It works perfectly for creating items inside 1Password vault, but I also want to be able to retrieve all these values using Ansible loop, something like this:

    - name: Get the item
      item_info:
        item: "{{ vault_title }}"
        field: "{{ item.definition.label }}"
        vault: Ansible
      no_log: true
      register: "{{ item.definition.var }}"
      loop: "{{ secrets.fields }}"

The problem is that registered var names are not templatable, so the task above is going to fail.

So, is there any other way of doing this?


1Password Version: Not Provided
Extension Version: Not Provided
OS Version: Not Provided

Comments

  • igorhrcek
    igorhrcek
    Community Member

    So, I managed to get this:

    TASK [Print the item] *********************************************************************************************************************************************************************************************
    ok: [snip] =>
      smtn:
        changed: false
        msg: All items completed
        results:
        - ansible_facts:
            discovered_interpreter_python: /usr/bin/python3
          ansible_loop_var: item
          changed: false
          failed: false
          field: the value
          invocation:
            module_args:
              field: Some Label
              hostname: snip
              item: Glupi item
              token: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
              vault: Ansible
          item:
            definition:
              field_type: concealed
              label: Some Label
              section: Personal Info
              value: the value
            var: some_label
          op_item: {}
        - ansible_loop_var: item
          changed: false
          failed: false
          field: DrtqaPW7jhUYCKXX
          invocation:
            module_args:
              field: Dashboard Password
              hostname: snip
              item: Glupi item
              token: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
              vault: Ansible
          item:
            definition:
              generate_value: on_create
              generator_recipe:
                include_symbols: false
                length: 16
              label: Dashboard Password
            var: dashboard_password
          op_item: {}
    

    out of this:

        - name: Get the item
          item_info:
            item: "{{ vault_title }}"
            field: "{{ item.definition.label }}"
            vault: Ansible
          no_log: true
          register: smtn
          loop: "{{ secrets.fields }}"
    

    But that's it. I see that there are two ansible_loop_var items in the results but I am just unable to iterate through them.

    Any help would be appreciated.

  • igorhrcek
    igorhrcek
    Community Member

    Well after some serious head banging I've actually managed to extract all information I needed.

    Here is the result:

    TASK [Are we there yet?] ***************************************************************************************************************************************************************************************************************************************************************************************************
    ok: [snip] =>
      password_secrets:
        dashboard_password: DrtqaPW7jhUYCKXX
        notesPlain: 'null'
        some_label: the value
        some_label3: the value3
        some_label_2: the value2
    

    And here is how:

        - name: Get the item
          item_info:
            item: "{{ vault_title }}"
            vault: Ansible
          no_log: true
          register: smtn
          loop: "{{ secrets.fields }}"
    
        - name: Set fields
          set_fact:
            fields: "{{ fields | default([]) + [item.op_item.fields] }}"
          loop: '{{ smtn.results }}'
    
        - name: Convert fields to an actual dictionary
          set_fact:
            field_dict: "{{ fields | first | dict2items }}"
    
        - name: Set final items
          set_fact:
            final_items: "{{ final_items | default([]) + [item.value] }}"
          loop: '{{ field_dict }}'
    
        - name: Loop into dictionary
          set_fact:
            password_secrets: "{{ password_secrets | default({}) | combine ({ item.label : item.value | default('null') }) }}"
          loop: '{{ final_items }}'
    
        - name: Are we there yet?
          ansible.builtin.debug:
            var: password_secrets
    

    Someone might find this useful. Anyhow, I think this should be much much much easier and something available right out of the box.

  • This is a great idea and I agree this should be supported by the module. We've looked into creating a Lookup Plugin as well, but haven't checked whether that would solve the multiple-lookup issue.

    Could you open an issue in our GitHub repository: 1password/ansible-onepasswordconnect-collection ?

  • igorhrcek
    igorhrcek
    Community Member

    So apparently someone decided to alter the response of the API and make it much simpler to extract all fields from the item.

    Now, instead of doing all that I had to do (described in the comment above), to get to the same result you just need to do this:

        - name: Get the item
          item_info:
            item: "{{ vault_title }}"
            vault: Ansible
          no_log: true
          register: smtn
          loop: "{{ secrets.fields }}"
    
        - name: Loop into dictionary
          set_fact:
            password_secrets: "{{ password_secrets | default({}) | combine ({ item.item.label : item.item.value | default('null') }) }}"
          loop: '{{ smtn.results }}'
    

    That's considerably easier! And I just finished my 1Password role and noticed that it's not working - this is why :) Anyhow, this is much much better!

This discussion has been closed.