Compare commits
5 Commits
52f98c1d57
...
0dd0633166
| Author | SHA1 | Date | |
|---|---|---|---|
|
0dd0633166
|
|||
|
9945330b82
|
|||
|
f4399a2c8a
|
|||
|
596b828e6f
|
|||
|
13ef8fa459
|
@@ -1,12 +1,6 @@
|
|||||||
# @TODO create inventory group variables akin to structure of sukaato group's for homeserver
|
# @TODO create inventory group variables akin to structure of sukaato group's for homeserver
|
||||||
# <str<vault>> representing password for Linux root user account of VPS
|
# <str<vault>> representing password for Linux root user account of VPS
|
||||||
password: !vault |
|
password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='armitage_test') }}"
|
||||||
$ANSIBLE_VAULT;1.1;AES256
|
|
||||||
32333335343939653231313938666134306338356633393035363039373465386165313666383262
|
|
||||||
6465313738316635633332623765336563626165336330370a616634393266366430363663333066
|
|
||||||
63373165346236386632393866316164623133373761303262643734356433646661636533666266
|
|
||||||
3834643765613937300a326365643961626236386261303933643965333565623836313231346537
|
|
||||||
3030
|
|
||||||
# <str> representing hostname for LAN server; same as host or group variable name
|
# <str> representing hostname for LAN server; same as host or group variable name
|
||||||
instance: armitage
|
instance: armitage
|
||||||
# <str<enum>> representing Linux distro or OS image to be used for VPS
|
# <str<enum>> representing Linux distro or OS image to be used for VPS
|
||||||
@@ -14,28 +8,19 @@ instance: armitage
|
|||||||
operating_system: ~
|
operating_system: ~
|
||||||
# <list[<str>]> of control node or local SSH key basenames
|
# <list[<str>]> of control node or local SSH key basenames
|
||||||
ssh_keys:
|
ssh_keys:
|
||||||
- ed25519@sukaato.hikiki
|
- ed25519@staging
|
||||||
- ecdsa@sukaato.hikiki
|
- ecdsa@staging
|
||||||
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
|
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
|
||||||
admins:
|
admins:
|
||||||
- username: senpai # <str> arbitrary valid user name
|
- username: senpai # <str> arbitrary valid user name
|
||||||
services: ~ # <list[<str>]> if linux system user, assocated servce
|
services: ~ # <list[<str>]> if linux system user, assocated servce
|
||||||
# <list[<str>]> list of control node or local SSH key basenames for this user
|
# <list[<str>]> list of control node or local SSH key basenames for this user
|
||||||
ssh_keys:
|
ssh_keys:
|
||||||
- ecdsa-37851076-sk@sukaato.hikiki
|
# @TODO add secondary and teriary Yubikeys
|
||||||
- ecdsa-37851072-sk@sukaato.hikiki
|
- ecdsa-37851076-sk@staging
|
||||||
|
- ed25519-37851076-sk@staging
|
||||||
# <str<vault?>> hashed (and maybe salted) password
|
# <str<vault?>> hashed (and maybe salted) password
|
||||||
password: !vault |
|
password: "{{ lookup('password', '../.tmp/armitage_test.pass', seed='senpai:armitage_test') }}"
|
||||||
$ANSIBLE_VAULT;1.1;AES256
|
|
||||||
34636132613365646330653431653236303563623464316638643439373761366564663264613738
|
|
||||||
3033343264373264333362616434333465323439653134340a643066663832353965313434386639
|
|
||||||
38366263646638353632656431366638393939623537326233306132306436363338373161643433
|
|
||||||
3439653833333164390a303430616561356464393030353433303738383730643330323031373432
|
|
||||||
62386231653339616436383837383966643539353036353034363132633539643332386131613537
|
|
||||||
31356230383561663735363530393562363237343166323635666665386165633130653864646238
|
|
||||||
39323735386161646531323335393639353630376136663063393930326434346435343937623336
|
|
||||||
33336132663238326662323536326638333139313535373166636363336366663962373936383536
|
|
||||||
62303536363939316563646630633064306364366331623665646533633065336236
|
|
||||||
# <dict[<str>:<dict>]> package groups
|
# <dict[<str>:<dict>]> package groups
|
||||||
pkgs:
|
pkgs:
|
||||||
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
|
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
|
||||||
|
|||||||
@@ -1,22 +1,7 @@
|
|||||||
# <str<vault>> representing password for Linux root user account of VPS
|
# <str<vault>> representing password for Linux root user account of VPS
|
||||||
password: !vault |
|
password: "{{ lookup('password', '../.tmp/sukaato_test.pass', seed='sukaato_test') }}"
|
||||||
$ANSIBLE_VAULT;1.1;AES256
|
|
||||||
66353462633933306537323461663665643234306166366663653163306436333037313032306338
|
|
||||||
3762653037396437633835356630656438623163656536310a306163663234383265386133396634
|
|
||||||
34363163343766623739646334643031373239373630663731376239333764346531396363636131
|
|
||||||
6163343335356337660a366337336632333236326532373032353332333636366638616265356562
|
|
||||||
66616534303035386134623535373935373065326539363065623230633034313433
|
|
||||||
# <str<vault>> representing API token for VPS cloud service
|
# <str<vault>> representing API token for VPS cloud service
|
||||||
token: !vault |
|
token: ~
|
||||||
$ANSIBLE_VAULT;1.1;AES256
|
|
||||||
33333839333337323062326231626534616166646666343261343966636464346630363033653130
|
|
||||||
3035653864396363376633346362353239643939663462370a323935353061313563336435366331
|
|
||||||
30393463653661326539326234646438663133616634663439303932656137633839656533376433
|
|
||||||
3666643635613039390a323138393033623131326438616331386539666333613630316263613636
|
|
||||||
66663263373665343662393638623064356234646165343835623966643761333562323132396466
|
|
||||||
63363436333463653130323531343139316466316131313031343232343039396261616231376232
|
|
||||||
66383938333661363532303166306563396634663132396166646132663131373738396131626633
|
|
||||||
34393265343061356531
|
|
||||||
# <str> representing name and hostname of VPS to be made in VPS cloud service
|
# <str> representing name and hostname of VPS to be made in VPS cloud service
|
||||||
instance: sukaato
|
instance: sukaato
|
||||||
# <str<enum>> representing region options from or for given VPS cloud service
|
# <str<enum>> representing region options from or for given VPS cloud service
|
||||||
@@ -25,28 +10,19 @@ origin: us-east
|
|||||||
operating_system: linode/debian13
|
operating_system: linode/debian13
|
||||||
# <list[<str>]> list of control node or local SSH key basenames for root user
|
# <list[<str>]> list of control node or local SSH key basenames for root user
|
||||||
ssh_keys:
|
ssh_keys:
|
||||||
- ed25519@sukaato.hikiki
|
- ed25519@staging
|
||||||
- ecdsa@sukaato.hikiki
|
- ecdsa@staging
|
||||||
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
|
# <list<dict>> list of administrative users (in Linux, users that can use "sudo")
|
||||||
admins:
|
admins:
|
||||||
- username: senpai # <str> arbitrary valid user name
|
- username: senpai # <str> arbitrary valid user name
|
||||||
services: ~ # <list[<str>]> if linux system user, assocated servce
|
services: ~ # <list[<str>]> if linux system user, assocated servce
|
||||||
# <list[<str>]> list of control node or local SSH key basenames for this user
|
# <list[<str>]> list of control node or local SSH key basenames for this user
|
||||||
ssh_keys:
|
ssh_keys:
|
||||||
- ecdsa-37851076-sk@sukaato.hikiki
|
# @TODO add secondary and teriary Yubikeys
|
||||||
- ecdsa-37851072-sk@sukaato.hikiki
|
- ecdsa-37851076-sk@staging
|
||||||
|
- ed25519-37851076-sk@staging
|
||||||
# <str<vault?>> hashed (and maybe salted) password
|
# <str<vault?>> hashed (and maybe salted) password
|
||||||
password: !vault |
|
password: "{{ lookup('password', '../.tmp/sukaato_test.pass', seed='senpai:sukaato_test') }}"
|
||||||
$ANSIBLE_VAULT;1.1;AES256
|
|
||||||
31663265653031323833373663653132653532646638316465393364613961643130653330393062
|
|
||||||
6165386239303965386261363565353137636164356130370a336465353931373564393339363561
|
|
||||||
37353162333331663833656631663165356134633961323337663439663733316231666334336539
|
|
||||||
6537373334326634610a623037613462663733343230306538386561363838316638623365636533
|
|
||||||
32313931666439363435663161663665346266653763343265376366383837376436643163376430
|
|
||||||
39393861613037333766386138376335653334363737626664383236303234653461313230383564
|
|
||||||
33393834636165386562383435666233313664656233326364616237636230303264363732376639
|
|
||||||
64396564366335366430303031323865333635306536346463386334303235386438663061343934
|
|
||||||
37376466373566396130366330383834323332626166316661336339346462343466
|
|
||||||
# <dict[<str>:<dict>]> package groups
|
# <dict[<str>:<dict>]> package groups
|
||||||
pkgs:
|
pkgs:
|
||||||
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
|
# <dict[<str>:<dict>]> representing package groups installed by package manager via repositories
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
# @TODO use hosts and host groupings that refer or point to VM or containerized servers for testing
|
# @TODO use hosts and host groupings that refer or point to VM or containerized servers for testing
|
||||||
ungrouped:
|
ungrouped:
|
||||||
hosts:
|
hosts:
|
||||||
staging:
|
staging0:
|
||||||
ansible_host: ~ # IP address of test host
|
ansible_host: ~
|
||||||
|
staging1:
|
||||||
|
ansible_host: ~
|
||||||
sukaato:
|
sukaato:
|
||||||
hosts: ~
|
hosts: ~
|
||||||
sukaato_test:
|
sukaato_test:
|
||||||
hosts:
|
hosts:
|
||||||
staging:
|
staging0:
|
||||||
armitage:
|
armitage:
|
||||||
hosts: ~
|
hosts: ~
|
||||||
armitage_test:
|
armitage_test:
|
||||||
hosts:
|
hosts:
|
||||||
staging:
|
staging1:
|
||||||
vps:
|
vps:
|
||||||
children:
|
children:
|
||||||
sukaato:
|
sukaato:
|
||||||
|
|||||||
@@ -18,20 +18,41 @@
|
|||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
root_pubkeys: "{{ root_pubkeys | default([]) + [lookup('file', item)] }}"
|
root_pubkeys: "{{ root_pubkeys | default([]) + [lookup('file', item)] }}"
|
||||||
loop: "{{ root_pubkey_paths }}"
|
loop: "{{ root_pubkey_paths }}"
|
||||||
|
- name: Ensuring password is defined for root user
|
||||||
|
when: prehashed_password is undefined or prehashed_password == None
|
||||||
|
block:
|
||||||
|
- name: Prompting for password for or of root user
|
||||||
|
when: password is undefined or password == None
|
||||||
|
ansible.builtin.pause:
|
||||||
|
prompt: "Provide a password for the root user"
|
||||||
|
echo: false
|
||||||
|
register: prompted_password
|
||||||
|
- name: Getting the inputted password for root user
|
||||||
|
when: prompted_password is defined or prompted_password != None
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
prehashed_password: "{{ prompted_password.user_input }}"
|
||||||
- name: Bootstrapping VPS
|
- name: Bootstrapping VPS
|
||||||
block:
|
block:
|
||||||
|
- name: Ensuring token is available for VPS service API
|
||||||
|
when: token is undefined or token == None
|
||||||
|
ansible.builtin.pause:
|
||||||
|
prompt: "Provide the API token for the given VPS service"
|
||||||
|
echo: false
|
||||||
|
register: prompted_token
|
||||||
- name: Creating VPS via Linode VPS service API
|
- name: Creating VPS via Linode VPS service API
|
||||||
block:
|
block:
|
||||||
- name: Creating the VPS
|
- name: Creating the VPS
|
||||||
linode.cloud.instance:
|
linode.cloud.instance:
|
||||||
api_token: "{{ token }}"
|
api_token: "{{ token | prompted_token.user_input }}"
|
||||||
label: "{{ instance }}"
|
label: "{{ instance }}"
|
||||||
type: g6-standard-2
|
type: g6-standard-2
|
||||||
image: "{{ operating_system }}"
|
image: "{{ operating_system }}"
|
||||||
disk_encryption: enabled
|
disk_encryption: enabled
|
||||||
region: "{{ origin }}"
|
region: "{{ origin }}"
|
||||||
private_ip: true
|
private_ip: true
|
||||||
root_pass: "{{ password }}"
|
# @TODO find out if 'root_pass' attribute takes in hashed or plaintext password
|
||||||
|
# root_pass: "{{ password | default((prehashed_password | lookup('password_hash', hashtype='sha512'))) }}" # IF HASHED
|
||||||
|
root_pass: "{{ password | default(prehashed_password) }}" # IF PLAINTEXT
|
||||||
authorized_keys: "{{ root_pubkeys }}"
|
authorized_keys: "{{ root_pubkeys }}"
|
||||||
state: present
|
state: present
|
||||||
register: new_instance
|
register: new_instance
|
||||||
@@ -43,7 +64,6 @@
|
|||||||
timeout: 300
|
timeout: 300
|
||||||
vars:
|
vars:
|
||||||
ansible_ssh_private_key_file: "{{ chosen_privkey | default(ssh_keypairs.files | rejectattr('path', 'search', '\\.pub$') | map(attribute='path') | list | random) }}" # @TODO define 'chosen_privkey'in playbook
|
ansible_ssh_private_key_file: "{{ chosen_privkey | default(ssh_keypairs.files | rejectattr('path', 'search', '\\.pub$') | map(attribute='path') | list | random) }}" # @TODO define 'chosen_privkey'in playbook
|
||||||
ansible_user: root
|
|
||||||
loop: "{{ new_instance.instance[ip_pref] }}"
|
loop: "{{ new_instance.instance[ip_pref] }}"
|
||||||
tags:
|
tags:
|
||||||
- linode
|
- linode
|
||||||
@@ -66,8 +86,6 @@
|
|||||||
ansible.builtin.wait_for_connection:
|
ansible.builtin.wait_for_connection:
|
||||||
delay: 20
|
delay: 20
|
||||||
timeout: 300
|
timeout: 300
|
||||||
vars:
|
|
||||||
ansible_user: root
|
|
||||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||||
- name: Checking if that server has required operating system
|
- name: Checking if that server has required operating system
|
||||||
delegate_to: "{{ item }}"
|
delegate_to: "{{ item }}"
|
||||||
@@ -76,8 +94,6 @@
|
|||||||
when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref']
|
when: ansible_facts["system"] != "Linux" and item is ansible.utils['ip_pref']
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: Unsupported operating system found
|
msg: Unsupported operating system found
|
||||||
vars:
|
|
||||||
ansible_user: root
|
|
||||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||||
- name: Checking if that server has required Linux distro
|
- name: Checking if that server has required Linux distro
|
||||||
delegate_to: "{{ item }}"
|
delegate_to: "{{ item }}"
|
||||||
@@ -86,19 +102,16 @@
|
|||||||
when: ansible_facts["system"] == "Linux" and ansible_facts["os_family"] != "Debian" and item is ansible.utils['ip_pref']
|
when: ansible_facts["system"] == "Linux" and ansible_facts["os_family"] != "Debian" and item is ansible.utils['ip_pref']
|
||||||
ansible.builtin.fail:
|
ansible.builtin.fail:
|
||||||
msg: Unsupported Linux distro found
|
msg: Unsupported Linux distro found
|
||||||
vars:
|
|
||||||
ansible_user: root
|
|
||||||
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
loop: "{{ groups[instance] | default(hostvars[instance]) }}"
|
||||||
- name: Providing authorized keys for server root account
|
- name: Providing authorized keys for server root account
|
||||||
delegate_to: "{{ item[0] }}"
|
delegate_to: "{{ item[0] }}"
|
||||||
delegate_facts: true
|
delegate_facts: true
|
||||||
|
become: true
|
||||||
remote_user: root
|
remote_user: root
|
||||||
ansible.posix.authorized_key:
|
ansible.posix.authorized_key:
|
||||||
user: "{{ ansible_user }}"
|
user: "{{ ansible_user }}"
|
||||||
key: "{{ lookup('file', item[1]) }}"
|
key: "{{ lookup('file', item[1]) }}"
|
||||||
state: present
|
state: present
|
||||||
vars:
|
|
||||||
ansible_user: root
|
|
||||||
loop: "{{ (groups[instance] | default(hostvars[instance])) | product(root_pubkey_paths) }}"
|
loop: "{{ (groups[instance] | default(hostvars[instance])) | product(root_pubkey_paths) }}"
|
||||||
tags:
|
tags:
|
||||||
- lan
|
- lan
|
||||||
|
|||||||
@@ -16,6 +16,27 @@
|
|||||||
register: remote_group
|
register: remote_group
|
||||||
tags:
|
tags:
|
||||||
- lan
|
- lan
|
||||||
|
- name: Managing passwords
|
||||||
|
when: prehashed_passwords is undefined or prehashed_passwords == None
|
||||||
|
block:
|
||||||
|
- name: Acquiring users lacking passwords
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
passwordless_admins: "{{ admins | selectattr('password', '==', 'null') | list }}"
|
||||||
|
- name: Pausing to acquire password for a user
|
||||||
|
when: item.password is undefined or item.password == None
|
||||||
|
ansible.builtin.pause:
|
||||||
|
prompt: "Provide a password for the administrative user, {{ item.username }}"
|
||||||
|
echo: false
|
||||||
|
loop: "{{ passwordless_admins }}"
|
||||||
|
register: prompted_passwords
|
||||||
|
- name: Processing inputted password per user
|
||||||
|
when: prompted_passwords is defined and prompted_passwords != None
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
prehashed_passwords: "{{ (prompted_passwords.results | default([])) | map(attribute='user_input') | list }}"
|
||||||
|
- name: Pairing inputted passwords with associated user
|
||||||
|
when: prehashed_passwords is defined or prehashed_passwords != None
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
prehashed_passwords: "{{ dict(passwordless_admins | map(attribute='username') | zip(prehashed_passwords) | list) }}"
|
||||||
- name: Creating an administrative user
|
- name: Creating an administrative user
|
||||||
become: true
|
become: true
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
@@ -27,7 +48,7 @@
|
|||||||
append: true
|
append: true
|
||||||
generate_ssh_key: true
|
generate_ssh_key: true
|
||||||
create_home: true
|
create_home: true
|
||||||
password: "{{ item.password }}"
|
password: "{{ item.password | default((prehashed_passwords[item.username] | password_hash(hashtype='sha512'))) }}"
|
||||||
shell: "/bin/bash"
|
shell: "/bin/bash"
|
||||||
loop: "{{ admins }}"
|
loop: "{{ admins }}"
|
||||||
register: admin_users
|
register: admin_users
|
||||||
|
|||||||
@@ -8,25 +8,30 @@ SKANSIBLE_DEBUG=1
|
|||||||
SKANSIBLE_UNIT_TEST=1
|
SKANSIBLE_UNIT_TEST=1
|
||||||
DEFAULT_USER=senpai
|
DEFAULT_USER=senpai
|
||||||
DEFAULT_SKANSIBLE_PLAY_HOST=vps
|
DEFAULT_SKANSIBLE_PLAY_HOST=vps
|
||||||
|
SKANSIBLE_SSH_KEY_COLLECTION=(~/.ssh/ed25519\@staging ~/.ssh/ecdsa\@staging ~/.ssh/ed25519-37851076-sk\@staging ~/.ssh/ecdsa-37851076-sk\@staging)
|
||||||
|
|
||||||
if [[ "$1" == "version" ]]; then
|
if [[ "$1" == "version" ]]; then
|
||||||
echo "0.0.0"
|
echo "0.0.0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "show-defaults" ]]; then
|
if [[ "$1" == "show-defaults" ]]; then
|
||||||
|
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate"
|
||||||
printf "User: %s\n" "$DEFAULT_USER"
|
printf "User: %s\n" "$DEFAULT_USER"
|
||||||
printf "Expected hosts for playbook: %s\n" "$DEFAULT_SKANSIBLE_PLAY_HOST"
|
printf "Expected hosts for playbook: %s\n" "$DEFAULT_SKANSIBLE_PLAY_HOST"
|
||||||
printf "Private SSH keys available throufh SSH agent: |\n%s\n" "$(ssh-add -l)"
|
printf "Private SSH keys available throufh SSH agent: |\n%s\n" "$(ssh-add -l)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "start-agent" ]]; then
|
if [[ "$1" == "start-agent" ]]; then
|
||||||
|
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate"
|
||||||
eval "$(ssh-agent -s)"
|
eval "$(ssh-agent -s)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "populate-agent" ]]; then
|
if [[ "$1" == "populate-agent" ]]; then
|
||||||
shift 1
|
shift 1
|
||||||
|
|
||||||
|
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate"
|
||||||
|
|
||||||
if [[ -z "$1" ]]; then
|
if [[ "$1" == "all" ]]; then
|
||||||
for SKANSIBLE_SSH_KEY in ~/.ssh/*; do
|
for SKANSIBLE_SSH_KEY in ~/.ssh/*; do
|
||||||
case $SKANSIBLE_SSH_KEY in
|
case $SKANSIBLE_SSH_KEY in
|
||||||
*.pub);;
|
*.pub);;
|
||||||
@@ -39,12 +44,21 @@ if [[ "$1" == "populate-agent" ]]; then
|
|||||||
*) ssh-add "${SKANSIBLE_SSH_KEY}";;
|
*) ssh-add "${SKANSIBLE_SSH_KEY}";;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
else
|
elif [[ "$1" == "select" ]]; then
|
||||||
|
for key in "${SKANSIBLE_SSH_KEY_COLLECTION[@]}"; do
|
||||||
|
ssh-add "$key"
|
||||||
|
done
|
||||||
|
elif [[ -z "$1" ]]; then
|
||||||
# @TODO improve by adding fuzzy querying or file finding pror
|
# @TODO improve by adding fuzzy querying or file finding pror
|
||||||
ssh-add "$1"
|
ssh-add "$1"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$1" == "list-agent" ]]; then
|
||||||
|
source "${SKANSIBLE_SCRIPT_PATH}/.env/bin/activate"
|
||||||
|
ssh-add -l
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$1" == "init" ]]; then
|
if [[ "$1" == "init" ]]; then
|
||||||
shift 1
|
shift 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user