Read become password from pass
Signed-off-by: Yohann D'ANELLO <ynerant@crans.org>
This commit is contained in:
parent
475fe06fb7
commit
7f39ea724a
@ -1,13 +1,15 @@
|
|||||||
[defaults]
|
[defaults]
|
||||||
# Explicitely redefined some defaults to make play execution work
|
# Explicitely redefined some defaults to make play execution work
|
||||||
roles_path = ./roles
|
roles_path = ./roles
|
||||||
|
vars_plugins = ./vars_plugins
|
||||||
|
|
||||||
inventory = ./hosts
|
inventory = ./hosts
|
||||||
timeout = 60
|
timeout = 60
|
||||||
|
|
||||||
[privilege_escalation]
|
[privilege_escalation]
|
||||||
become = True
|
become = True
|
||||||
become_ask_pass = True
|
# Use a separate module to read passwords from pass
|
||||||
|
become_ask_pass = False
|
||||||
|
|
||||||
[ssh_connection]
|
[ssh_connection]
|
||||||
pipelining = True
|
pipelining = True
|
||||||
|
BIN
vars_plugins/__pycache__/pass.cpython-39.pyc
Normal file
BIN
vars_plugins/__pycache__/pass.cpython-39.pyc
Normal file
Binary file not shown.
BIN
vars_plugins/__pycache__/vault_cranspasswords.cpython-39.pyc
Normal file
BIN
vars_plugins/__pycache__/vault_cranspasswords.cpython-39.pyc
Normal file
Binary file not shown.
6
vars_plugins/pass.ini
Normal file
6
vars_plugins/pass.ini
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[pass]
|
||||||
|
# password_store_dir=/home/ynerant/.password-store
|
||||||
|
# crans_password_store_submodule=crans
|
||||||
|
|
||||||
|
[pass_become]
|
||||||
|
all=templier
|
6
vars_plugins/pass.ini.example
Normal file
6
vars_plugins/pass.ini.example
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[pass]
|
||||||
|
# password_store_dir=/home/me/.password-store
|
||||||
|
# crans_password_store_submodule=crans
|
||||||
|
|
||||||
|
[pass_become]
|
||||||
|
# all=mdp-root
|
102
vars_plugins/pass.py
Normal file
102
vars_plugins/pass.py
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from functools import lru_cache
|
||||||
|
from getpass import getpass
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from ansible.module_utils.six.moves import configparser
|
||||||
|
from ansible.plugins.vars import BaseVarsPlugin
|
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION = """
|
||||||
|
module: pass
|
||||||
|
vars: vault
|
||||||
|
version_added: 2.9
|
||||||
|
short_description: Load vault passwords from pass
|
||||||
|
description:
|
||||||
|
- Works exactly as a vault, loading variables from pass.
|
||||||
|
- Decrypts the YAML file `ansible_vault` from cranspasswords.
|
||||||
|
- Loads the secret variables.
|
||||||
|
- Makes use of data caching in order to avoid calling cranspasswords multiple times.
|
||||||
|
- Uses the local gpg key from the user running ansible on the Control node.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VarsModule(BaseVarsPlugin):
|
||||||
|
@staticmethod
|
||||||
|
@lru_cache
|
||||||
|
def decrypt_password(name, crans_submodule=False):
|
||||||
|
"""
|
||||||
|
Passwords are decrypted from the local password store, then are cached.
|
||||||
|
By that way, we don't decrypt these passwords everytime.
|
||||||
|
"""
|
||||||
|
# Load config
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pass.ini'))
|
||||||
|
|
||||||
|
password_store = Path(config.get('pass', 'password_store_dir',
|
||||||
|
fallback=os.getenv('PASSWORD_STORE_DIR', Path.home() / '.password-store')))
|
||||||
|
|
||||||
|
if crans_submodule:
|
||||||
|
password_store /= config.get('pass', 'crans_password_store_submodule',
|
||||||
|
fallback=os.getenv('CRANS_PASSWORD_STORE_SUBMODULE', 'crans'))
|
||||||
|
full_command = ['gpg', '-d', password_store / f'{name}.gpg']
|
||||||
|
proc = subprocess.run(full_command, capture_output=True, close_fds=True)
|
||||||
|
clear_text = proc.stdout.decode('UTF-8')
|
||||||
|
sys.stderr.write(proc.stderr.decode('UTF-8'))
|
||||||
|
return clear_text
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@lru_cache
|
||||||
|
def become_password(entity):
|
||||||
|
"""
|
||||||
|
Query the become password that should be used for the given entity.
|
||||||
|
If entity is the whole group that has no default password,
|
||||||
|
the become password will be prompted.
|
||||||
|
The configuration should be given in pass.ini, in the `pass_become`
|
||||||
|
group. You have only to write `group=pass-filename`.
|
||||||
|
"""
|
||||||
|
# Load config
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pass.ini'))
|
||||||
|
if config.has_option('pass_become', entity.get_name()):
|
||||||
|
return VarsModule.decrypt_password(
|
||||||
|
config.get('pass_become', entity.get_name())).split('\n')[0]
|
||||||
|
if entity.get_name() == "all":
|
||||||
|
return getpass("BECOME password: ", stream=None)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_vars(self, loader, path, entities):
|
||||||
|
"""
|
||||||
|
Get all vars for entities, called by Ansible.
|
||||||
|
|
||||||
|
loader: Ansible's DataLoader.
|
||||||
|
path: Current play's playbook directory.
|
||||||
|
entities: Host or group names pertinent to the variables needed.
|
||||||
|
"""
|
||||||
|
# VarsModule objects are called every time you need host vars, per host,
|
||||||
|
# and per group the host is part of.
|
||||||
|
# It is about 6 times per host per task in current state
|
||||||
|
# of Ansible Crans configuration.
|
||||||
|
|
||||||
|
# It is way to much.
|
||||||
|
# So we cache the data into the DataLoader (see parsing/DataLoader).
|
||||||
|
|
||||||
|
passwords = {}
|
||||||
|
|
||||||
|
for entity in entities:
|
||||||
|
# Load vault passwords
|
||||||
|
if entity.get_name() == 'all':
|
||||||
|
passwords['vault'] = loader.load(
|
||||||
|
VarsModule.decrypt_password('ansible_vault', True))
|
||||||
|
|
||||||
|
# Load become password
|
||||||
|
become_password = VarsModule.become_password(entity)
|
||||||
|
if become_password is not None:
|
||||||
|
passwords['ansible_become_password'] = become_password
|
||||||
|
|
||||||
|
return passwords
|
Loading…
Reference in New Issue
Block a user