33 changed files with 1063 additions and 2 deletions
Unified View
Diff Options
-
1.gitignore
-
13cluster.yml
-
6inventory/group_vars/all.yml
-
8roles/adduser/defaults/main.yml
-
1roles/download/defaults/main.yml
-
1roles/etcd/defaults/main.yml
-
65roles/vault/defaults/main.yml
-
6roles/vault/meta/main.yml
-
32roles/vault/tasks/bootstrap/ca_trust.yml
-
29roles/vault/tasks/bootstrap/gen_etcd_certs.yml
-
29roles/vault/tasks/bootstrap/gen_etcd_node_certs.yml
-
66roles/vault/tasks/bootstrap/gen_vault_certs.yml
-
60roles/vault/tasks/bootstrap/main.yml
-
55roles/vault/tasks/bootstrap/start_vault_temp.yml
-
4roles/vault/tasks/bootstrap/stop_vault_temp.yml
-
38roles/vault/tasks/bootstrap/sync_etcd_certs.yml
-
34roles/vault/tasks/bootstrap/sync_etcd_node_certs.yml
-
32roles/vault/tasks/bootstrap/sync_vault_certs.yml
-
77roles/vault/tasks/check_vault.yml
-
25roles/vault/tasks/cluster/docker.yml
-
33roles/vault/tasks/cluster/gen_kube_master_certs.yml
-
33roles/vault/tasks/cluster/gen_kube_node_certs.yml
-
49roles/vault/tasks/cluster/init.yml
-
30roles/vault/tasks/cluster/main.yml
-
23roles/vault/tasks/cluster/pki_mount.yml
-
38roles/vault/tasks/cluster/sync_kube_master_certs.yml
-
34roles/vault/tasks/cluster/sync_kube_node_certs.yml
-
26roles/vault/tasks/cluster/unseal.yml
-
19roles/vault/tasks/config_ca.yml
-
50roles/vault/tasks/gen_cert.yml
-
13roles/vault/tasks/main.yml
-
38roles/vault/tasks/sync.yml
-
97roles/vault/tasks/sync_file.yml
@ -0,0 +1,65 @@ |
|||||
|
--- |
||||
|
|
||||
|
vault_bootstrap: false |
||||
|
vault_ca_options: |
||||
|
common_name: kube-cluster-ca |
||||
|
format: pem |
||||
|
ttl: 87600h |
||||
|
vault_cert_dir: "{{ vault_config_dir }}/ssl" |
||||
|
vault_client_headers: |
||||
|
Accept: "application/json" |
||||
|
Content-Type: "application/json" |
||||
|
vault_config: |
||||
|
backend: |
||||
|
etcd: |
||||
|
address: "https://{{ hostvars[groups.etcd[0]]['ansible_default_ipv4']['address'] }}:2379" |
||||
|
ha_enabled: "true" |
||||
|
redirect_addr: "https://{{ ansible_default_ipv4.address }}:{{ vault_port }}" |
||||
|
tls_ca_file: "{{ vault_cert_dir }}/ca.pem" |
||||
|
cluster_name: "kubernetes-vault" |
||||
|
default_lease_ttl: "{{ vault_default_lease_ttl }}" |
||||
|
listener: |
||||
|
tcp: |
||||
|
address: "0.0.0.0:{{ vault_port }}" |
||||
|
tls_cert_file: "{{ vault_cert_dir }}/api.pem" |
||||
|
tls_key_file: "{{ vault_cert_dir }}/api-key.pem" |
||||
|
max_lease_ttl: 720h |
||||
|
vault_config_dir: /etc/vault |
||||
|
vault_container_name: kube-hashicorp-vault |
||||
|
vault_default_lease_ttl: 720h |
||||
|
vault_default_role_permissions: |
||||
|
allow_any_name: true |
||||
|
vault_deployment_type: docker |
||||
|
vault_etcd_needs_gen: false |
||||
|
vault_etcd_sync_hosts: [] |
||||
|
vault_max_lease_ttl: 87600h |
||||
|
vault_needs_gen: false |
||||
|
vault_port: 8200 |
||||
|
vault_secret_shares: 1 |
||||
|
vault_secret_threshold: 1 |
||||
|
vault_secrets_dir: "{{ vault_config_dir }}/secrets" |
||||
|
vault_temp_config: |
||||
|
default_lease_ttl: "{{ vault_default_lease_ttl }}" |
||||
|
backend: |
||||
|
file: |
||||
|
path: /vault/file |
||||
|
listener: |
||||
|
tcp: |
||||
|
address: "0.0.0.0:{{ vault_temp_port }}" |
||||
|
tls_disable: "true" |
||||
|
vault_temp_port: 8201 |
||||
|
|
||||
|
# This should be set higher up, but setting defaults here to avoid issues |
||||
|
etcd_cert_dir: /etc/ssl/etcd/ssl |
||||
|
kube_cert_dir: /etc/kubernetes/ssl |
||||
|
|
||||
|
# Sync cert defaults (should be role, once include_role is fixed) |
||||
|
sync_file: '' |
||||
|
sync_file_dir: '' |
||||
|
sync_file_host_count: 0 |
||||
|
sync_file_is_cert: false |
||||
|
sync_file_key_path: '' |
||||
|
sync_file_key_srcs: [] |
||||
|
sync_file_path: '' |
||||
|
sync_file_results: [] |
||||
|
sync_file_srcs: [] |
@ -0,0 +1,6 @@ |
|||||
|
--- |
||||
|
# Implicit requirement on sync_cert role (include_role used in tasks) |
||||
|
|
||||
|
dependencies: |
||||
|
- role: download |
||||
|
file: "{{ downloads.vault }}" |
@ -0,0 +1,32 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: trust_ca | pull CA from cert from groups.vault|first |
||||
|
command: "cat {{ vault_cert_dir }}/ca.pem" |
||||
|
register: vault_cert_file_cat |
||||
|
when: inventory_hostname == groups.vault|first |
||||
|
|
||||
|
# This part is mostly stolen from the etcd role |
||||
|
- name: trust_ca | target ca-certificate store file |
||||
|
set_fact: |
||||
|
ca_cert_path: >- |
||||
|
{% if ansible_os_family == "Debian" -%} |
||||
|
/usr/local/share/ca-certificates/kube-cluster-ca.crt |
||||
|
{%- elif ansible_os_family == "RedHat" -%} |
||||
|
/etc/pki/ca-trust/source/anchors/kube-cluster-ca.crt |
||||
|
{%- elif ansible_os_family == "CoreOS" -%} |
||||
|
/etc/ssl/certs/kube-cluster-ca.pem |
||||
|
{%- endif %} |
||||
|
|
||||
|
- name: trust_ca | add CA to trusted CA dir |
||||
|
copy: |
||||
|
content: "{{ hostvars[groups.vault|first]['vault_cert_file_cat']['stdout'] }}" |
||||
|
dest: "{{ ca_cert_path }}" |
||||
|
register: vault_ca_cert |
||||
|
|
||||
|
- name: trust_ca | update ca-certificates (Debian/Ubuntu/CoreOS) |
||||
|
command: update-ca-certificates |
||||
|
when: vault_ca_cert.changed and ansible_os_family in ["Debian", "CoreOS"] |
||||
|
|
||||
|
- name: trust_ca | update ca-certificates (RedHat) |
||||
|
command: update-ca-trust extract |
||||
|
when: vault_ca_cert.changed and ansible_os_family == "RedHat" |
@ -0,0 +1,29 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: bootstrap/gen_etcd_certs | Add the etcd role |
||||
|
uri: |
||||
|
url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}/v1/pki/roles/etcd" |
||||
|
headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
allow_any_name: true |
||||
|
status_code: 204 |
||||
|
when: inventory_hostname == groups.etcd|first |
||||
|
|
||||
|
- include: ../gen_cert.yml |
||||
|
vars: |
||||
|
gen_cert_alt_names: "{{ groups.etcd | join(',') }},localhost" |
||||
|
gen_cert_copy_ca: "{{ true if item == vault_etcd_certs_needed|first else false }}" |
||||
|
gen_cert_hosts: "{{ groups.etcd }}" |
||||
|
gen_cert_ip_sans: >- |
||||
|
{%- for host in groups.etcd -%} |
||||
|
{{ hostvars[host]["ansible_default_ipv4"]["address"] }} |
||||
|
{%- if not loop.last -%},{%- endif -%} |
||||
|
{%- endfor -%} |
||||
|
,127.0.0.1,::1 |
||||
|
gen_cert_path: "{{ item }}" |
||||
|
gen_cert_vault_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
gen_cert_vault_role: etcd |
||||
|
gen_cert_vault_url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}" |
||||
|
with_items: "{{ vault_etcd_certs_needed|default([]) }}" |
@ -0,0 +1,29 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: bootstrap/gen_etcd_node_certs | Add the etcd role |
||||
|
uri: |
||||
|
url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}/v1/pki/roles/etcd" |
||||
|
headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
allow_any_name: true |
||||
|
status_code: 204 |
||||
|
when: inventory_hostname == groups["k8s-cluster"]|first |
||||
|
|
||||
|
- include: ../gen_cert.yml |
||||
|
vars: |
||||
|
gen_cert_alt_names: "{{ groups['k8s-cluster'] | union(groups.etcd) | join(',') }},localhost" |
||||
|
gen_cert_copy_ca: "{{ true if item == vault_etcd_node_certs_needed|first else false }}" |
||||
|
gen_cert_hosts: "{{ groups['k8s-cluster'] | union(groups.etcd) }}" |
||||
|
gen_cert_ip_sans: >- |
||||
|
{%- for host in groups["k8s-cluster"] | union(groups.etcd) -%} |
||||
|
{{ hostvars[host]["ansible_default_ipv4"]["address"] }} |
||||
|
{%- if not loop.last -%},{%- endif -%} |
||||
|
{%- endfor -%} |
||||
|
,127.0.0.1,::1 |
||||
|
gen_cert_path: "{{ item }}" |
||||
|
gen_cert_vault_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
gen_cert_vault_role: etcd |
||||
|
gen_cert_vault_url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}" |
||||
|
with_items: "{{ vault_etcd_node_certs_needed|default([]) }}" |
@ -0,0 +1,66 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Ensure vault_cert_dir exists |
||||
|
file: |
||||
|
path: "{{ vault_cert_dir }}" |
||||
|
state: directory |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Generate Root CA in vault-temp |
||||
|
uri: |
||||
|
url: "http://localhost:{{ vault_temp_port }}/v1/pki/root/generate/exported" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: "{{ vault_ca_options }}" |
||||
|
register: vault_ca_gen |
||||
|
when: inventory_hostname == groups.vault|first and vault_ca_cert_needed |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Set facts for ca cert and key |
||||
|
set_fact: |
||||
|
vault_ca_cert: "{{ vault_ca_gen.json.data.certificate }}" |
||||
|
vault_ca_key: "{{ vault_ca_gen.json.data.private_key }}" |
||||
|
when: inventory_hostname == groups.vault|first and vault_ca_cert_needed |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Set cert and key facts for all hosts other than groups.vault|first |
||||
|
set_fact: |
||||
|
vault_ca_cert: "{{ hostvars[groups.vault|first]['vault_ca_cert'] }}" |
||||
|
vault_ca_key: "{{ hostvars[groups.vault|first]['vault_ca_key'] }}" |
||||
|
when: inventory_hostname != groups.vault|first and vault_ca_cert_needed |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Copy root CA cert locally |
||||
|
copy: |
||||
|
content: "{{ vault_ca_cert }}" |
||||
|
dest: "{{ vault_cert_dir }}/ca.pem" |
||||
|
when: vault_ca_cert_needed |
||||
|
|
||||
|
- name: bootstrap/gen_vault_certs | Copy root CA key locally |
||||
|
copy: |
||||
|
content: "{{vault_ca_key}}" |
||||
|
dest: "{{vault_cert_dir}}/ca-key.pem" |
||||
|
when: vault_ca_cert_needed |
||||
|
|
||||
|
- name: boostrap/gen_vault_certs | Add the vault role |
||||
|
uri: |
||||
|
url: "http://localhost:{{ vault_temp_port }}/v1/pki/roles/vault" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: "{{ vault_default_role_permissions }}" |
||||
|
status_code: 204 |
||||
|
when: inventory_hostname == groups.vault|first and vault_api_cert_needed |
||||
|
|
||||
|
- include: ../gen_cert.yml |
||||
|
vars: |
||||
|
gen_cert_alt_names: "{{ groups.vault | join(',') }},localhost" |
||||
|
gen_cert_hosts: "{{ groups.vault }}" |
||||
|
gen_cert_ip_sans: >- |
||||
|
{%- for host in groups.vault -%} |
||||
|
{{ hostvars[host]["ansible_default_ipv4"]["address"] }} |
||||
|
{%- if not loop.last -%},{%- endif -%} |
||||
|
{%- endfor -%} |
||||
|
,127.0.0.1,::1 |
||||
|
gen_cert_path: "{{ vault_cert_dir }}/api.pem" |
||||
|
gen_cert_vault_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
gen_cert_vault_role: vault |
||||
|
gen_cert_vault_url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}" |
||||
|
when: vault_api_cert_needed |
@ -0,0 +1,60 @@ |
|||||
|
--- |
||||
|
|
||||
|
## Sync Certs |
||||
|
|
||||
|
- include: bootstrap/sync_vault_certs.yml |
||||
|
when: inventory_hostname in groups.vault |
||||
|
|
||||
|
- include: bootstrap/sync_etcd_certs.yml |
||||
|
when: inventory_hostname in groups.etcd |
||||
|
|
||||
|
- include: bootstrap/sync_etcd_node_certs.yml |
||||
|
when: inventory_hostname in groups["k8s-cluster"] | union(groups.etcd) |
||||
|
|
||||
|
## Generate Certs |
||||
|
|
||||
|
# Start a temporary instance of Vault |
||||
|
- include: bootstrap/start_vault_temp.yml |
||||
|
when: >- |
||||
|
( hostvars[groups.etcd|first].get("vault_etcd_certs_needed", [])|length > 0 or |
||||
|
hostvars[groups.etcd|first].get("vault_etcd_node_certs_needed", [])|length > 0 or |
||||
|
hostvars[groups.vault|first]["vault_ca_cert_needed"] ) and |
||||
|
inventory_hostname == groups.vault|first |
||||
|
|
||||
|
# Generate root CA certs for Vault if none exist |
||||
|
- include: bootstrap/gen_vault_certs.yml |
||||
|
when: >- |
||||
|
( hostvars[groups.vault|first]["vault_ca_cert_needed"] or |
||||
|
hostvars[groups.vault|first]["vault_api_cert_needed"] ) and |
||||
|
inventory_hostname in groups.vault |
||||
|
|
||||
|
# Change vault-temp's issuing CA to use existing ca.pem/ca-key.pem |
||||
|
- include: config_ca.yml |
||||
|
vars: |
||||
|
vault_url: "http://{{ groups.vault|first }}:{{ vault_temp_port }}" |
||||
|
when: >- |
||||
|
( hostvars[groups.etcd|first].get("vault_etcd_certs_needed", [])|length > 0 or |
||||
|
hostvars[groups["k8s-cluster"]|first].get("vault_etcd_node_certs_needed", [])|length > 0 or |
||||
|
hostvars[groups.vault|first]["vault_api_cert_needed"] ) and |
||||
|
not hostvars[groups.vault|first]["vault_ca_cert_needed"] and |
||||
|
inventory_hostname == groups.vault|first |
||||
|
|
||||
|
# Generate etcd certs for etcd cluster members |
||||
|
- include: bootstrap/gen_etcd_certs.yml |
||||
|
when: >- |
||||
|
hostvars[groups.etcd|first].get("vault_etcd_certs_needed", [])|length > 0 and |
||||
|
inventory_hostname in groups.etcd |
||||
|
|
||||
|
# Generate etcd node certs for all k8s-cluster |
||||
|
- include: bootstrap/gen_etcd_node_certs.yml |
||||
|
when: >- |
||||
|
hostvars[groups["k8s-cluster"]|first].get("vault_etcd_node_certs_needed", [])|length > 0 and |
||||
|
inventory_hostname in groups["k8s-cluster"] | union(groups.etcd) |
||||
|
|
||||
|
# Stop temporary vault |
||||
|
- include: bootstrap/stop_vault_temp.yml |
||||
|
when: >- |
||||
|
inventory_hostname == groups.vault|first and |
||||
|
hostvars[groups.vault|first]["vault_temp_start"]|succeeded |
||||
|
|
||||
|
- include: ca_trust.yml |
@ -0,0 +1,55 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: boostrap/start_vault_temp | Ensure vault-temp isn't already running |
||||
|
shell: if docker rm -f vault-temp 2>&1 1>/dev/null;then echo true;else echo false;fi |
||||
|
register: vault_temp_stop_check |
||||
|
changed_when: "{{ 'true' in vault_temp_stop_check.stdout }}" |
||||
|
|
||||
|
- name: bootstrap/start_vault_temp | Start single node Vault with file backend |
||||
|
command: > |
||||
|
docker run -d --cap-add=IPC_LOCK --name vault-temp -p {{ vault_temp_port }}:{{ vault_temp_port }} |
||||
|
-e 'VAULT_LOCAL_CONFIG={{ vault_temp_config|to_json }}' |
||||
|
-v /etc/vault:/etc/vault |
||||
|
{{ vault_image_repo }}:{{ vault_version }} server |
||||
|
register: vault_temp_start |
||||
|
|
||||
|
- name: bootstrap/start_vault_temp | Initialize vault-temp |
||||
|
uri: |
||||
|
url: "http://localhost:{{ vault_temp_port }}/v1/sys/init" |
||||
|
headers: "{{ vault_client_headers }}" |
||||
|
method: PUT |
||||
|
body_format: json |
||||
|
body: |
||||
|
secret_shares: 1 |
||||
|
secret_threshold: 1 |
||||
|
register: vault_temp_init |
||||
|
|
||||
|
# NOTE: vault_headers and vault_url are used by subsequent gen_cert calls |
||||
|
- name: bootstrap/start_vault_temp | Set needed vault facts |
||||
|
set_fact: |
||||
|
vault_temp_unseal_keys: "{{ vault_temp_init.json['keys'] }}" |
||||
|
vault_temp_root_token: "{{ vault_temp_init.json.root_token }}" |
||||
|
vault_headers: "{{ vault_client_headers|combine({'X-Vault-Token': vault_temp_init.json.root_token}) }}" |
||||
|
|
||||
|
- name: bootstrap/start_vault_temp | Unseal vault-temp |
||||
|
uri: |
||||
|
url: "http://localhost:{{ vault_temp_port }}/v1/sys/unseal" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
key: "{{ item }}" |
||||
|
with_items: "{{ vault_temp_unseal_keys|default([]) }}" |
||||
|
|
||||
|
- name: bootstrap/start_vault_temp | Create new PKI mount |
||||
|
uri: |
||||
|
url: "http://localhost:{{ vault_temp_port }}/v1/sys/mounts/pki" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
config: |
||||
|
default_lease_ttl: "{{ vault_default_lease_ttl }}" |
||||
|
max_lease_ttl: "{{ vault_max_lease_ttl }}" |
||||
|
type: pki |
||||
|
status_code: 204 |
@ -0,0 +1,4 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: stop vault-temp container |
||||
|
command: docker stop vault-temp |
@ -0,0 +1,38 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_certs | Create list of certs needing creation |
||||
|
set_fact: |
||||
|
vault_etcd_cert_list: >- |
||||
|
{{ vault_etcd_cert_list|default([]) + [ |
||||
|
"admin-" + item + ".pem", |
||||
|
"member-" + item + ".pem" |
||||
|
] }} |
||||
|
with_items: "{{ groups.etcd }}" |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "{{ item }}" |
||||
|
sync_file_dir: "{{ etcd_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups.etcd }}" |
||||
|
sync_file_is_cert: true |
||||
|
with_items: "{{ vault_etcd_cert_list|default([]) }}" |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_certs | Set facts for etcd sync_file results |
||||
|
set_fact: |
||||
|
vault_etcd_certs_needed: "{{ vault_etcd_certs_needed|default([]) + [item.path] }}" |
||||
|
with_items: "{{ sync_file_results }}" |
||||
|
when: item.no_srcs|bool |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_certs | Unset sync_file_results after etcd certs sync |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: ca.pem |
||||
|
sync_file_dir: "{{ etcd_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups.etcd }}" |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_certs | Unset sync_file_results after ca.pem sync |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
@ -0,0 +1,34 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_node_certs | Create list of certs needing creation |
||||
|
set_fact: |
||||
|
vault_etcd_node_cert_list: "{{ vault_etcd_node_cert_list|default([]) + ['node-' + item + '.pem'] }}" |
||||
|
with_items: "{{ groups['k8s-cluster'] | union(groups.etcd) }}" |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "{{ item }}" |
||||
|
sync_file_dir: "{{ etcd_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['k8s-cluster'] | union(groups.etcd) }}" |
||||
|
sync_file_is_cert: true |
||||
|
with_items: "{{ vault_etcd_node_cert_list|default([]) }}" |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_node_certs | Set facts for etcd sync_file results |
||||
|
set_fact: |
||||
|
vault_etcd_node_certs_needed: "{{ vault_etcd_node_certs_needed|default([]) + [item.path] }}" |
||||
|
with_items: "{{ sync_file_results }}" |
||||
|
when: item.no_srcs|bool |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_node_certs | Unset sync_file_results after etcd node certs |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: ca.pem |
||||
|
sync_file_dir: "{{ etcd_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['k8s-cluster']| union(groups.etcd) }}" |
||||
|
|
||||
|
- name: bootstrap/sync_etcd_node_certs | Unset sync_file_results after ca.pem |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
@ -0,0 +1,32 @@ |
|||||
|
--- |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "ca.pem" |
||||
|
sync_file_dir: "{{ vault_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups.vault }}" |
||||
|
sync_file_is_cert: true |
||||
|
|
||||
|
- name: "bootstrap/sync_vault_certs | Set facts for vault sync_file results" |
||||
|
set_fact: |
||||
|
vault_ca_cert_needed: "{{ true if sync_file_results|length > 0 else false }}" |
||||
|
|
||||
|
- name: bootstrap/sync_vault_certs | Unset sync_file_results after ca.pem sync |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "api.pem" |
||||
|
sync_file_dir: "{{ vault_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups.vault }}" |
||||
|
sync_file_is_cert: true |
||||
|
|
||||
|
- name: bootstrap/sync_vault_certs | Set fact if Vault's API cert is needed |
||||
|
set_fact: |
||||
|
vault_api_cert_needed: "{{ true if sync_file_results|length > 0 else false }}" |
||||
|
|
||||
|
- name: bootstrap/sync_vault_certs | Unset sync_file_results after api.pem sync |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
@ -0,0 +1,77 @@ |
|||||
|
--- |
||||
|
|
||||
|
# Check if vault is reachable on the localhost |
||||
|
- name: check_vault | Attempt to pull local vault health |
||||
|
uri: |
||||
|
url: "https://localhost:{{ vault_port }}/v1/sys/health" |
||||
|
headers: "{{ vault_client_headers }}" |
||||
|
validate_certs: no |
||||
|
ignore_errors: true |
||||
|
register: vault_local_service_health |
||||
|
|
||||
|
- name: check_vault | Set facts about local Vault health |
||||
|
set_fact: |
||||
|
vault_is_running: "{{ vault_local_service_health|succeeded }}" |
||||
|
vault_is_initialized: "{{ vault_local_service_health.get('json', {}).get('initialized', false) }}" |
||||
|
vault_is_sealed: "{{ vault_local_service_health.get('json', {}).get('sealed', true) }}" |
||||
|
vault_in_standby: "{{ vault_local_service_health.get('json', {}).get('standby', true) }}" |
||||
|
vault_run_version: "{{ vault_local_service_health.get('json', {}).get('version', '') }}" |
||||
|
|
||||
|
- name: check_vault | Set fact about the Vault cluster's initialization state |
||||
|
set_fact: |
||||
|
vault_cluster_is_initialized: "{{ vault_is_initialized or hostvars[item]['vault_is_initialized'] }}" |
||||
|
with_items: "{{ groups.vault }}" |
||||
|
|
||||
|
- name: check_vault | Set fact about the Vault Cluster's available hosts |
||||
|
set_fact: |
||||
|
vault_available_hosts: "{{ vault_available_hosts|default([]) + [item] }}" |
||||
|
with_items: "{{ groups.vault }}" |
||||
|
when: "hostvars[item]['vault_is_running'] and not hostvars[item]['vault_is_sealed']" |
||||
|
|
||||
|
- include: sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "{{ item }}" |
||||
|
sync_file_dir: "{{ vault_secrets_dir }}" |
||||
|
sync_file_hosts: "{{ groups.vault }}" |
||||
|
with_items: |
||||
|
- root_token |
||||
|
- unseal_keys |
||||
|
|
||||
|
# Logic is hard to follow on this one, probably need to simplify somehow |
||||
|
- name: "check_vault | Set fact based on sync_file_results" |
||||
|
set_fact: |
||||
|
vault_secrets_available: "{{ vault_secrets_available|default(true) and not item.no_srcs }}" |
||||
|
with_items: "{{ sync_file_results }}" |
||||
|
|
||||
|
- name: "check_vault | Reset sync_file_results to avoid variable bleed" |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- name: "check_vault | Print out warning message if secrets are not available" |
||||
|
pause: |
||||
|
prompt: > |
||||
|
Vault orchestration may not be able to proceed. The Vault cluster is initialzed, but |
||||
|
'root_token' or 'unseal_keys' were not found in {{ vault_secrets_dir }}. These are |
||||
|
needed for many orchestration steps. |
||||
|
when: vault_cluster_is_initialized and not vault_secrets_available |
||||
|
|
||||
|
- name: "check_vault | Cat root_token from a vault host" |
||||
|
command: "cat {{ vault_secrets_dir }}/root_token" |
||||
|
register: vault_root_token_cat |
||||
|
when: vault_secrets_available and inventory_hostname == groups.vault|first |
||||
|
|
||||
|
- name: "check_vault | Cat unseal_keys from a vault host" |
||||
|
command: "cat {{ vault_secrets_dir }}/unseal_keys" |
||||
|
register: vault_unseal_keys_cat |
||||
|
when: vault_secrets_available and inventory_hostname == groups.vault|first |
||||
|
|
||||
|
- name: "check_vault | Set needed facts for Vault API interaction when Vault is already running" |
||||
|
set_fact: |
||||
|
vault_root_token: "{{ hostvars[groups.vault|first]['vault_root_token_cat']['stdout'] }}" |
||||
|
vault_unseal_keys: "{{ hostvars[groups.vault|first]['vault_unseal_keys_cat']['stdout_lines'] }}" |
||||
|
when: vault_secrets_available |
||||
|
|
||||
|
- name: "check-vault | Update vault_headers if we have the root_token" |
||||
|
set_fact: |
||||
|
vault_headers: "{{ vault_client_headers | combine({'X-Vault-Token': vault_root_token}) }}" |
||||
|
when: vault_secrets_available |
@ -0,0 +1,25 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: docker | Check on state of docker instance |
||||
|
command: "docker inspect {{ vault_container_name }}" |
||||
|
ignore_errors: true |
||||
|
register: vault_container_inspect |
||||
|
|
||||
|
- name: docker | Set fact on container status |
||||
|
set_fact: |
||||
|
vault_container_inspect_json: "{{ vault_container_inspect.stdout|from_json }}" |
||||
|
when: vault_container_inspect|succeeded |
||||
|
|
||||
|
# Not sure if State.Running is the best check here... |
||||
|
- name: docker | Remove old container if it's not currently running |
||||
|
command: "docker rm {{ vault_container_name }}" |
||||
|
when: vault_container_inspect|succeeded and not vault_container_inspect_json[0]["State"]["Running"]|bool |
||||
|
|
||||
|
- name: docker | Start a new Vault instance |
||||
|
command: > |
||||
|
docker run -d --cap-add=IPC_LOCK --name {{vault_container_name}} -p {{vault_port}}:{{vault_port}} |
||||
|
-e 'VAULT_LOCAL_CONFIG={{ vault_config|to_json }}' |
||||
|
-v /etc/vault:/etc/vault |
||||
|
{{vault_image_repo}}:{{vault_version}} server |
||||
|
register: vault_docker_start |
||||
|
when: vault_container_inspect|failed or not vault_container_inspect_json[0]["State"]["Running"]|bool |
@ -0,0 +1,33 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: "cluster/gen_kube_node_certs | Ensure kube_cert_dir exists" |
||||
|
file: |
||||
|
path: "{{ kube_cert_dir }}" |
||||
|
state: directory |
||||
|
|
||||
|
- name: gen_kube_master_certs | Add the kube role |
||||
|
uri: |
||||
|
url: "https://{{ hostvars[groups.vault|first]['vault_leader'] }}:{{ vault_port }}/v1/pki/roles/kubernetes" |
||||
|
headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: "{{ vault_default_role_permissions }}" |
||||
|
status_code: 204 |
||||
|
when: inventory_hostname == groups["kube-master"]|first |
||||
|
|
||||
|
- include: ../gen_cert.yml |
||||
|
vars: |
||||
|
gen_cert_alt_names: "{{ groups['kube-master'] | join(',') }},localhost" |
||||
|
gen_cert_copy_ca: "{{ true if item == vault_kube_master_certs_needed|first else false }}" |
||||
|
gen_cert_hosts: "{{ groups['kube-master'] }}" |
||||
|
gen_cert_ip_sans: >- |
||||
|
{%- for host in groups["kube-master"] -%} |
||||
|
{{ hostvars[host]["ansible_default_ipv4"]["address"] }} |
||||
|
{%- if not loop.last -%},{%- endif -%} |
||||
|
{%- endfor -%} |
||||
|
,127.0.0.1,::1 |
||||
|
gen_cert_path: "{{ item }}" |
||||
|
gen_cert_vault_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
gen_cert_vault_role: kubernetes |
||||
|
gen_cert_vault_url: "https://{{ hostvars[groups.vault|first]['vault_leader'] }}:{{ vault_port }}" |
||||
|
with_items: "{{ vault_kube_master_certs_needed|default([]) }}" |
@ -0,0 +1,33 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: "cluster/gen_kube_node_certs | Ensure kube_cert_dir exists" |
||||
|
file: |
||||
|
path: "{{ kube_cert_dir }}" |
||||
|
state: directory |
||||
|
|
||||
|
- name: "cluster/gen_kube_node_certs | Add the kubernetes role" |
||||
|
uri: |
||||
|
url: "https://{{ hostvars[groups.vault|first]['vault_leader'] }}:{{ vault_port }}/v1/pki/roles/kubernetes" |
||||
|
headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: "{{ vault_default_role_permissions }}" |
||||
|
status_code: 204 |
||||
|
when: inventory_hostname == groups["k8s-cluster"]|first |
||||
|
|
||||
|
- include: ../gen_cert.yml |
||||
|
vars: |
||||
|
gen_cert_alt_names: "{{ groups['k8s-cluster'] | join(',') }},localhost" |
||||
|
gen_cert_copy_ca: "{{ true if item == vault_kube_node_certs_needed|first else false }}" |
||||
|
gen_cert_hosts: "{{ groups['k8s-cluster'] }}" |
||||
|
gen_cert_ip_sans: >- |
||||
|
{%- for host in groups["k8s-cluster"] -%} |
||||
|
{{ hostvars[host]["ansible_default_ipv4"]["address"] }} |
||||
|
{%- if not loop.last -%},{%- endif -%} |
||||
|
{%- endfor -%} |
||||
|
,127.0.0.1,::1 |
||||
|
gen_cert_path: "{{ item }}" |
||||
|
gen_cert_vault_headers: "{{ hostvars[groups.vault|first]['vault_headers'] }}" |
||||
|
gen_cert_vault_role: kubernetes |
||||
|
gen_cert_vault_url: "https://{{ hostvars[groups.vault|first]['vault_leader'] }}:{{ vault_port }}" |
||||
|
with_items: "{{ vault_kube_node_certs_needed|default([]) }}" |
@ -0,0 +1,49 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: cluster/init | Initialize Vault |
||||
|
uri: |
||||
|
url: "https://{{ groups.vault|first }}:{{ vault_port }}/v1/sys/init" |
||||
|
headers: "{{ vault_client_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
secret_shares: "{{ vault_secret_shares }}" |
||||
|
secret_threshold: "{{ vault_secret_threshold }}" |
||||
|
validate_certs: false |
||||
|
register: vault_init_result |
||||
|
when: not vault_cluster_is_initialized and inventory_hostname == groups.vault|first |
||||
|
|
||||
|
- name: cluster/init | Set facts on the results of the initialization |
||||
|
set_fact: |
||||
|
vault_unseal_keys: "{{ vault_init_result.json['keys'] }}" |
||||
|
vault_root_token: "{{ vault_init_result.json.root_token }}" |
||||
|
vault_headers: "{{ vault_client_headers|combine({'X-Vault-Token': vault_init_result.json.root_token}) }}" |
||||
|
when: not vault_cluster_is_initialized and inventory_hostname == groups.vault|first |
||||
|
|
||||
|
- name: cluster/init | Ensure all hosts have these facts |
||||
|
set_fact: |
||||
|
vault_unseal_keys: "{{ hostvars[groups.vault|first]['vault_unseal_keys'] }}" |
||||
|
vault_root_token: "{{ hostvars[groups.vault|first]['vault_root_token'] }}" |
||||
|
when: not vault_cluster_is_initialized and inventory_hostname != groups.vault|first |
||||
|
|
||||
|
- name: cluster/init | Ensure the vault_secrets_dir exists |
||||
|
file: |
||||
|
path: "{{ vault_secrets_dir }}" |
||||
|
state: directory |
||||
|
|
||||
|
- name: cluster/init | Ensure all in groups.vault have the unseal_keys locally |
||||
|
copy: |
||||
|
content: "{{ vault_unseal_keys|join('\n') }}" |
||||
|
dest: "{{ vault_secrets_dir }}/unseal_keys" |
||||
|
when: not vault_cluster_is_initialized |
||||
|
|
||||
|
- name: cluster/init | Ensure all in groups.vault have the root_token locally |
||||
|
copy: |
||||
|
content: "{{ vault_root_token }}" |
||||
|
dest: "{{ vault_secrets_dir }}/root_token" |
||||
|
when: not vault_cluster_is_initialized |
||||
|
|
||||
|
- name: cluster/init | Ensure vault_headers and vault statuses are updated |
||||
|
set_fact: |
||||
|
vault_headers: "{{ vault_client_headers | combine({'X-Vault-Token': vault_root_token})}}" |
||||
|
vault_cluster_is_initialized: true |
@ -0,0 +1,30 @@ |
|||||
|
--- |
||||
|
|
||||
|
## Vault Cluster Setup |
||||
|
|
||||
|
- include: docker.yml |
||||
|
when: inventory_hostname in groups.vault and vault_deployment_type == "docker" |
||||
|
- include: init.yml |
||||
|
when: inventory_hostname in groups.vault |
||||
|
- include: unseal.yml |
||||
|
when: inventory_hostname in groups.vault |
||||
|
- include: pki_mount.yml |
||||
|
when: 'inventory_hostname == hostvars[groups.vault|first]["vault_leader"]' |
||||
|
- include: config_ca.yml |
||||
|
vars: |
||||
|
vault_url: "https://{{ vault_leader }}:{{ vault_port }}" |
||||
|
when: 'inventory_hostname == hostvars[groups.vault|first]["vault_leader"]' |
||||
|
|
||||
|
## Sync Kubernetes Certs |
||||
|
|
||||
|
- include: sync_kube_master_certs.yml |
||||
|
when: inventory_hostname in groups["kube-master"] |
||||
|
- include: sync_kube_node_certs.yml |
||||
|
when: inventory_hostname in groups["k8s-cluster"] |
||||
|
|
||||
|
## Generate Kubernetes Certs |
||||
|
|
||||
|
- include: gen_kube_master_certs.yml |
||||
|
when: inventory_hostname in groups["kube-master"] |
||||
|
- include: gen_kube_node_certs.yml |
||||
|
when: inventory_hostname in groups["k8s-cluster"] |
@ -0,0 +1,23 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: cluster/pki_mount | Test if default PKI mount exists |
||||
|
uri: |
||||
|
url: "https://localhost:{{ vault_port }}/v1/sys/mounts/pki/tune" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
validate_certs: false |
||||
|
ignore_errors: true |
||||
|
register: vault_pki_mount_check |
||||
|
|
||||
|
- name: cluster/pki_mount | Mount default PKI mount if needed |
||||
|
uri: |
||||
|
url: "https://localhost:{{ vault_port }}/v1/sys/mounts/pki" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
config: |
||||
|
default_lease_ttl: "{{ vault_default_lease_ttl }}" |
||||
|
max_lease_ttl: "{{ vault_max_lease_ttl }}" |
||||
|
type: pki |
||||
|
status_code: 204 |
||||
|
when: vault_pki_mount_check | failed |
@ -0,0 +1,38 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: cluster/sync_kube_master_certs | Create list of needed certs |
||||
|
set_fact: |
||||
|
vault_kube_master_cert_list: >- |
||||
|
{{ vault_kube_master_cert_list|default([]) + [ |
||||
|
"admin-" + item + ".pem", |
||||
|
"apiserver-" + item + ".pem" |
||||
|
] }} |
||||
|
with_items: "{{ groups['kube-master'] }}" |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "{{ item }}" |
||||
|
sync_file_dir: "{{ kube_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['kube-master'] }}" |
||||
|
sync_file_is_cert: true |
||||
|
with_items: "{{ vault_kube_master_cert_list|default([]) }}" |
||||
|
|
||||
|
- name: cluster/sync_kube_master_certs | Set facts for kube-master sync_file results |
||||
|
set_fact: |
||||
|
vault_kube_master_certs_needed: "{{ vault_kube_master_certs_needed|default([]) + [item.path] }}" |
||||
|
with_items: "{{ sync_file_results }}" |
||||
|
when: item.no_srcs|bool |
||||
|
|
||||
|
- name: cluster/sync_kube_master_certs | Unset sync_file_results after kube master certs |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: ca.pem |
||||
|
sync_file_dir: "{{ kube_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['kube-master'] }}" |
||||
|
|
||||
|
- name: cluster/sync_kube_master_certs | Unset sync_file_results after ca.pem |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
@ -0,0 +1,34 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: cluster/sync_kube_node_certs | Create list of needed certs |
||||
|
set_fact: |
||||
|
vault_kube_node_cert_list: "{{ vault_kube_node_cert_list|default([]) + ['node-' + item + '.pem'] }}" |
||||
|
with_items: "{{ groups['k8s-cluster'] }}" |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: "{{ item }}" |
||||
|
sync_file_dir: "{{ kube_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['k8s-cluster'] }}" |
||||
|
sync_file_is_cert: true |
||||
|
with_items: "{{ vault_kube_node_cert_list|default([]) }}" |
||||
|
|
||||
|
- name: cluster/sync_kube_node_certs | Set facts for kube-master sync_file results |
||||
|
set_fact: |
||||
|
vault_kube_node_certs_needed: "{{ vault_kube_node_certs_needed|default([]) + [item.path] }}" |
||||
|
with_items: "{{ sync_file_results }}" |
||||
|
when: item.no_srcs|bool |
||||
|
|
||||
|
- name: cluster/sync_kube_node_certs | Unset sync_file_results after kube node certs |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
||||
|
|
||||
|
- include: ../sync_file.yml |
||||
|
vars: |
||||
|
sync_file: ca.pem |
||||
|
sync_file_dir: "{{ kube_cert_dir }}" |
||||
|
sync_file_hosts: "{{ groups['k8s-cluster'] }}" |
||||
|
|
||||
|
- name: cluster/sync_kube_node_certs | Unset sync_file_results after ca.pem |
||||
|
set_fact: |
||||
|
sync_file_results: [] |
@ -0,0 +1,26 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: cluster/unseal | Unseal Vault |
||||
|
uri: |
||||
|
url: "https://localhost:{{ vault_port }}/v1/sys/unseal" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
key: "{{ item }}" |
||||
|
with_items: "{{ vault_unseal_keys|default([]) }}" |
||||
|
when: vault_is_sealed |
||||
|
|
||||
|
- name: cluster/unseal | Find the current leader |
||||
|
uri: |
||||
|
url: "https://localhost:{{ vault_port }}/v1/sys/health" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: HEAD |
||||
|
status_code: 200,429 |
||||
|
register: vault_leader_check |
||||
|
|
||||
|
- name: cluster/unseal | Set fact for current leader |
||||
|
set_fact: |
||||
|
vault_leader: "{{ item }}" |
||||
|
with_items: "{{ groups.vault }}" |
||||
|
when: 'hostvars[item]["vault_leader_check"]["status"] == 200' |
@ -0,0 +1,19 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: config_ca | Read root CA cert for Vault |
||||
|
command: cat /etc/vault/ssl/ca.pem |
||||
|
register: vault_ca_cert_cat |
||||
|
|
||||
|
- name: config_ca | Read root CA key for Vault |
||||
|
command: cat /etc/vault/ssl/ca-key.pem |
||||
|
register: vault_ca_key_cat |
||||
|
|
||||
|
- name: config_ca | Configure pki mount to use the found root CA cert and key |
||||
|
uri: |
||||
|
url: "{{ vault_url }}/v1/pki/config/ca" |
||||
|
headers: "{{ vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
pem_bundle: "{{ vault_ca_cert_cat.stdout + '\n' + vault_ca_key_cat.stdout }}" |
||||
|
status_code: 204 |
@ -0,0 +1,50 @@ |
|||||
|
--- |
||||
|
|
||||
|
# This could be a role or custom module |
||||
|
|
||||
|
- name: gen_cert | Ensure target directory exists |
||||
|
file: |
||||
|
path: "{{ gen_cert_path | dirname }}" |
||||
|
state: directory |
||||
|
|
||||
|
- name: gen_cert | Generate the cert |
||||
|
uri: |
||||
|
url: "{{ gen_cert_vault_url}}/v1/pki/issue/{{ gen_cert_vault_role }}" |
||||
|
headers: "{{ gen_cert_vault_headers }}" |
||||
|
method: POST |
||||
|
body_format: json |
||||
|
body: |
||||
|
alt_names: "{{ gen_cert_alt_names|default([]) }}" |
||||
|
common_name: "{{ gen_cert_path.rsplit('/', 1)[1].rsplit('.', 1)[0] }}" |
||||
|
format: "{{ gen_cert_format|default('pem') }}" |
||||
|
ip_sans: "{{ gen_cert_ip_sans|default([]) }}" |
||||
|
register: gen_cert_result |
||||
|
when: inventory_hostname == gen_cert_hosts|first |
||||
|
|
||||
|
- name: gen_cert | Copy the cert to all hosts |
||||
|
copy: |
||||
|
content: "{{ hostvars[gen_cert_hosts|first]['gen_cert_result']['json']['data']['certificate'] }}" |
||||
|
dest: "{{ gen_cert_path }}" |
||||
|
|
||||
|
- name: gen_cert | Copy the key to all hosts |
||||
|
copy: |
||||
|
content: "{{ hostvars[gen_cert_hosts|first]['gen_cert_result']['json']['data']['private_key'] }}" |
||||
|
dest: "{{ gen_cert_path.rsplit('.', 1)|first + '-key.' + gen_cert_path.rsplit('.', 1)|last }}" |
||||
|
|
||||
|
- name: gen_cert | Copy issuing CA cert |
||||
|
copy: |
||||
|
content: "{{ hostvars[gen_cert_hosts|first]['gen_cert_result']['json']['data']['issuing_ca'] }}" |
||||
|
dest: "{{ gen_cert_path | dirname }}/ca.pem" |
||||
|
when: gen_cert_copy_ca|default(false)|bool |
||||
|
|
||||
|
- name: gen_cert | Unset common variables to avoid bleed over |
||||
|
set_fact: |
||||
|
gen_cert_copy_ca: false |
||||
|
gen_cert_alt_names: [] |
||||
|
gen_cert_format: pem |
||||
|
gen_cert_hosts: [] |
||||
|
gen_cert_ip_sans: [] |
||||
|
gen_cert_path: '' |
||||
|
gen_cert_vault_headers: '' |
||||
|
gen_cert_vault_role: '' |
||||
|
gen_cert_vault_url: '' |
@ -0,0 +1,13 @@ |
|||||
|
--- |
||||
|
|
||||
|
- include: check_vault.yml |
||||
|
when: inventory_hostname in groups.vault |
||||
|
|
||||
|
# bootstrap.yml's sole purpose is to ensure certs exist for Vault and Etcd |
||||
|
# prior to startup, so TLS can be enabled. |
||||
|
- include: bootstrap/main.yml |
||||
|
when: vault_bootstrap|bool |
||||
|
|
||||
|
# cluster.yml should only run after the backend service is ready (default etcd) |
||||
|
- include: cluster/main.yml |
||||
|
when: not vault_bootstrap|bool |
@ -0,0 +1,38 @@ |
|||||
|
--- |
||||
|
|
||||
|
- name: "sync_file | Cat the file" |
||||
|
command: "cat {{ sync_file_path }}" |
||||
|
register: sync_file_cat |
||||
|
when: inventory_hostname == sync_file_srcs|first |
||||
|
|
||||
|
- name: "sync_file | Cat the key file" |
||||
|
command: "cat {{ sync_file_key_path }}" |
||||
|
register: sync_file_key_cat |
||||
|
when: sync_file_is_cert|bool and inventory_hostname == sync_file_srcs|first |
||||
|
|
||||
|
- name: "sync_file | Set facts for file contents" |
||||
|
set_fact: |
||||
|
sync_file_contents: "{{ hostvars[sync_file_srcs|first]['sync_file_cat']['stdout'] }}" |
||||
|
|
||||
|
- name: "sync_file | Set fact for key contents" |
||||
|
set_fact: |
||||
|
sync_file_key_contents: "{{ hostvars[sync_file_srcs|first]['sync_file_key_cat']['stdout'] }}" |
||||
|
when: sync_file_is_cert|bool |
||||
|
|
||||
|
- name: "sync_file | Ensure the directory exists" |
||||
|
file: |
||||
|
path: "{{ sync_file_dir }}" |
||||
|
state: directory |
||||
|
when: inventory_hostname not in sync_file_srcs |
||||
|
|
||||
|
- name: "sync_file | Copy the file to hosts that don't have it" |
||||
|
copy: |
||||
|
content: "{{ sync_file_contents }}" |
||||
|
dest: "{{ sync_file_path }}" |
||||
|
when: inventory_hostname not in sync_file_srcs |
||||
|
|
||||
|
- name: "sync_file | Copy the key file to hosts that don't have it" |
||||
|
copy: |
||||
|
content: "{{ sync_file_key_contents }}" |
||||
|
dest: "{{ sync_file_key_path }}" |
||||
|
when: sync_file_is_cert|bool and inventory_hostname not in sync_file_srcs |
@ -0,0 +1,97 @@ |
|||||
|
--- |
||||
|
|
||||
|
# NOTE: This should be a role (or custom module), but currently include_role is too buggy to use |
||||
|
|
||||
|
- name: "sync_file | Set facts for directory and file when sync_file_path is defined" |
||||
|
set_fact: |
||||
|
sync_file_dir: "{{ sync_file_path | dirname }}" |
||||
|
sync_file: "{{ sync_file_path | basename }}" |
||||
|
when: sync_file_path|bool |
||||
|
|
||||
|
- name: "sync_file | Set fact for sync_file_path when undefined" |
||||
|
set_fact: |
||||
|
sync_file_path: "{{ (sync_file_dir, sync_file)|join('/') }}" |
||||
|
when: not sync_file_path|bool |
||||
|
|
||||
|
- name: "sync_file | Set fact for key path name" |
||||
|
set_fact: |
||||
|
sync_file_key_path: "{{ sync_file_path.rsplit('.', 1)|first + '-key.' + sync_file_path.rsplit('.', 1)|last }}" |
||||
|
when: sync_file_is_cert|bool and not sync_file_key_path|bool |
||||
|
|
||||
|
- name: "sync_file | Check if file exists" |
||||
|
stat: |
||||
|
path: "{{ sync_file_path }}" |
||||
|
register: sync_file_stat |
||||
|
|
||||
|
- name: "sync_file | Check if key file exists" |
||||
|
stat: |
||||
|
path: "{{ sync_file_key_path }}" |
||||
|
register: sync_file_key_stat |
||||
|
when: sync_file_is_cert|bool |
||||
|
|
||||
|
- name: "sync_file | Combine all possible file sync sources" |
||||
|
set_fact: |
||||
|
sync_file_srcs: "{{ sync_file_srcs|default([]) + [host_item] }}" |
||||
|
with_items: "{{ sync_file_hosts | unique }}" |
||||
|
loop_control: |
||||
|
loop_var: host_item |
||||
|
when: hostvars[host_item]["sync_file_stat"]["stat"]["exists"]|bool |
||||
|
|
||||
|
- name: "sync_file | Combine all possible key file sync sources" |
||||
|
set_fact: |
||||
|
sync_file_key_srcs: "{{ sync_file_key_srcs|default([]) + [host_item] }}" |
||||
|
with_items: "{{ sync_file_hosts | unique }}" |
||||
|
loop_control: |
||||
|
loop_var: host_item |
||||
|
when: sync_file_is_cert|bool and hostvars[host_item]["sync_file_key_stat"]["stat"]["exists"]|bool |
||||
|
|
||||
|
- name: "sync_file | Remove sync sources with files that do not match sync_file_srcs|first" |
||||
|
set_fact: |
||||
|
_: "{% if inventory_hostname in sync_file_srcs %}{{ sync_file_srcs.remove(inventory_hostname) }}{% endif %}" |
||||
|
when: >- |
||||
|
sync_file_srcs|length > 0 and |
||||
|
inventory_hostname != sync_file_srcs|first and |
||||
|
sync_file_stat.stat.get("checksum") != hostvars[sync_file_srcs|first]["sync_file_stat"]["stat"]["checksum"] |
||||
|
|
||||
|
- name: "sync_file | Remove sync sources with keys that do not match sync_file_srcs|first" |
||||
|
set_fact: |
||||
|
_: "{% if inventory_hostname in sync_file_srcs %}{{ sync_file_srcs.remove(inventory_hostname) }}{% endif %}" |
||||
|
when: >- |
||||
|
sync_file_is_cert|bool and |
||||
|
sync_file_key_srcs|length > 0 and |
||||
|
inventory_hostname != sync_file_srcs|first and |
||||
|
sync_file_key_stat.stat.checksum != hostvars[sync_file_srcs|first]["sync_file_key_stat"]["stat"]["checksum"] |
||||
|
|
||||
|
- name: "sync_file | Consolidate file and key sources" |
||||
|
set_fact: |
||||
|
sync_file_srcs: "{{ sync_file_srcs | intersect(sync_file_key_srcs) }}" |
||||
|
when: sync_file_is_cert|bool |
||||
|
|
||||
|
- name: "sync_file | Set facts for situations where sync is not needed" |
||||
|
set_fact: |
||||
|
sync_file_no_srcs: "{{ true if sync_file_srcs|length == 0 else false }}" |
||||
|
sync_file_unneeded: "{{ true if sync_file_srcs|length == sync_file_hosts|length else false }}" |
||||
|
|
||||
|
- name: "sync_file | Set sync_file_result fact" |
||||
|
set_fact: |
||||
|
sync_file_result: |
||||
|
no_srcs: "{{ sync_file_no_srcs }}" |
||||
|
path: "{{ sync_file_path }}" |
||||
|
sync_unneeded: "{{ sync_file_unneeded }}" |
||||
|
|
||||
|
- name: "sync_file | Update sync_file_results fact" |
||||
|
set_fact: |
||||
|
sync_file_results: "{{ sync_file_results|default([]) + [sync_file_result] }}" |
||||
|
|
||||
|
- include: sync.yml |
||||
|
when: not (sync_file_no_srcs or sync_file_unneeded) |
||||
|
|
||||
|
- name: "Unset local vars to avoid variable bleed into next iteration" |
||||
|
set_fact: |
||||
|
sync_file_dir: '' |
||||
|
sync_file: '' |
||||
|
sync_file_key_path: '' |
||||
|
sync_file_hosts: [] |
||||
|
sync_file_path: '' |
||||
|
sync_file_srcs: [] |
||||
|
sync_file_key_srcs: [] |
Write
Preview
Loading…
Cancel
Save