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`
|
#### `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 |
|
| Key | Type | Default | Description |
|
||||||
| ---------- | ----------- | ------- | -------------------------------------------------- |
|
| ---------- | ----------- | ------- | -------------------------------------------------- |
|
||||||
| `name` | string | -- | Username (required) |
|
| *(dict key)* | string | -- | Username (required) |
|
||||||
| `password` | string | -- | User password (required for first user) |
|
| `password` | string | -- | User password (required for at least one user) |
|
||||||
| `keys` | list | `[]` | SSH public keys |
|
| `keys` | list | `[]` | SSH public keys |
|
||||||
| `sudo` | bool/string | -- | `true` for NOPASSWD ALL, or custom sudoers string |
|
| `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`
|
#### `system.root`
|
||||||
|
|
||||||
@@ -398,7 +413,7 @@ ansible-playbook -i inventory.yml main.yml
|
|||||||
ansible-playbook -i inventory.yml main.yml -e @vars.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:
|
Example inventory files are included:
|
||||||
|
|
||||||
@@ -408,7 +423,7 @@ Example inventory files are included:
|
|||||||
|
|
||||||
## 7. Security
|
## 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
|
## 8. Safety
|
||||||
|
|
||||||
|
|||||||
75
main.yml
75
main.yml
@@ -14,82 +14,7 @@
|
|||||||
strategy: free # noqa: run-once[play]
|
strategy: free # noqa: run-once[play]
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
become: true
|
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:
|
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
|
- name: Load global defaults
|
||||||
ansible.builtin.import_role:
|
ansible.builtin.import_role:
|
||||||
name: global_defaults
|
name: global_defaults
|
||||||
|
|||||||
Reference in New Issue
Block a user