Skip to content

wip: unify caas/normal secrets #676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ansible/roles/passwords/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
This is pretty subtle.

- secrets always need to be idempotent
- caas cannot run a pre-task to create files in inventory, so secrets
need to be loaded as part of site
- caas cannot write inventory, b/c that is in a container which is new each
run


TODO:
- remove the adhoc generate-passwords from non-caas
- remove and the other role/hook from caas and the secret overrides
- work out how we'd migrate secrets for caas????
- test it properly
- doc this role properly
15 changes: 11 additions & 4 deletions ansible/roles/passwords/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
---

slurm_appliance_secrets:
# TODO: should we make these "'{{}}'" to ensure templating is OK??
passwords_defaults:
vault_grafana_admin_password: "{{ secrets_openhpc_grafana_admin_password | default(vault_grafana_admin_password | default(lookup('password', '/dev/null'))) }}"
vault_elasticsearch_admin_password: "{{ secrets_openhpc_elasticsearch_admin_password | default(vault_elasticsearch_admin_password | default(lookup('password', '/dev/null'))) }}"
vault_mysql_root_password: "{{ secrets_openhpc_mysql_root_password | default(vault_mysql_root_password | default(lookup('password', '/dev/null'))) }}"
vault_mysql_slurm_password: "{{ secrets_openhpc_mysql_slurm_password | default(vault_mysql_slurm_password | default(lookup('password', '/dev/null'))) }}"
vault_openhpc_mungekey: "{{ secrets_openhpc_mungekey | default(vault_openhpc_mungekey | default(secrets_openhpc_mungekey_default)) }}"
vault_openhpc_mungekey: "{{ secrets_openhpc_mungekey | default(vault_openhpc_mungekey | default(passwords_openhpc_mungekey_default)) }}"
vault_freeipa_ds_password: "{{ vault_freeipa_ds_password | default(lookup('password', '/dev/null')) }}"
vault_freeipa_admin_password: "{{ vault_freeipa_admin_password | default(lookup('password', '/dev/null')) }}"
vault_k3s_node_password: "{{ vault_k3s_node_password | default(lookup('ansible.builtin.password', '/dev/null', length=64)) }}"
vault_pulp_admin_password: "{{ vault_pulp_admin_password | default(lookup('password', '/dev/null', chars=['ascii_letters', 'digits'])) }}"
vault_demo_user_password: "{{ vault_demo_user_password | default(lookup('password', '/dev/null')) }}"
vault_alertmanager_admin_password: "{{ vault_alertmanager_admin_password | default(lookup('password', '/dev/null')) }}"
# vault_newthing: "{{ vault_newthing | default(lookup('password', '/dev/null')) }}"

secrets_openhpc_mungekey_default:
passwords_openhpc_mungekey_default:
content: "{{ lookup('pipe', 'dd if=/dev/urandom bs=1 count=1024 2>/dev/null | base64') }}"

openhpc_passwords_output_path: "{{ lookup('env', 'APPLIANCES_ENVIRONMENT_ROOT') | default(undefined, true) | mandatory('You must define the APPLIANCES_ENVIRONMENT_ROOT environment variable') }}/inventory/group_vars/all/secrets.yml"
passwords_output_path: "{{ lookup('env', 'APPLIANCES_ENVIRONMENT_ROOT') | default(undefined, true) | mandatory('You must define the APPLIANCES_ENVIRONMENT_ROOT environment variable') }}/inventory/group_vars/all/secrets.yml"

passwords_host: localhost
passwords_owner: "{{ ansible_user }}"
passwords_group: "{{ passwords_owner }}"

78 changes: 76 additions & 2 deletions ansible/roles/passwords/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,82 @@
---

# STATUS:

# looks like it works for caas, but not for normal now

# can't use ansible.builtin.include_vars - that only looks on the deploy host
# (even with delegate)

# For caas where passwords_output_path isn't actually in inventory we need
# to load them first, so that templating is idempotent

- name: Slurp passwords if defined
ansible.builtin.slurp:
src: "{{ passwords_output_path }}"
delegate_to: "{{ passwords_host }}"
register: _passwords_slurp_first
failed_when:
- _passwords_slurp_first.failed
- "'file not found' not in _passwords_slurp_first.msg"

- name: Set facts for passwords
set_fact:
"{{ item.key }}": "{{ item.value }}"
when: "'content' in _passwords_slurp_first"
loop: "{{ _passwords_slurp_first.content | b64decode | from_yaml | dict2items }}"
no_log: "{{ no_log | default(true) }}"

# - name: Set facts for passwords
# set_fact:
# # nah can't template yaml keys so not sure we can do this!
# when: not _passwords_slurp.failed
# loop: "{{ _passwords_slurp.content | b64decode | from_yaml }}"

- name: Ensure secrets directory exists
file:
path: "{{ passwords_output_path | dirname }}"
owner: "{{ passwords_owner }}"
group: "{{ passwords_group }}"
state: directory
#mode: ug=rwX,o=rX # non-caas for caas we want u=rwx,go=
delegate_to: "{{ passwords_host }}"
become: "{{ passwords_owner != ansible_user }}" # not sure about this in the general case but seems ok here
run_once: true

- name: Template passwords
template:
src: passwords.yml
dest: "{{ openhpc_passwords_output_path }}"
delegate_to: localhost
dest: "{{ passwords_output_path }}"
owner: "{{ passwords_owner }}"
group: "{{ passwords_group }}"
become: "{{ passwords_owner != ansible_user }}"
delegate_to: "{{ passwords_host }}"
run_once: true
register: _passwords_template

# even if the files are in inventory, even meta: inventory_reload doesn't
# get the new variables, so we need to set them as facts:
- name: Slurp passwords if changed
ansible.builtin.slurp:
src: "{{ passwords_output_path }}"
delegate_to: "{{ passwords_host }}"
register: _passwords_slurp_second
when: _passwords_template.changed

- name: Set facts for passwords
set_fact:
"{{ item.key }}": "{{ item.value }}"
when: not _passwords_slurp_second.skipped | default(false)
loop: "{{ _passwords_slurp_second.content | b64decode | from_yaml | dict2items }}"
no_log: "{{ no_log | default(true) }}"


# we do see passwords end up in the templated config for slurm-controlled rebuild!


# oh man maybe this doesn't work b/c things are accessed through hostvars[*] ...

# also; does this work for caas?? Because the vars won't be in inventory to
# start with, so then they won't exist, so they'll be re-templated despite
# the fact the file exists. Maybe we need to load them first, if the file
# exists??
9 changes: 5 additions & 4 deletions ansible/roles/passwords/tasks/validate.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- name: Assert secrets created
assert:
that: (hostvars[inventory_hostname].keys() | select('contains', 'vault_') | length) > 1 # 1 as may have vault_demo_user_password defined in dev
fail_msg: "No inventory variables 'vault_*' found: Has ansible/adhoc/generate-passwords.yml been run?"
# - name: Assert secrets created
# assert:
# that: (hostvars[inventory_hostname].keys() | select('contains', 'vault_') | length) > 1 # 1 as may have vault_demo_user_password defined in dev
# fail_msg: "No inventory variables 'vault_*' found: Has ansible/adhoc/generate-passwords.yml been run?"
# TODO: should maybe remove this, it isn't needed now??
2 changes: 1 addition & 1 deletion ansible/roles/passwords/templates/passwords.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
---
# {{ ansible_managed }}
{{ slurm_appliance_secrets | to_nice_yaml }}
{{ passwords_defaults | to_nice_yaml }}
9 changes: 9 additions & 0 deletions ansible/site.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
---

- name: Template passwords
hosts: cluster # TODO: maybe we need to run this
gather_facts: false
tasks:
- name: Include password generation role
include_role:
name: passwords
- meta: end_here

- name: Run pre.yml hook
vars:
# hostvars not available here, so have to recalculate environment root:
Expand Down
Loading