Add openldap certificate creation to bootstrap.yml

This change adds the openldap certificate creation process to the
bootstrap.yml playbook. It also adds support for updating it to
the migrate_platform_certificates_to_certmanager playbook.

This change is also renaming the kubernetes Root CA's common name to
starlingx, so that it can be used as the system_local_ca clusterIssuer
which will be used as the Issuer of the openldap certificate.

Test Plan:
PASS: Run the bootstrap playbook and verify that it is able to create
      the openldap certificate and install system_root_ca as a ssl_ca
      certificate in 'system certificate-list'
PASS  Do system unlock and verify that cert-mon is able to pick up and
      install the openldap certificate
PASS: Test migrate_platform_certificates_to_certmanager and verify that
      it is able to update the openldap certificate
PASS: On a DC system (centos only), verify that the bootstrap.yml
      playbook works for 'dcmanager subcloud add'
PASS: On a DC system (centos only), verify that the openldap certificate
      in not created in subclouds
PASS: Verified that the bootstrap.yml playbook can be re-played
      multiple times without error
PASS: Verify remote system bootstrap for debian works

Story: 2009834
Task: 45774

Signed-off-by: Rei Oliveira <Reinildes.JoseMateusOliveira@windriver.com>
Change-Id: Ie4c37026c9d5d4864dfea6fff3f066f3735c9fe2
This commit is contained in:
Rei Oliveira 2022-07-18 14:36:25 -03:00
parent ce510c7b9d
commit 1a1ac09dfd
14 changed files with 238 additions and 83 deletions

View File

@ -4,10 +4,33 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# This is an example inventory file to be used for
# usr/share/ansible/stx-ansible/playbooks/migrate_platform_certificates_to_certmanager.yml
# playbook.
#
# To run the playbook, the user would define an overrides file (as exemplified here)
# providing the required variable settings and pass it on the ansible command-line as a parameter.
#
# Example ansible command:
# ansible-playbook migrate_platform_certificates_to_certmanager.yml \
# -i @my-inventory-file.yml \
# --extra-vars "target_list=subcloud1 mode=update"
# Use target_list to target individual subclouds, or a comma-separated
# list of subclouds such as 'subcloud1,subcloud2'. To target all online
# subclouds at once use target_list=all_online_subclouds
#
# To target the system controller or standalone systems use target_list=localhost
#
# Note on the example parameters below :
#
# Parameter system_local_ca_cert will be the certificate that will be used as the
# issuer for platform certificates (registry.local, https / rest-api, oidc)
#
# Please make sure that you use a root_ca_cert and system_local_ca_cert certificate
# If system_local_ca_cert is an Intermediate CA (recommended), make sure that
# system_root_ca_cert is the Root CA which is its Issuer.
#
# Please make sure that you use a system_root_ca_cert and system_local_ca_cert certificate
# with a long duration. The playbook will fail if any of these CA certificates expire in
# less than 3 years.
#
@ -15,19 +38,23 @@
# it by setting a different value to validation parameter ca_duration:
# Example:
# ca_duration: 2
# Notice that ca_duration is applied to both root_ca_cert and system_local_ca_cert
# Notice that ca_duration is applied to both system_root_ca_cert and system_local_ca_cert
#
# Please also make sure that duration and renewBefore are sensible values
# considering the system_local_ca_cert remaining duration.
#
# See: https://docs.starlingx.io/security/kubernetes/migrate-platform-certificates-to-use-cert-manager-c0b1727e4e5d.html
#
all:
vars:
root_ca_cert: <base64_cert>
# It's strongly recommended using an Intermediate CA for system-local-ca_cert
# If using an Intermediate CA for system_local_ca_cert (recommended), the value
# for system_root_ca_cert needs to be the Root CA which is the Issuer of system_local_ca_cert
system_root_ca_cert: <base64_cert>
# It's strongly recommended using an Intermediate CA for system_local_ca_cert
# as that has the advantages of anchoring your certificates to your external Root CA.
# However, it is possible to simply specify a Root CA for system-local-ca_cert.
# However, it is possible to simply specify a Root CA for system_local_ca_cert.
# For that, specify system_local_ca_cert and system_local_ca_key with values from your Root CA.
# Note that system_local_ca_cert and root_ca_cert must be the same for that configuration.
# Note: system_local_ca_cert and system_root_ca_cert must be the same for that configuration.
system_local_ca_cert: <base64_cert>
system_local_ca_key: <base64_key>
# the ca_duration parameter is optional. If not specified, it defaults to 3.
@ -40,16 +67,17 @@ all:
# Use the below example in hosts to override particulars for a subcloud such as passwords
target_group:
vars:
dns_domain: xyz.com
duration: 2160h # 90d
renewBefore: 360h # 15d
subject_C: canada
subject_ST: ontario
subject_L: ottawa
subject_O: myorganization
subject_OU: engineering
subject_CN: myorganization.com
subject_prefix: starlingx
system_platform_certificate:
dns_domain: xyz.com
duration: 2160h # 90d
renewBefore: 360h # 15d
subject_C: canada
subject_ST: ontario
subject_L: ottawa
subject_O: myorganization
subject_OU: engineering
subject_CN: myorganization.com
subject_prefix: starlingx
# SSH password to connect to all subclouds
ansible_ssh_user: sysadmin
ansible_ssh_pass: <sysadmin-pwd>

View File

@ -1,6 +1,6 @@
---
#
# Copyright (c) 2019 Wind River Systems, Inc.
# Copyright (c) 2019-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -24,6 +24,8 @@
- { role: bootstrap/persist-config, become: yes }
- { role: bootstrap/bringup-essential-services, become: yes }
- { role: bootstrap/bringup-bootstrap-applications, become: yes }
- { role: bootstrap/install-platform-certificates, become: yes }
- { role: bootstrap/complete-bootstrap, become: yes }
vars:
replayed: false

View File

@ -79,10 +79,10 @@
tasks:
- name: Install certificates as system Trusted CA certificates
include_role:
name: migrate-platform-certificates-to-certmanager/install-trusted-ca
name: common/install-trusted-ca
with_items:
- { name: system_local_ca_cert, content: "{{ system_local_ca_cert }}" }
- { name: root_ca_cert, content: "{{ root_ca_cert }}" }
- { name: system_root_ca_cert, content: "{{ system_root_ca_cert }}" }
loop_control:
label: "{{ item.name }}"

View File

@ -1,6 +1,6 @@
---
#
# Copyright (c) 2020-21 Wind River Systems, Inc.
# Copyright (c) 2020-2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
@ -157,8 +157,3 @@
# Nested dictionaries are picky about having things on the same line
- "prev_docker_registries: "
- "{{ docker_registries | to_yaml }}"
- name: Mark the bootstrap as completed
file:
path: "{{ bootstrap_completed_flag }}"
state: touch

View File

@ -104,7 +104,7 @@
openssl_csr:
path: "{{ kubeadm_pki_dir }}/ca.csr"
privatekey_path: "{{ kubeadm_pki_dir }}/ca.key"
common_name: kubernetes
common_name: starlingx
basic_constraints:
- CA:TRUE
- pathlen:1

View File

@ -0,0 +1,13 @@
---
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# Task to mark the playbook as complete.
# It indicates that the controller was successfully bootstrapped.
#
- name: Mark the bootstrap as completed
file:
path: "{{ bootstrap_completed_flag }}"
state: touch

View File

@ -0,0 +1,62 @@
---
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# These tasks get information from the running system and use it to
# generate a certificate spec file which is going to be applied to
# kubernetes at a later step
#
- name: Read kubernetes Root CA certificate
shell: cat "{{ kubeadm_pki_dir }}/ca.crt" | base64 -w0
register: kubernetes_root_ca_crt
become: true
- name: Read kubernetes Root CA key
shell: cat "{{ kubeadm_pki_dir }}/ca.key" | base64 -w0
register: kubernetes_root_ca_key
become: true
- name: Set Root CA and local CA based on kubernetes Root CA
set_fact:
system_root_ca_cert: "{{ kubernetes_root_ca_crt.stdout }}"
system_local_ca_cert: "{{ kubernetes_root_ca_crt.stdout }}"
system_local_ca_key: "{{ kubernetes_root_ca_key.stdout }}"
- name: Get distributed_cloud role
shell: |
source /etc/platform/openrc
system show | grep distributed_cloud_role | awk '{ print $4 }'
register: distributed_cloud_role
- name: Set which platform certificates to install
set_fact:
install_oidc_auth_apps_certificate: false
install_system_open_ldap_certificate: "{{ true if distributed_cloud_role.stdout == 'systemcontroller' else false }}"
install_system_registry_local_certificate: false
install_system_restapi_gui_certificate: false
- name: Generate kubernetes yaml for cert-manager resources
include_role:
name: common/generate-platform-certificates-template
vars:
destination: /tmp/platform_certificates.yaml
- name: Install system_root_ca_cert as system Trusted CA certificate
include_role:
name: common/install-trusted-ca
with_items:
- { name: system_root_ca_cert, content: "{{ system_root_ca_cert }}" }
loop_control:
label: "{{ item.name }}"
- name: Apply kubernetes yaml to create cert-manager clusterissuer and certificates
command: kubectl apply -f /tmp/platform_certificates.yaml
environment:
KUBECONFIG: /etc/kubernetes/admin.conf
register: create_k8_apply_ep
until: create_k8_apply_ep is not failed
retries: 10
delay: 30

View File

@ -0,0 +1,11 @@
---
#
# Copyright (c) 2022 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
ca_duration: 3
system_platform_certificate:
dns_domain: starlingx.local
duration: 2160h # 90d
renewBefore: 360h # 15d

View File

@ -16,7 +16,17 @@
- name: Get floating management ip
shell: |
echo "{{ address_table.stdout }}" | awk '$4 == "management" { print $14 }'
register: management_ip
register: management_floating_ip
- name: Get controller0 floating management ip
shell: |
echo "{{ address_table.stdout }}" | awk '$4 == "management" { print $16 }'
register: management_c0_ip
- name: Get controller1 floating management ip
shell: |
echo "{{ address_table.stdout }}" | awk '$4 == "management" { print $18 }'
register: management_c1_ip
- name: Get floating oam ip
shell: |
@ -42,7 +52,7 @@
shell: |
source /etc/platform/openrc
system show | grep region_name | awk '{ print $4 }'
register: region_name
register: region_name_register
- name: Get distributed_cloud role
shell: |

View File

@ -1,5 +1,5 @@
## strips out any bad character from region name. Only [^A-Za-z0-9-]" is supported
{% set clean_region_name = region_name.stdout | replace("_", "-") | regex_replace("[^A-Za-z0-9-]","") | lower %}
{% set clean_region_name = region_name_register.stdout | replace("_", "-") | regex_replace("[^A-Za-z0-9-]","") | lower %}
---
apiVersion: v1
data:
@ -23,6 +23,7 @@ items:
secretName: system-local-ca
status: {}
{% if install_system_restapi_gui_certificate | bool %}
{% set short_certificate_name = 'system-restapi-gui' %}
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
@ -32,30 +33,20 @@ items:
spec:
commonName: "{{ oam_ip.stdout }}"
dnsNames:
- "{{ clean_region_name }}.{{ dns_domain }}"
duration: "{{ duration }}"
- "{{ clean_region_name }}.{{ system_platform_certificate.dns_domain }}"
duration: "{{ system_platform_certificate.duration }}"
ipAddresses:
- "{{ oam_ip.stdout }}"
issuerRef:
kind: ClusterIssuer
name: system-local-ca
renewBefore: "{{ renewBefore }}"
renewBefore: "{{ system_platform_certificate.renewBefore }}"
secretName: system-restapi-gui-certificate
subject:
countries:
- "{{ subject_C }}"
localities:
- "{{ subject_L }}"
- "{{ subject_prefix + ':' if subject_prefix is defined else '' }}{{ clean_region_name }}:system-restapi-gui"
organizationalUnits:
- "{{ subject_OU }}"
organizations:
- "{{ subject_O }}"
provinces:
- "{{ subject_ST }}"
{% include 'subject_snippet.j2' %}
status: {}
{% endif %}
{% if install_system_registry_local_certificate | bool %}
{% set short_certificate_name = 'system-registry-local' %}
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
@ -65,35 +56,25 @@ items:
spec:
commonName: "{{ oam_ip.stdout }}"
dnsNames:
- "{{ clean_region_name }}.{{ dns_domain }}"
- "{{ clean_region_name }}.{{ system_platform_certificate.dns_domain }}"
- registry.local
{% if distributed_cloud_role.stdout == 'systemcontroller' %}
- registry.central
{% endif %}
duration: "{{ duration }}"
duration: "{{ system_platform_certificate.duration }}"
ipAddresses:
- "{{ oam_ip.stdout }}"
- "{{ management_ip.stdout }}"
- "{{ management_floating_ip.stdout }}"
issuerRef:
kind: ClusterIssuer
name: system-local-ca
renewBefore: "{{ renewBefore }}"
renewBefore: "{{ system_platform_certificate.renewBefore }}"
secretName: system-registry-local-certificate
subject:
countries:
- "{{ subject_C }}"
localities:
- "{{ subject_L }}"
- "{{ subject_prefix + ':' if subject_prefix is defined else '' }}{{ clean_region_name }}:system-registry-local"
organizationalUnits:
- "{{ subject_OU }}"
organizations:
- "{{ subject_O }}"
provinces:
- "{{ subject_ST }}"
{% include 'subject_snippet.j2' %}
status: {}
{% endif %}
{% if install_oidc_auth_apps_certificate | bool %}
{% set short_certificate_name = 'system-oidc-dex' %}
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
@ -103,8 +84,8 @@ items:
spec:
commonName: "{{ oam_ip.stdout }}"
dnsNames:
- "{{ clean_region_name }}.{{ dns_domain }}"
duration: "{{ duration }}"
- "{{ clean_region_name }}.{{ system_platform_certificate.dns_domain }}"
duration: "{{ system_platform_certificate.duration }}"
ipAddresses:
- "{{ oam_ip.stdout }}"
# Add kubernetes cluster ip to make sure certificate has issuer ip in san list
@ -115,20 +96,35 @@ items:
issuerRef:
kind: ClusterIssuer
name: system-local-ca
renewBefore: "{{ renewBefore }}"
renewBefore: "{{ system_platform_certificate.renewBefore }}"
secretName: oidc-auth-apps-certificate
subject:
countries:
- "{{ subject_C }}"
localities:
- "{{ subject_L }}"
- "{{ subject_prefix + ':' if subject_prefix is defined else '' }}{{ clean_region_name }}:system-oidc-dex"
organizationalUnits:
- "{{ subject_OU }}"
organizations:
- "{{ subject_O }}"
provinces:
- "{{ subject_ST }}"
{% include 'subject_snippet.j2' %}
status: {}
{% endif %}
{% if install_system_open_ldap_certificate | bool %}
{% set short_certificate_name = 'system-openldap' %}
- apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
creationTimestamp: null
name: system-openldap-local-certificate
namespace: deployment
spec:
commonName: "{{ short_certificate_name }}"
dnsNames:
- "{{ clean_region_name }}.{{ system_platform_certificate.dns_domain }}"
- controller
duration: "{{ system_platform_certificate.duration }}"
ipAddresses:
- "{{ management_floating_ip.stdout }}"
- "{{ management_c0_ip.stdout }}"
- "{{ management_c1_ip.stdout }}"
issuerRef:
kind: ClusterIssuer
name: system-local-ca
renewBefore: "{{ system_platform_certificate.renewBefore }}"
secretName: system-openldap-local-certificate
{% include 'subject_snippet.j2' %}
status: {}
{% endif %}
kind: List

View File

@ -0,0 +1,24 @@
{% if system_platform_certificate is defined %}
subject:
{% if system_platform_certificate.subject_C is defined %}
countries:
- "{{ system_platform_certificate.subject_C }}"
{% endif %}
{% if system_platform_certificate.subject_ST is defined %}
provinces:
- "{{ system_platform_certificate.subject_ST }}"
{% endif %}
{% if system_platform_certificate.subject_L is defined %}
localities:
- "{{ system_platform_certificate.subject_L }}"
- "{{ system_platform_certificate.subject_prefix + ':' if system_platform_certificate.subject_prefix is defined else '' }}{{ clean_region_name }}:{{ short_certificate_name }}"
{% endif %}
{% if system_platform_certificate.subject_O is defined %}
organizations:
- "{{ system_platform_certificate.subject_O }}"
{% endif %}
{% if system_platform_certificate.subject_OU is defined %}
organizationalUnits:
- "{{ system_platform_certificate.subject_OU }}"
{% endif %}
{% endif %}

View File

@ -11,18 +11,19 @@
shell: echo "{{ item.content }}" | base64 -d > /tmp/ca.pem
- block:
- name: Check if system_local_ca_cert is signed by root_ca_cert or self-signed
- name: Check if system_local_ca_cert is signed by system_root_ca_cert or self-signed
shell: |
echo "{{ root_ca_cert }}" | base64 -d > /tmp/root.pem
echo "{{ system_root_ca_cert }}" | base64 -d > /tmp/root.pem
openssl verify -verbose -CAfile /tmp/root.pem /tmp/ca.pem
register: ca_verification
# failed_when as false in order to print a better error msg in the task below
failed_when: false
- name: Fail when system_local_ca_cert is not signed by root_ca_cert or self-signed
- name: Fail when system_local_ca_cert is not signed by system_root_ca_cert or self-signed
fail:
msg: |
The system_local_ca_cert provided is not signed by root_ca_cert provided or self-signed.
The system_local_ca_cert provided is not signed by
system_root_ca_cert provided or self-signed.
Please review your inventory parameters.
when: ca_verification.rc | int != 0
when: item.name == 'system_local_ca_cert'

View File

@ -20,7 +20,14 @@
awk '{ if ($0 == "applied") print "true"; else print "false"; }'
register: oidc_applied
- name: Check if openldap certificate exists
shell: |
source /etc/platform/openrc
system certificate-list | grep openldap
register: openldap_certificate_exists
- set_fact:
install_oidc_auth_apps_certificate: "{{ true if oidc_applied.stdout | bool else false }}"
install_system_open_ldap_certificate: "{{ true if openldap_certificate_exists.stdout | int == 0 else false }}"
install_system_registry_local_certificate: true
install_system_restapi_gui_certificate: "{{ true if https_enabled.stdout | bool else false }}"
install_oidc_auth_apps_certificate: "{{ true if oidc_applied.stdout | bool else false }}"

View File

@ -57,7 +57,7 @@
- name: Generate kubernetes yaml for cert-manager resources
include_role:
name: common/generate-platform-certificates
name: common/generate-platform-certificates-template
vars:
destination: /tmp/platform_certificates.yaml
@ -73,16 +73,17 @@
- name: Force certificate renewals
include_tasks: delete-kubernetes-objects.yml
with_items:
- { secret: system-openldap-local-certificate, namespace: deployment, type: secret }
- { secret: system-registry-local-certificate, namespace: deployment, type: secret }
- { secret: system-restapi-gui-certificate, namespace: deployment, type: secret }
- { secret: oidc-auth-apps-certificate, namespace: kube-system, type: secret }
- name: Install certificates as system Trusted CA certificates
include_role:
name: migrate-platform-certificates-to-certmanager/install-trusted-ca
name: common/install-trusted-ca
with_items:
- { name: system_local_ca_cert, content: "{{ system_local_ca_cert }}" }
- { name: root_ca_cert, content: "{{ root_ca_cert }}" }
- { name: system_root_ca_cert, content: "{{ system_root_ca_cert }}" }
loop_control:
label: "{{ item.name }}"
@ -173,5 +174,10 @@
namespace: kube-system,
should_run: "{{oidc_applied.stdout}}"
}
- {
secret: system-openldap-local-certificate,
namespace: deployment,
should_run: "{{ true if openldap_certificate_exists.stdout | int == 0 else false }}"
}
when: mode == 'check'