refactor(prompts): remove vars_prompt, require users defined in inventory
This commit is contained in:
25
README.md
25
README.md
@@ -202,14 +202,29 @@ When `interfaces` is empty, the flat fields (`bridge`, `ip`, `prefix`, `gateway`
|
||||
|
||||
#### `system.users`
|
||||
|
||||
Dict keyed by username. At least one user must have a `password` (used for SSH access during bootstrap). Users without a password get locked accounts (key-only auth).
|
||||
|
||||
```yaml
|
||||
system:
|
||||
users:
|
||||
svcansible:
|
||||
password: "vault_lookup"
|
||||
keys:
|
||||
- "ssh-ed25519 AAAA..."
|
||||
appuser:
|
||||
sudo: "ALL=(ALL) NOPASSWD: ALL"
|
||||
keys:
|
||||
- "ssh-ed25519 BBBB..."
|
||||
```
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
| ---------- | ----------- | ------- | -------------------------------------------------- |
|
||||
| `name` | string | -- | Username (required) |
|
||||
| `password` | string | -- | User password (required for first user) |
|
||||
| *(dict key)* | string | -- | Username (required) |
|
||||
| `password` | string | -- | User password (required for at least one user) |
|
||||
| `keys` | list | `[]` | SSH public keys |
|
||||
| `sudo` | bool/string | -- | `true` for NOPASSWD ALL, or custom sudoers string |
|
||||
|
||||
The first user's credentials are prompted interactively via `vars_prompt` unless supplied in inventory or `-e`.
|
||||
Users must be defined in inventory. The dict format enables additive merging across inventory layers with `hash_behaviour=merge`.
|
||||
|
||||
#### `system.root`
|
||||
|
||||
@@ -398,7 +413,7 @@ ansible-playbook -i inventory.yml main.yml
|
||||
ansible-playbook -i inventory.yml main.yml -e @vars.yml
|
||||
```
|
||||
|
||||
Credentials for the first user and root are prompted interactively via `vars_prompt` unless already set in inventory or passed via `-e`.
|
||||
All credentials (`system.users`, `system.root.password`) must be defined in inventory or passed via `-e`.
|
||||
|
||||
Example inventory files are included:
|
||||
|
||||
@@ -408,7 +423,7 @@ Example inventory files are included:
|
||||
|
||||
## 7. Security
|
||||
|
||||
Use **Ansible Vault** for all sensitive values (`hypervisor.password`, `system.luks.passphrase`, `system.users[].password`, `system.root.password`).
|
||||
Use **Ansible Vault** for all sensitive values (`hypervisor.password`, `system.luks.passphrase`, user passwords in `system.users`, `system.root.password`).
|
||||
|
||||
## 8. Safety
|
||||
|
||||
|
||||
75
main.yml
75
main.yml
@@ -14,82 +14,7 @@
|
||||
strategy: free # noqa: run-once[play]
|
||||
gather_facts: false
|
||||
become: true
|
||||
vars_prompt:
|
||||
- name: user_name
|
||||
prompt: |
|
||||
What is your username?
|
||||
default: ""
|
||||
private: false
|
||||
|
||||
- name: user_public_key
|
||||
prompt: |
|
||||
What is your ssh key?
|
||||
default: ""
|
||||
private: false
|
||||
|
||||
- name: user_password
|
||||
prompt: |
|
||||
What is your password?
|
||||
default: ""
|
||||
confirm: true
|
||||
|
||||
- name: root_password
|
||||
prompt: |
|
||||
What is your root password?
|
||||
default: ""
|
||||
confirm: true
|
||||
pre_tasks:
|
||||
- name: Apply prompted authentication values to system input
|
||||
no_log: true
|
||||
vars:
|
||||
system_input: "{{ system | default({}) }}"
|
||||
system_users_input: "{{ system_input.users | default({}) }}"
|
||||
_first_entry: "{{ system_users_input | dict2items | first | default({'key': '', 'value': {}}) }}"
|
||||
_first_name: "{{ _first_entry.key }}"
|
||||
_first_attrs: "{{ _first_entry.value if _first_entry.value is mapping else {} }}"
|
||||
system_root_input: "{{ (system_input.root | default({})) if (system_input.root is mapping) else {} }}"
|
||||
prompt_user_name: "{{ user_name | default(system_user_name | default(''), true) | string }}"
|
||||
prompt_user_key: "{{ user_public_key | default(user_key | default(system_user_key | default(''), true), true) | string | trim }}"
|
||||
prompt_user_password: "{{ user_password | default(system_user_password | default(''), true) | string }}"
|
||||
prompt_root_password: "{{ root_password | default(system_root_password | default(''), true) | string }}"
|
||||
resolved_name: "{{ _first_name if (_first_name | length > 0) else prompt_user_name }}"
|
||||
resolved_attrs:
|
||||
keys: >-
|
||||
{{
|
||||
_first_attrs['keys']
|
||||
if (_first_attrs['keys'] is defined
|
||||
and _first_attrs['keys'] is iterable
|
||||
and _first_attrs['keys'] is not string
|
||||
and _first_attrs['keys'] | length > 0)
|
||||
else (
|
||||
[prompt_user_key]
|
||||
if (prompt_user_key | length > 0)
|
||||
else []
|
||||
)
|
||||
}}
|
||||
password: >-
|
||||
{{
|
||||
_first_attrs.password | string
|
||||
if (_first_attrs.password | default('') | string | length) > 0
|
||||
else prompt_user_password
|
||||
}}
|
||||
ansible.builtin.set_fact:
|
||||
system: >-
|
||||
{{
|
||||
system_input
|
||||
| combine(
|
||||
{
|
||||
'users': system_users_input | combine({resolved_name: (_first_attrs | combine(resolved_attrs, recursive=True))}),
|
||||
'root': {
|
||||
'password': (
|
||||
(system_root_input.password | default('') | string | length) > 0
|
||||
) | ternary(system_root_input.password | string, prompt_root_password)
|
||||
}
|
||||
},
|
||||
recursive=True
|
||||
)
|
||||
}}
|
||||
|
||||
- name: Load global defaults
|
||||
ansible.builtin.import_role:
|
||||
name: global_defaults
|
||||
|
||||
Reference in New Issue
Block a user