Merge pull request #3257 from georgejdli/feature-helm-tls-2
[helm-tls] add option to secure helm tiller with tls
This commit is contained in:
commit
baf1aba239
4 changed files with 212 additions and 0 deletions
|
@ -10,6 +10,24 @@ helm_deployment_type: host
|
||||||
# Do not download the local repository cache on helm init
|
# Do not download the local repository cache on helm init
|
||||||
helm_skip_refresh: false
|
helm_skip_refresh: false
|
||||||
|
|
||||||
|
# Secure Tiller installation with TLS
|
||||||
|
tiller_enable_tls: false
|
||||||
|
helm_config_dir: "{{ kube_config_dir }}/helm"
|
||||||
|
helm_script_dir: "{{ bin_dir }}/helm-scripts"
|
||||||
|
|
||||||
|
# Store tiller release information as Secret instead of a ConfigMap
|
||||||
|
tiller_secure_release_info: false
|
||||||
|
|
||||||
|
# Where private root key will be secured for TLS
|
||||||
|
helm_tiller_cert_dir: "{{ helm_config_dir }}/ssl"
|
||||||
|
tiller_tls_cert: "{{ helm_tiller_cert_dir }}/tiller.pem"
|
||||||
|
tiller_tls_key: "{{ helm_tiller_cert_dir }}/tiller-key.pem"
|
||||||
|
tiller_tls_ca_cert: "{{ helm_tiller_cert_dir }}/ca.pem"
|
||||||
|
|
||||||
|
# Permission owner and group for helm client cert. Will be dependent on the helm_home_dir
|
||||||
|
helm_cert_group: root
|
||||||
|
helm_cert_owner: root
|
||||||
|
|
||||||
# Set URL for stable repository
|
# Set URL for stable repository
|
||||||
# helm_stable_repo_url: "https://kubernetes-charts.storage.googleapis.com"
|
# helm_stable_repo_url: "https://kubernetes-charts.storage.googleapis.com"
|
||||||
|
|
||||||
|
|
76
roles/kubernetes-apps/helm/files/helm-make-ssl.sh
Normal file
76
roles/kubernetes-apps/helm/files/helm-make-ssl.sh
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
cat << EOF
|
||||||
|
Create self signed certificates
|
||||||
|
|
||||||
|
Usage : $(basename $0) -f <config> [-d <ssldir>]
|
||||||
|
-h | --help : Show this message
|
||||||
|
-e | --helm-home : Helm home directory
|
||||||
|
-d | --ssldir : Directory where the certificates will be installed
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Options parsing
|
||||||
|
while (($#)); do
|
||||||
|
case "$1" in
|
||||||
|
-h | --help) usage; exit 0;;
|
||||||
|
-e | --helm-home) HELM_HOME="${2}"; shift 2;;
|
||||||
|
-d | --ssldir) SSLDIR="${2}"; shift 2;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
echo "ERROR : Unknown option"
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z ${SSLDIR} ]; then
|
||||||
|
SSLDIR="/etc/kubernetes/helm/ssl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmpdir=$(mktemp -d /tmp/helm_cacert.XXXXXX)
|
||||||
|
trap 'rm -rf "${tmpdir}"' EXIT
|
||||||
|
cd "${tmpdir}"
|
||||||
|
|
||||||
|
mkdir -p "${SSLDIR}"
|
||||||
|
|
||||||
|
# Root CA
|
||||||
|
if [ -e "$SSLDIR/ca-key.pem" ]; then
|
||||||
|
# Reuse existing CA
|
||||||
|
cp $SSLDIR/{ca.pem,ca-key.pem} .
|
||||||
|
else
|
||||||
|
openssl genrsa -out ca-key.pem 4096 > /dev/null 2>&1
|
||||||
|
openssl req -x509 -new -nodes -key ca-key.pem -days 36500 -out ca.pem -subj "/CN=tiller-ca" > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
|
||||||
|
gen_key_and_cert() {
|
||||||
|
local name=$1
|
||||||
|
local subject=$2
|
||||||
|
openssl genrsa -out ${name}-key.pem 4096 > /dev/null 2>&1
|
||||||
|
openssl req -new -key ${name}-key.pem -sha256 -out ${name}.csr -subj "${subject}" > /dev/null 2>&1
|
||||||
|
openssl x509 -req -in ${name}.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ${name}.pem -days 36500 > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
#Generate cert and key for Tiller if they don't exist
|
||||||
|
if ! [ -e "$SSLDIR/tiller.pem" ]; then
|
||||||
|
gen_key_and_cert "tiller" "/CN=tiller-server"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Generate cert and key for Helm client if they dont exist
|
||||||
|
if ! [ -e "$SSLDIR/helm.pem" ]; then
|
||||||
|
gen_key_and_cert "helm" "/CN=helm-client"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Secure certs to first master
|
||||||
|
mv *.pem ${SSLDIR}/
|
||||||
|
|
||||||
|
# Install Helm client certs to first master
|
||||||
|
# Copy using Helm default names for convenience
|
||||||
|
cp ${SSLDIR}/ca.pem ${HELM_HOME}/ca.pem
|
||||||
|
cp ${SSLDIR}/helm.pem ${HELM_HOME}/cert.pem
|
||||||
|
cp ${SSLDIR}/helm-key.pem ${HELM_HOME}/key.pem
|
107
roles/kubernetes-apps/helm/tasks/gen_helm_tiller_certs.yml
Normal file
107
roles/kubernetes-apps/helm/tasks/gen_helm_tiller_certs.yml
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
---
|
||||||
|
- name: "Gen_helm_tiller_certs | Create helm config directory (on {{groups['kube-master'][0]}})"
|
||||||
|
run_once: yes
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
file:
|
||||||
|
path: "{{ helm_config_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: kube
|
||||||
|
|
||||||
|
- name: "Gen_helm_tiller_certs | Create helm script directory (on {{groups['kube-master'][0]}})"
|
||||||
|
run_once: yes
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
file:
|
||||||
|
path: "{{ helm_script_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: kube
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Copy certs generation script
|
||||||
|
run_once: yes
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
copy:
|
||||||
|
src: "helm-make-ssl.sh"
|
||||||
|
dest: "{{ helm_script_dir }}/helm-make-ssl.sh"
|
||||||
|
mode: 0700
|
||||||
|
|
||||||
|
- name: "Check_helm_certs | check if helm client certs have already been generated on first master (on {{groups['kube-master'][0]}})"
|
||||||
|
find:
|
||||||
|
paths: "{{ helm_home_dir }}"
|
||||||
|
patterns: "*.pem"
|
||||||
|
get_checksum: true
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
register: helmcert_master
|
||||||
|
run_once: true
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | run cert generation script
|
||||||
|
run_once: yes
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
command: "{{ helm_script_dir }}/helm-make-ssl.sh -e {{ helm_home_dir }} -d {{ helm_tiller_cert_dir }}"
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
helm_client_certs: ['ca.pem', 'cert.pem', 'key.pem']
|
||||||
|
|
||||||
|
- name: "Check_helm_client_certs | check if a cert already exists on master node"
|
||||||
|
find:
|
||||||
|
paths: "{{ helm_home_dir }}"
|
||||||
|
patterns: "*.pem"
|
||||||
|
get_checksum: true
|
||||||
|
register: helmcert_node
|
||||||
|
when: inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: "Check_helm_client_certs | Set 'sync_helm_certs' to true on masters"
|
||||||
|
set_fact:
|
||||||
|
sync_helm_certs: true
|
||||||
|
when: inventory_hostname != groups['kube-master'][0] and
|
||||||
|
(not item in helmcert_node.files | map(attribute='path') | map("basename") | list or
|
||||||
|
helmcert_node.files | selectattr("path", "equalto", "{{ helm_home_dir }}/{{ item }}") | map(attribute="checksum")|first|default('') != helmcert_master.files | selectattr("path", "equalto", "{{ helm_home_dir }}/{{ item }}") | map(attribute="checksum")|first|default(''))
|
||||||
|
with_items:
|
||||||
|
- "{{ helm_client_certs }}"
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Gather helm client certs
|
||||||
|
shell: "tar cfz - -C {{ helm_home_dir }} -T /dev/stdin <<< {{ helm_client_certs|join(' ') }} | base64 --wrap=0"
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
no_log: true
|
||||||
|
register: helm_client_cert_data
|
||||||
|
check_mode: no
|
||||||
|
delegate_to: "{{groups['kube-master'][0]}}"
|
||||||
|
when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Use tempfile for unpacking certs on masters
|
||||||
|
tempfile:
|
||||||
|
state: file
|
||||||
|
path: /tmp
|
||||||
|
prefix: helmcertsXXXXX
|
||||||
|
suffix: tar.gz
|
||||||
|
register: helm_cert_tempfile
|
||||||
|
when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Write helm client certs to tempfile
|
||||||
|
copy:
|
||||||
|
content: "{{helm_client_cert_data.stdout}}"
|
||||||
|
dest: "{{helm_cert_tempfile.path}}"
|
||||||
|
owner: root
|
||||||
|
mode: "0600"
|
||||||
|
when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Unpack helm certs on masters
|
||||||
|
shell: "base64 -d < {{ helm_cert_tempfile.path }} | tar xz -C {{ helm_home_dir }}"
|
||||||
|
no_log: true
|
||||||
|
changed_when: false
|
||||||
|
check_mode: no
|
||||||
|
when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: Gen_helm_tiller_certs | Cleanup tempfile on masters
|
||||||
|
file:
|
||||||
|
path: "{{helm_cert_tempfile.path}}"
|
||||||
|
state: absent
|
||||||
|
when: sync_helm_certs|default(false) and inventory_hostname != groups['kube-master'][0]
|
||||||
|
|
||||||
|
- name: Gen_certs | check certificate permissions
|
||||||
|
file:
|
||||||
|
path: "{{ helm_home_dir }}"
|
||||||
|
group: "{{ helm_cert_group }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ helm_cert_owner }}"
|
||||||
|
mode: "u=rwX,g-rwx,o-rwx"
|
||||||
|
recurse: yes
|
|
@ -27,6 +27,11 @@
|
||||||
with_items: "{{ manifests.results }}"
|
with_items: "{{ manifests.results }}"
|
||||||
when: dns_mode != 'none' and inventory_hostname == groups['kube-master'][0]
|
when: dns_mode != 'none' and inventory_hostname == groups['kube-master'][0]
|
||||||
|
|
||||||
|
# Generate necessary certs for securing Helm and Tiller connection with TLS
|
||||||
|
- name: Helm | Set up TLS
|
||||||
|
include_tasks: "gen_helm_tiller_certs.yml"
|
||||||
|
when: tiller_enable_tls
|
||||||
|
|
||||||
- name: Helm | Install/upgrade helm
|
- name: Helm | Install/upgrade helm
|
||||||
command: >
|
command: >
|
||||||
{{ bin_dir }}/helm init --upgrade --tiller-image={{ tiller_image_repo }}:{{ tiller_image_tag }} --tiller-namespace={{ tiller_namespace }}
|
{{ bin_dir }}/helm init --upgrade --tiller-image={{ tiller_image_repo }}:{{ tiller_image_tag }} --tiller-namespace={{ tiller_namespace }}
|
||||||
|
@ -36,8 +41,11 @@
|
||||||
{% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
|
{% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
|
||||||
{% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
|
{% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
|
||||||
{% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
|
{% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
|
||||||
|
{% if tiller_enable_tls %} --tiller-tls --tiller-tls-verify --tiller-tls-cert={{ tiller_tls_cert }} --tiller-tls-key={{ tiller_tls_key }} --tls-ca-cert={{ tiller_tls_ca_cert }} {% endif %}
|
||||||
|
{% if tiller_secure_release_info %} --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' {% endif %}
|
||||||
register: install_helm
|
register: install_helm
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
environment: "{{proxy_env}}"
|
||||||
|
|
||||||
# FIXME: https://github.com/helm/helm/issues/4063
|
# FIXME: https://github.com/helm/helm/issues/4063
|
||||||
- name: Helm | Force apply tiller overrides if necessary
|
- name: Helm | Force apply tiller overrides if necessary
|
||||||
|
@ -49,9 +57,12 @@
|
||||||
{% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
|
{% if tiller_node_selectors is defined %} --node-selectors {{ tiller_node_selectors }}{% endif %}
|
||||||
{% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
|
{% if tiller_override is defined %} --override {{ tiller_override }}{% endif %}
|
||||||
{% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
|
{% if tiller_max_history is defined %} --history-max={{ tiller_max_history }}{% endif %}
|
||||||
|
{% if tiller_enable_tls %} --tiller-tls --tiller-tls-verify --tiller-tls-cert={{ tiller_tls_cert }} --tiller-tls-key={{ tiller_tls_key }} --tls-ca-cert={{ tiller_tls_ca_cert }} {% endif %}
|
||||||
|
{% if tiller_secure_release_info %} --override 'spec.template.spec.containers[0].command'='{/tiller,--storage=secret}' {% endif %}
|
||||||
| kubectl apply -f -
|
| kubectl apply -f -
|
||||||
changed_when: false
|
changed_when: false
|
||||||
when: tiller_override is defined
|
when: tiller_override is defined
|
||||||
|
environment: "{{proxy_env}}"
|
||||||
|
|
||||||
- name: Helm | Set up bash completion
|
- name: Helm | Set up bash completion
|
||||||
shell: "umask 022 && {{ bin_dir }}/helm completion bash >/etc/bash_completion.d/helm.sh"
|
shell: "umask 022 && {{ bin_dir }}/helm completion bash >/etc/bash_completion.d/helm.sh"
|
||||||
|
|
Loading…
Reference in a new issue