summaryrefslogtreecommitdiffstats
path: root/roles/etcd
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2017-09-21 14:24:43 -0700
committerGitHub <noreply@github.com>2017-09-21 14:24:43 -0700
commitee8252d536c4204b9e0c4a88d0899297caf39423 (patch)
tree9c92bb13a285058e5b20bc76f33cb5d58c91ba9d /roles/etcd
parent505764651b3f8279ffe8881e9b26851d1dd14258 (diff)
parent99745a04223f2ed8111b5eb4b49d2bcfec9e678f (diff)
downloadopenshift-ee8252d536c4204b9e0c4a88d0899297caf39423.tar.gz
openshift-ee8252d536c4204b9e0c4a88d0899297caf39423.tar.bz2
openshift-ee8252d536c4204b9e0c4a88d0899297caf39423.tar.xz
openshift-ee8252d536c4204b9e0c4a88d0899297caf39423.zip
Merge pull request #5371 from ingvagabund/consolidate-etcd-certs-roles
Automatic merge from submit-queue consolidate etcd certs roles This is a starter for consolidation of all etcd like roles into a single `etcd` action-based role. I have intentionally started with the simplest one to demonstrate the steps needed to make it so and to make the review easy enough for everyone.
Diffstat (limited to 'roles/etcd')
-rw-r--r--roles/etcd/meta/main.yml1
-rw-r--r--roles/etcd/tasks/ca.yml2
-rw-r--r--roles/etcd/tasks/ca/deploy.yml78
-rw-r--r--roles/etcd/tasks/client_certificates.yml2
-rw-r--r--roles/etcd/tasks/client_certificates/fetch_from_ca.yml138
-rw-r--r--roles/etcd/tasks/main.yml2
-rw-r--r--roles/etcd/tasks/server_certificates.yml2
-rw-r--r--roles/etcd/tasks/server_certificates/fetch_from_ca.yml238
-rw-r--r--roles/etcd/templates/openssl_append.j251
9 files changed, 513 insertions, 1 deletions
diff --git a/roles/etcd/meta/main.yml b/roles/etcd/meta/main.yml
index 9a955c822..d69366a39 100644
--- a/roles/etcd/meta/main.yml
+++ b/roles/etcd/meta/main.yml
@@ -18,5 +18,4 @@ galaxy_info:
dependencies:
- role: lib_openshift
- role: lib_os_firewall
-- role: etcd_server_certificates
- role: etcd_common
diff --git a/roles/etcd/tasks/ca.yml b/roles/etcd/tasks/ca.yml
new file mode 100644
index 000000000..7cda49069
--- /dev/null
+++ b/roles/etcd/tasks/ca.yml
@@ -0,0 +1,2 @@
+---
+- include: ca/deploy.yml
diff --git a/roles/etcd/tasks/ca/deploy.yml b/roles/etcd/tasks/ca/deploy.yml
new file mode 100644
index 000000000..3d32290a2
--- /dev/null
+++ b/roles/etcd/tasks/ca/deploy.yml
@@ -0,0 +1,78 @@
+---
+- name: Install openssl
+ package:
+ name: openssl
+ state: present
+ when: not etcd_is_atomic | bool
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- file:
+ path: "{{ item }}"
+ state: directory
+ mode: 0700
+ owner: root
+ group: root
+ with_items:
+ - "{{ etcd_ca_new_certs_dir }}"
+ - "{{ etcd_ca_crl_dir }}"
+ - "{{ etcd_ca_dir }}/fragments"
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- command: cp /etc/pki/tls/openssl.cnf ./
+ args:
+ chdir: "{{ etcd_ca_dir }}/fragments"
+ creates: "{{ etcd_ca_dir }}/fragments/openssl.cnf"
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- template:
+ dest: "{{ etcd_ca_dir }}/fragments/openssl_append.cnf"
+ src: openssl_append.j2
+ backup: true
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- assemble:
+ src: "{{ etcd_ca_dir }}/fragments"
+ dest: "{{ etcd_openssl_conf }}"
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- name: Check etcd_ca_db exist
+ stat: path="{{ etcd_ca_db }}"
+ register: etcd_ca_db_check
+ changed_when: false
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- name: Touch etcd_ca_db file
+ file:
+ path: "{{ etcd_ca_db }}"
+ state: touch
+ when: etcd_ca_db_check.stat.isreg is not defined
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- copy:
+ dest: "{{ etcd_ca_serial }}"
+ content: "01"
+ force: no
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- name: Create etcd CA certificate
+ command: >
+ openssl req -config {{ etcd_openssl_conf }} -newkey rsa:4096
+ -keyout {{ etcd_ca_key }} -new -out {{ etcd_ca_cert }}
+ -x509 -extensions {{ etcd_ca_exts_self }} -batch -nodes
+ -days {{ etcd_ca_default_days }}
+ -subj /CN=etcd-signer@{{ ansible_date_time.epoch }}
+ args:
+ chdir: "{{ etcd_ca_dir }}"
+ creates: "{{ etcd_ca_cert }}"
+ environment:
+ SAN: 'etcd-signer'
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
diff --git a/roles/etcd/tasks/client_certificates.yml b/roles/etcd/tasks/client_certificates.yml
new file mode 100644
index 000000000..2e9c078b9
--- /dev/null
+++ b/roles/etcd/tasks/client_certificates.yml
@@ -0,0 +1,2 @@
+---
+- include: client_certificates/fetch_from_ca.yml
diff --git a/roles/etcd/tasks/client_certificates/fetch_from_ca.yml b/roles/etcd/tasks/client_certificates/fetch_from_ca.yml
new file mode 100644
index 000000000..119071a72
--- /dev/null
+++ b/roles/etcd/tasks/client_certificates/fetch_from_ca.yml
@@ -0,0 +1,138 @@
+---
+- name: Ensure CA certificate exists on etcd_ca_host
+ stat:
+ path: "{{ etcd_ca_cert }}"
+ register: g_ca_cert_stat_result
+ delegate_to: "{{ etcd_ca_host }}"
+ run_once: true
+
+- fail:
+ msg: >
+ CA certificate {{ etcd_ca_cert }} doesn't exist on CA host
+ {{ etcd_ca_host }}. Apply 'etcd_ca' action from `etcd` role to
+ {{ etcd_ca_host }}.
+ when: not g_ca_cert_stat_result.stat.exists | bool
+ run_once: true
+
+- name: Check status of external etcd certificatees
+ stat:
+ path: "{{ etcd_cert_config_dir }}/{{ item }}"
+ with_items:
+ - "{{ etcd_cert_prefix }}client.crt"
+ - "{{ etcd_cert_prefix }}client.key"
+ - "{{ etcd_cert_prefix }}ca.crt"
+ register: g_external_etcd_cert_stat_result
+ when: not etcd_certificates_redeploy | default(false) | bool
+
+- set_fact:
+ etcd_client_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool
+ else (False in (g_external_etcd_cert_stat_result.results
+ | default({})
+ | oo_collect(attribute='stat.exists')
+ | list)) }}"
+
+- name: Ensure generated_certs directory present
+ file:
+ path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ state: directory
+ mode: 0700
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Create the client csr
+ command: >
+ openssl req -new -keyout {{ etcd_cert_prefix }}client.key
+ -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}client.csr
+ -reqexts {{ etcd_req_ext }} -batch -nodes
+ -subj /CN={{ etcd_hostname }}
+ args:
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'client.csr' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }},DNS:{{ etcd_hostname }}"
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+# Certificates must be signed serially in order to avoid competing
+# for the serial file.
+- name: Sign and create the client crt
+ delegated_serial_command:
+ command: >
+ openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}client.crt
+ -in {{ etcd_cert_prefix }}client.csr
+ -batch
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'client.crt' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }}"
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- file:
+ src: "{{ etcd_ca_cert }}"
+ dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt"
+ state: hard
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Create local temp directory for syncing certs
+ local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX
+ register: g_etcd_client_mktemp
+ changed_when: False
+ when: etcd_client_certs_missing | bool
+ become: no
+
+- name: Create a tarball of the etcd certs
+ command: >
+ tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz
+ -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} .
+ args:
+ creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
+ # Disables the following warning:
+ # Consider using unarchive module rather than running tar
+ warn: no
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Retrieve the etcd cert tarballs
+ fetch:
+ src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
+ dest: "{{ g_etcd_client_mktemp.stdout }}/"
+ flat: yes
+ fail_on_missing: yes
+ validate_checksum: yes
+ when: etcd_client_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Ensure certificate directory exists
+ file:
+ path: "{{ etcd_cert_config_dir }}"
+ state: directory
+ when: etcd_client_certs_missing | bool
+
+- name: Unarchive etcd cert tarballs
+ unarchive:
+ src: "{{ g_etcd_client_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz"
+ dest: "{{ etcd_cert_config_dir }}"
+ when: etcd_client_certs_missing | bool
+
+- file:
+ path: "{{ etcd_cert_config_dir }}/{{ item }}"
+ owner: root
+ group: root
+ mode: 0600
+ with_items:
+ - "{{ etcd_cert_prefix }}client.crt"
+ - "{{ etcd_cert_prefix }}client.key"
+ - "{{ etcd_cert_prefix }}ca.crt"
+ when: etcd_client_certs_missing | bool
+
+- name: Delete temporary directory
+ local_action: file path="{{ g_etcd_client_mktemp.stdout }}" state=absent
+ changed_when: False
+ when: etcd_client_certs_missing | bool
+ become: no
diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml
index 78e543ef1..870c11ad4 100644
--- a/roles/etcd/tasks/main.yml
+++ b/roles/etcd/tasks/main.yml
@@ -1,4 +1,6 @@
---
+- include: server_certificates.yml
+
- name: Set hostname and ip facts
set_fact:
# Store etcd_hostname and etcd_ip such that they will be available
diff --git a/roles/etcd/tasks/server_certificates.yml b/roles/etcd/tasks/server_certificates.yml
new file mode 100644
index 000000000..f0ba58b6e
--- /dev/null
+++ b/roles/etcd/tasks/server_certificates.yml
@@ -0,0 +1,2 @@
+---
+- include: server_certificates/fetch_from_ca.yml
diff --git a/roles/etcd/tasks/server_certificates/fetch_from_ca.yml b/roles/etcd/tasks/server_certificates/fetch_from_ca.yml
new file mode 100644
index 000000000..064fe1952
--- /dev/null
+++ b/roles/etcd/tasks/server_certificates/fetch_from_ca.yml
@@ -0,0 +1,238 @@
+---
+- include: ../ca/deploy.yml
+ when:
+ - etcd_ca_setup | default(True) | bool
+
+- name: Install etcd
+ package:
+ name: "etcd{{ '-' + etcd_version if etcd_version is defined else '' }}"
+ state: present
+ when: not etcd_is_containerized | bool
+
+- name: Check status of etcd certificates
+ stat:
+ path: "{{ item }}"
+ with_items:
+ - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}server.crt"
+ - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}peer.crt"
+ - "{{ etcd_cert_config_dir }}/{{ etcd_cert_prefix }}ca.crt"
+ - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}server.crt"
+ - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}peer.crt"
+ - "{{ etcd_system_container_cert_config_dir }}/{{ etcd_cert_prefix }}ca.crt"
+ register: g_etcd_server_cert_stat_result
+ when: not etcd_certificates_redeploy | default(false) | bool
+
+- set_fact:
+ etcd_server_certs_missing: "{{ true if etcd_certificates_redeploy | default(false) | bool
+ else (False in (g_etcd_server_cert_stat_result.results
+ | default({})
+ | oo_collect(attribute='stat.exists')
+ | list)) }}"
+
+- name: Ensure generated_certs directory present
+ file:
+ path: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ state: directory
+ mode: 0700
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Create the server csr
+ command: >
+ openssl req -new -keyout {{ etcd_cert_prefix }}server.key
+ -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}server.csr
+ -reqexts {{ etcd_req_ext }} -batch -nodes
+ -subj /CN={{ etcd_hostname }}
+ args:
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'server.csr' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }},DNS:{{ etcd_hostname }}"
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+# Certificates must be signed serially in order to avoid competing
+# for the serial file.
+- name: Sign and create the server crt
+ delegated_serial_command:
+ command: >
+ openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}server.crt
+ -in {{ etcd_cert_prefix }}server.csr
+ -extensions {{ etcd_ca_exts_server }} -batch
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'server.crt' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }}"
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Create the peer csr
+ command: >
+ openssl req -new -keyout {{ etcd_cert_prefix }}peer.key
+ -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}peer.csr
+ -reqexts {{ etcd_req_ext }} -batch -nodes
+ -subj /CN={{ etcd_hostname }}
+ args:
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'peer.csr' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }},DNS:{{ etcd_hostname }}"
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+# Certificates must be signed serially in order to avoid competing
+# for the serial file.
+- name: Sign and create the peer crt
+ delegated_serial_command:
+ command: >
+ openssl ca -name {{ etcd_ca_name }} -config {{ etcd_openssl_conf }}
+ -out {{ etcd_cert_prefix }}peer.crt
+ -in {{ etcd_cert_prefix }}peer.csr
+ -extensions {{ etcd_ca_exts_peer }} -batch
+ chdir: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}"
+ creates: "{{ etcd_generated_certs_dir ~ '/' ~ etcd_cert_subdir ~ '/'
+ ~ etcd_cert_prefix ~ 'peer.crt' }}"
+ environment:
+ SAN: "IP:{{ etcd_ip }}"
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- file:
+ src: "{{ etcd_ca_cert }}"
+ dest: "{{ etcd_generated_certs_dir}}/{{ etcd_cert_subdir }}/{{ etcd_cert_prefix }}ca.crt"
+ state: hard
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Create local temp directory for syncing certs
+ local_action: command mktemp -d /tmp/etcd_certificates-XXXXXXX
+ become: no
+ register: g_etcd_server_mktemp
+ changed_when: False
+ when: etcd_server_certs_missing | bool
+
+- name: Create a tarball of the etcd certs
+ command: >
+ tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz
+ -C {{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }} .
+ args:
+ creates: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
+ # Disables the following warning:
+ # Consider using unarchive module rather than running tar
+ warn: no
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Retrieve etcd cert tarball
+ fetch:
+ src: "{{ etcd_generated_certs_dir }}/{{ etcd_cert_subdir }}.tgz"
+ dest: "{{ g_etcd_server_mktemp.stdout }}/"
+ flat: yes
+ fail_on_missing: yes
+ validate_checksum: yes
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Ensure certificate directory exists
+ file:
+ path: "{{ item }}"
+ state: directory
+ with_items:
+ - "{{ etcd_cert_config_dir }}"
+ - "{{ etcd_system_container_cert_config_dir }}"
+ when: etcd_server_certs_missing | bool
+
+- name: Unarchive cert tarball
+ unarchive:
+ src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz"
+ dest: "{{ etcd_cert_config_dir }}"
+ when: etcd_server_certs_missing | bool
+
+- name: Create a tarball of the etcd ca certs
+ command: >
+ tar -czvf {{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz
+ -C {{ etcd_ca_dir }} .
+ args:
+ creates: "{{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz"
+ warn: no
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Retrieve etcd ca cert tarball
+ fetch:
+ src: "{{ etcd_generated_certs_dir }}/{{ etcd_ca_name }}.tgz"
+ dest: "{{ g_etcd_server_mktemp.stdout }}/"
+ flat: yes
+ fail_on_missing: yes
+ validate_checksum: yes
+ when: etcd_server_certs_missing | bool
+ delegate_to: "{{ etcd_ca_host }}"
+
+- name: Ensure ca directory exists
+ file:
+ path: "{{ item }}"
+ state: directory
+ with_items:
+ - "{{ etcd_ca_dir }}"
+ - "{{ etcd_system_container_cert_config_dir }}/ca"
+ when: etcd_server_certs_missing | bool
+
+- name: Unarchive cert tarball for the system container
+ unarchive:
+ src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_cert_subdir }}.tgz"
+ dest: "{{ etcd_system_container_cert_config_dir }}"
+ when:
+ - etcd_server_certs_missing | bool
+ - r_etcd_common_etcd_runtime == 'runc'
+
+- name: Unarchive etcd ca cert tarballs for the system container
+ unarchive:
+ src: "{{ g_etcd_server_mktemp.stdout }}/{{ etcd_ca_name }}.tgz"
+ dest: "{{ etcd_system_container_cert_config_dir }}/ca"
+ when:
+ - etcd_server_certs_missing | bool
+ - r_etcd_common_etcd_runtime == 'runc'
+
+- name: Delete temporary directory
+ local_action: file path="{{ g_etcd_server_mktemp.stdout }}" state=absent
+ become: no
+ changed_when: False
+ when: etcd_server_certs_missing | bool
+
+- name: Validate permissions on certificate files
+ file:
+ path: "{{ item }}"
+ mode: 0600
+ owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ when: etcd_url_scheme == 'https'
+ with_items:
+ - "{{ etcd_ca_file }}"
+ - "{{ etcd_cert_file }}"
+ - "{{ etcd_key_file }}"
+
+- name: Validate permissions on peer certificate files
+ file:
+ path: "{{ item }}"
+ mode: 0600
+ owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ when: etcd_peer_url_scheme == 'https'
+ with_items:
+ - "{{ etcd_peer_ca_file }}"
+ - "{{ etcd_peer_cert_file }}"
+ - "{{ etcd_peer_key_file }}"
+
+- name: Validate permissions on the config dir
+ file:
+ path: "{{ etcd_conf_dir }}"
+ state: directory
+ owner: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ group: "{{ 'etcd' if not etcd_is_containerized | bool else omit }}"
+ mode: 0700
diff --git a/roles/etcd/templates/openssl_append.j2 b/roles/etcd/templates/openssl_append.j2
new file mode 100644
index 000000000..f28316fc2
--- /dev/null
+++ b/roles/etcd/templates/openssl_append.j2
@@ -0,0 +1,51 @@
+
+[ {{ etcd_req_ext }} ]
+basicConstraints = critical,CA:FALSE
+keyUsage = digitalSignature,keyEncipherment
+subjectAltName = ${ENV::SAN}
+
+[ {{ etcd_ca_name }} ]
+dir = {{ etcd_ca_dir }}
+crl_dir = {{ etcd_ca_crl_dir }}
+database = {{ etcd_ca_db }}
+new_certs_dir = {{ etcd_ca_new_certs_dir }}
+certificate = {{ etcd_ca_cert }}
+serial = {{ etcd_ca_serial }}
+private_key = {{ etcd_ca_key }}
+crl_number = {{ etcd_ca_crl_number }}
+x509_extensions = {{ etcd_ca_exts_client }}
+default_days = {{ etcd_ca_default_days }}
+default_md = sha256
+preserve = no
+name_opt = ca_default
+cert_opt = ca_default
+policy = policy_anything
+unique_subject = no
+copy_extensions = copy
+
+[ {{ etcd_ca_exts_self }} ]
+authorityKeyIdentifier = keyid,issuer
+basicConstraints = critical,CA:TRUE,pathlen:0
+keyUsage = critical,digitalSignature,keyEncipherment,keyCertSign
+subjectKeyIdentifier = hash
+
+[ {{ etcd_ca_exts_peer }} ]
+authorityKeyIdentifier = keyid,issuer:always
+basicConstraints = critical,CA:FALSE
+extendedKeyUsage = clientAuth,serverAuth
+keyUsage = digitalSignature,keyEncipherment
+subjectKeyIdentifier = hash
+
+[ {{ etcd_ca_exts_server }} ]
+authorityKeyIdentifier = keyid,issuer:always
+basicConstraints = critical,CA:FALSE
+extendedKeyUsage = serverAuth
+keyUsage = digitalSignature,keyEncipherment
+subjectKeyIdentifier = hash
+
+[ {{ etcd_ca_exts_client }} ]
+authorityKeyIdentifier = keyid,issuer:always
+basicConstraints = critical,CA:FALSE
+extendedKeyUsage = clientAuth
+keyUsage = digitalSignature,keyEncipherment
+subjectKeyIdentifier = hash