Commit b2856e22 authored by ale's avatar ale

Refactor the credentials role

Separate a base "credentials" role and a "float-credentials" one that
instantiates the float-derived service credentials. This allows users
to install credentials from Ansible roles that do not have a
corresponding float service.
parent d49df5dc
Pipeline #6759 passed with stage
in 3 minutes and 36 seconds
......@@ -3,7 +3,7 @@
- hosts: all
roles:
- base
- credentials
- float-credentials
- vagrant-compat
- hosts: net-overlay
......
......@@ -358,7 +358,6 @@ def _host_vars(name, inventory, services, assignments):
'float_disabled_services': [],
'float_enabled_containers': [],
'float_host_service_credentials': [],
'float_host_service_credentials_certs': [],
'float_host_overlay_networks': _host_net_overlays(name, inventory),
'float_host_dns_map': _host_service_dns_map(
name, inventory, services, assignments),
......@@ -366,8 +365,7 @@ def _host_vars(name, inventory, services, assignments):
# Add default client credentials that are present on all hosts.
for c in DEFAULT_SERVICE_CREDENTIALS:
hv['float_host_service_credentials'].append({'credentials': c})
hv['float_host_service_credentials_certs'].append({
hv['float_host_service_credentials'].append({
'credentials': c, 'service': 'LOCAL',
'mode': 'client', 'x509_params': {}})
......@@ -390,15 +388,13 @@ def _host_vars(name, inventory, services, assignments):
for u in services[s].get('systemd_services', []):
enabled_systemd_units.add(u)
for c in services[s].get('service_credentials', []):
hv['float_host_service_credentials'].append({
'service': s, 'credentials': c})
if c.get('enable_server', True):
params = _service_credential_params(name, s, inventory, assignments)
hv['float_host_service_credentials_certs'].append({
hv['float_host_service_credentials'].append({
'credentials': c, 'service': s,
'mode': 'server', 'x509_params': params})
if c.get('enable_client', True):
hv['float_host_service_credentials_certs'].append({
hv['float_host_service_credentials'].append({
'credentials': c, 'service': s,
'mode': 'client', 'x509_params': {}})
else:
......
......@@ -3,7 +3,24 @@ credentials
Ansible role that installs all the [service
credentials](../docs/service_mesh.md#mutual-service-authentication) on
the hosts where they're needed.
the hosts where they're needed. This role works in combination with
the 'x509' action plugin.
Private keys never leave the target host, we create a CSR and sign it
on the Ansible host.
X509 credentials are stored in /etc/credentials/x509 under directories
named after the services. Every service directory contains a copy of
the public CA certificate, so it can be bind-mounted in a container
easily.
Private keys have mode 440, are owned by root and by a dedicated group
named *service*-credentials. When the service is actually installed,
later, maybe by an Ansible role, it can add the service user to this
group.
Use by including this role and setting the *credentials* variable to a
list of entries specifying the desired credentials. This is already
done once system-wide by the *float-credentials* role with the
credentials automagically derived from the service definitions by
*float*.
---
#- set_fact:
# x509_params: "{{ float_service_credentials_params[service_name_item + '-' + credentials.name] | default({}) }}"
# when: "service_name_item is defined"
- name: Set up internal PKI credentials
block:
- file:
path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}"
state: directory
loop: "{{ float_host_service_credentials_certs }}"
- name: "Check the internal PKI certificates"
x509_csr:
credentials_name: "{{ item.credentials.name }}"
domain: "{{ domain }}"
mode: "{{ item.mode }}"
params: "{{ item.x509_params|default({}) }}"
private_key_path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/private_key.pem"
cert_path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/cert.pem"
ca_cert_path: "/etc/credentials/x509/{{ item.credentials.name }}/ca.pem"
check: true
loop: "{{ float_host_service_credentials_certs }}"
check_mode: no
register: x509_should_update
# TODO: set the right permissions (credentials.name-credentials)
- name: "Create internal PKI CSRs"
x509_csr:
credentials_name: "{{ item.0.credentials.name }}"
domain: "{{ domain }}"
mode: "{{ item.0.mode }}"
params: "{{ item.0.x509_params|default({}) }}"
private_key_path: "/etc/credentials/x509/{{ item.0.credentials.name }}/{{ item.0.mode }}/private_key.pem"
check: false
when: "item.1.changed"
loop: "{{ float_host_service_credentials_certs | zip(x509_should_update.results) | list }}"
register: x509_csr
- name: "Sign internal PKI certificates"
x509_sign:
csr: "{{ item.1.csr }}"
mode: "{{ item.0.mode }}"
ca_cert_path: "{{ credentials_dir }}/x509/ca.pem"
ca_key_path: "{{ credentials_dir }}/x509/ca_private_key.pem"
when: "item.1.changed"
loop: "{{ float_host_service_credentials_certs | zip(x509_csr.results) | list }}"
register: x509_sign
- name: "Install the signed internal PKI certificates"
copy:
dest: "/etc/credentials/x509/{{ item.0.credentials.name }}/{{ item.0.mode }}/cert.pem"
content: "{{ item.1.cert }}"
mode: 0644
when: "item.1.changed"
loop: "{{ float_host_service_credentials_certs | zip(x509_sign.results) | list }}"
- name: "Set permissions on the private keys"
file:
path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/private_key.pem"
group: "{{ item.credentials.name }}-credentials"
mode: 0640
loop: "{{ float_host_service_credentials_certs }}"
# This should use the systemd module but it doesn't take lists of services.
- name: "Restart associated services"
shell: "systemctl restart {{ services[item.0.service].systemd_services | join(' ') }}"
when: "item.1.changed"
loop: "{{ float_host_service_credentials_certs | zip(x509_sign.results) | list }}"
rescue:
- debug:
msg: "Failed to set up one or more credentials"
---
- name: "Create service credentials group"
group:
name: "{{ item.credentials.name }}-credentials"
system: true
loop: "{{ float_host_service_credentials }}"
- name: "Create service credentials dirs"
file:
path: "/etc/credentials/x509/{{ item.credentials.name }}"
state: directory
loop: "{{ float_host_service_credentials }}"
- name: Copy CA
copy:
src: "{{ credentials_dir }}/x509/ca.pem"
dest: "/etc/credentials/x509/{{ item.credentials.name }}/ca.pem"
owner: root
group: root
mode: 0644
loop: "{{ float_host_service_credentials }}"
---
# Distribute the SSO public key to all hosts.
# This package needs to be on hosts in order to generate the CSRs.
- name: Install x509ca package
apt:
name: x509ca
state: present
# Get the credential names from the list of certs.
- set_fact:
credentials_names: "{{ credentials | map(attribute='credentials') | map(attribute='name') | unique | list }}"
- file:
path: /etc/sso
- name: "Create service credentials group"
group:
name: "{{ item }}-credentials"
system: true
loop: "{{ credentials_names }}"
- name: "Create service credentials dirs"
file:
path: "/etc/credentials/x509/{{ item }}"
state: directory
owner: root
group: root
mode: 0755
loop: "{{ credentials_names }}"
- name: Install SSO public key
- name: Copy CA
copy:
src: "{{ credentials_dir }}/sso/public.key"
dest: /etc/sso/public.key
src: "{{ credentials_dir }}/x509/ca.pem"
dest: "/etc/credentials/x509/{{ item }}/ca.pem"
owner: root
group: root
mode: 0644
loop: "{{ credentials_names }}"
# Distribute X509 credentials to all hosts as needed. This role works
# in combination with the 'x509' action plugin.
# Create and sign all certificates in a series of loops (with some
# unfortunately complex change-detection logic).
- name: Set up internal PKI credentials
block:
# X509 credentials are stored in /etc/credentials/x509 under
# directories named after the services. Every service directory
# contains a copy of the public CA certificate, so it can be
# bind-mounted in a container easily.
- file:
path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}"
state: directory
loop: "{{ credentials }}"
# Private keys have mode 440, are owned by root and by a dedicated
# group named <service>-credentials. When the service is actually
# installed, later, maybe by an Ansible role, it can add the service
# user to this group.
- name: "Check the internal PKI certificates"
x509_csr:
credentials_name: "{{ item.credentials.name }}"
domain: "{{ domain }}"
mode: "{{ item.mode }}"
params: "{{ item.x509_params|default({}) }}"
private_key_path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/private_key.pem"
cert_path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/cert.pem"
ca_cert_path: "/etc/credentials/x509/{{ item.credentials.name }}/ca.pem"
check: true
loop: "{{ credentials }}"
check_mode: no
register: x509_should_update
- name: Install x509ca package
apt:
name: x509ca
state: present
# TODO: set the right permissions (credentials.name-credentials)
- name: "Create internal PKI CSRs"
x509_csr:
credentials_name: "{{ item.0.credentials.name }}"
domain: "{{ domain }}"
mode: "{{ item.0.mode }}"
params: "{{ item.0.x509_params|default({}) }}"
private_key_path: "/etc/credentials/x509/{{ item.0.credentials.name }}/{{ item.0.mode }}/private_key.pem"
check: false
when: "item.1.changed"
loop: "{{ credentials | zip(x509_should_update.results) | list }}"
register: x509_csr
- import_tasks: install_credentials.yml
- import_tasks: install_certs.yml
- name: "Sign internal PKI certificates"
x509_sign:
csr: "{{ item.1.csr }}"
mode: "{{ item.0.mode }}"
ca_cert_path: "{{ credentials_dir }}/x509/ca.pem"
ca_key_path: "{{ credentials_dir }}/x509/ca_private_key.pem"
when: "item.1.changed"
loop: "{{ credentials | zip(x509_csr.results) | list }}"
register: x509_sign
# Remove credentials that shouldn't be here.
# - file: path="/etc/credentials/x509/{{ item.1.name }}" state=absent
# with_subelements:
# - "{{ services }}"
# - service_credentials
# - { skip_missing: true }
- name: "Install the signed internal PKI certificates"
copy:
dest: "/etc/credentials/x509/{{ item.0.credentials.name }}/{{ item.0.mode }}/cert.pem"
content: "{{ item.1.cert }}"
mode: 0644
when: "item.1.changed"
loop: "{{ credentials | zip(x509_sign.results) | list }}"
# Create a group for public credentials.
- name: Create public-credentials group
group:
name: public-credentials
system: yes
- name: "Set permissions on the private keys"
file:
path: "/etc/credentials/x509/{{ item.credentials.name }}/{{ item.mode }}/private_key.pem"
group: "{{ item.credentials.name }}-credentials"
mode: 0640
loop: "{{ credentials }}"
# This should use the systemd module but it doesn't take lists of services.
- name: "Restart associated services"
shell: "systemctl restart {{ services[item.0.service].systemd_services | join(' ') }}"
when: "item.1.changed"
loop: "{{ credentials | zip(x509_sign.results) | list }}"
rescue:
- debug:
msg: "Failed to set up one or more credentials"
# Create the root directory for public credentials.
- file:
path: /etc/credentials/public
state: directory
This role includes the *credentials* role with the list of credentials
derived from the service descriptions in services.yml.
---
dependencies:
- role: credentials
vars:
credentials: "{{ float_host_service_credentials }}"
---
# Distribute the SSO public key to all hosts.
- file:
path: /etc/sso
state: directory
owner: root
group: root
mode: 0755
- name: Install SSO public key
copy:
src: "{{ credentials_dir }}/sso/public.key"
dest: /etc/sso/public.key
mode: 0644
# Create a group for public credentials.
- name: Create public-credentials group
group:
name: public-credentials
system: yes
# Create the root directory for public credentials.
- file:
path: /etc/credentials/public
state: directory
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment