community.general icon indicating copy to clipboard operation
community.general copied to clipboard

ansible_become_password via 1Password lookup causes significant slowdown of playbook execution

Open jamesdh opened this issue 1 year ago • 3 comments

Summary

I was working on some playbooks intended for running locally over the weekend and got tired of constantly typing in my password, so I added the following:

- hosts: localhost
  vars:
    ansible_become_password: "{{ lookup('community.general.onepassword', 'Personal MacBook', field='password') }}"
  roles:
    ...

I gave a run, and immediately noticed that the playbooks were executing at about 1/10th of their normal speed, with a noticeable ~1 second pause between every task. It's almost as if it's evaluating the field lookup for every task.

Issue Type

Bug Report

Component Name

onepassword

Ansible Version

2.16.4

Community.general Version

community.general 8.4.0  

Configuration

CALLBACKS_ENABLED(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = ['ansible.posix.profile_tasks']
CONFIG_FILE() = /Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg
DEFAULT_HOST_LIST(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = ['/Users/jamesdh/Projects/jamesdh/dotfiles/hosts']
DEFAULT_LOOKUP_PLUGIN_PATH(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = ['/Users/jamesdh/Projects/jamesdh/dotfiles/lookup_plugins']
DEFAULT_MODULE_PATH(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = ['/Users/jamesdh/Projects/jamesdh/dotfiles/library']
DEFAULT_STDOUT_CALLBACK(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = yaml
DEFAULT_VAULT_PASSWORD_FILE(/Users/jamesdh/Projects/jamesdh/dotfiles/ansible.cfg) = /Users/jamesdh/.ansible/dotfiles_vaultpass
EDITOR(env: EDITOR) = vim

OS / Environment

macOS 14.4, Python 3.12.2

Steps to Reproduce

  • Add a simple login field to 1Password named "Personal Password" w/ a field "password" that matches your local
  • Create a hosts file and add the following:
[localhost]
127.0.0.1  ansible_connection=local
  • Configure your inventory to use this hosts file:
[defaults]
inventory=hosts
  • Create a playbook that defines the ansible_become_password var via lookup, and add any number of dummy tasks to it:
- hosts: localhost
  vars:
    ansible_become_password: "{{ lookup('community.general.onepassword', 'Personal Password', field='password') }}"
  roles:
    ...
  • Run the playbook:
ansible-playbook ansible.yml

Expected Results

Playbooks execute at the same speed as if the user used --ask-become-pass and manually entered it.

Actual Results

Playbooks execute many times slower

Code of Conduct

  • [X] I agree to follow the Ansible Code of Conduct

jamesdh avatar Mar 17 '24 20:03 jamesdh

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot avatar Mar 17 '24 20:03 ansibullbot

Variables are lazily evaluated. This means that this lookup is called every single time ansible_become_password is used.

Better use set_fact as a first task (or pre-task) to obtain the password once and store the (evaluated) result in a variable.

felixfontein avatar Mar 17 '24 20:03 felixfontein

Thanks @felixfontein, I suspected it was something like that but have been away from ansible long enough I really had no idea.

jamesdh avatar Mar 17 '24 20:03 jamesdh

I achieved this with a playbook like this:

---
- hosts: remote_host
  become: true
  become_method: ansible.builtin.sudo
  become_user: root
  gather_facts: false

  pre_tasks:
  - name: Get facts from 1Password
    set_fact:
      ansible_become_pass: "{{ lookup('community.general.onepassword', 'remote_host', field='become_password', vault='infra') }}"
      ansible_host: "{{ lookup('community.general.onepassword', 'remote_host', field='hostname', vault='infra') }}"
      ansible_port: "{{ lookup('community.general.onepassword', 'remote_host', field='port', vault='infra') }}"
      ansible_user: "{{ lookup('community.general.onepassword', 'remote_host', field='user', vault='infra') }}"
  - name: Gather facts
    ansible.builtin.gather_facts:

Thanks for the guidance!

kitforbes avatar Apr 20 '24 17:04 kitforbes

You might want to add run_once: true to the set_fact task to speed this up even a bit further :)

felixfontein avatar Apr 20 '24 20:04 felixfontein

Closing this since @kitforbes and @felixfontein's answers provide a working solution. Thank you!

jamesdh avatar Apr 23 '24 18:04 jamesdh