diff options
-rw-r--r-- | roles/openshift_logging/files/generate-jks.sh | 177 | ||||
-rw-r--r-- | roles/openshift_logging/tasks/generate_certs.yaml | 102 | ||||
-rw-r--r-- | roles/openshift_logging/templates/jks_pod.j2 (renamed from roles/openshift_logging/templates/job.j2) | 8 |
3 files changed, 191 insertions, 96 deletions
diff --git a/roles/openshift_logging/files/generate-jks.sh b/roles/openshift_logging/files/generate-jks.sh index 8760f37fe..db7ed9ab8 100644 --- a/roles/openshift_logging/files/generate-jks.sh +++ b/roles/openshift_logging/files/generate-jks.sh @@ -1,36 +1,140 @@ #! /bin/sh set -ex -function importPKCS() { - dir=${SCRATCH_DIR:-_output} - NODE_NAME=$1 - ks_pass=${KS_PASS:-kspass} - ts_pass=${TS_PASS:-tspass} - rm -rf $NODE_NAME - - keytool \ - -importkeystore \ - -srckeystore $NODE_NAME.pkcs12 \ - -srcstoretype PKCS12 \ - -srcstorepass pass \ - -deststorepass $ks_pass \ - -destkeypass $ks_pass \ - -destkeystore $dir/keystore.jks \ - -alias 1 \ - -destalias $NODE_NAME - - echo "Import back to keystore (including CA chain)" - - keytool \ - -import \ - -file $dir/ca.crt \ - -keystore $dir/keystore.jks \ - -storepass $ks_pass \ - -noprompt -alias sig-ca +function generate_JKS_chain() { + dir=${SCRATCH_DIR:-_output} + ADD_OID=$1 + NODE_NAME=$2 + CERT_NAMES=${3:-$NODE_NAME} + ks_pass=${KS_PASS:-kspass} + ts_pass=${TS_PASS:-tspass} + rm -rf $NODE_NAME + + extension_names="" + for name in ${CERT_NAMES//,/ }; do + extension_names="${extension_names},dns:${name}" + done + + if [ "$ADD_OID" = true ]; then + extension_names="${extension_names},oid:1.2.3.4.5.5" + fi + + echo Generating keystore and certificate for node $NODE_NAME + + keytool -genkey \ + -alias $NODE_NAME \ + -keystore $dir/$NODE_NAME.jks \ + -keypass $ks_pass \ + -storepass $ks_pass \ + -keyalg RSA \ + -keysize 2048 \ + -validity 712 \ + -dname "CN=$NODE_NAME, OU=OpenShift, O=Logging" \ + -ext san=dns:localhost,ip:127.0.0.1"${extension_names}" + + echo Generating certificate signing request for node $NODE_NAME + + keytool -certreq \ + -alias $NODE_NAME \ + -keystore $dir/$NODE_NAME.jks \ + -storepass $ks_pass \ + -file $dir/$NODE_NAME.csr \ + -keyalg rsa \ + -dname "CN=$NODE_NAME, OU=OpenShift, O=Logging" \ + -ext san=dns:localhost,ip:127.0.0.1"${extension_names}" + + echo Sign certificate request with CA + + openssl ca \ + -in $dir/$NODE_NAME.csr \ + -notext \ + -out $dir/$NODE_NAME.crt \ + -config $dir/signing.conf \ + -extensions v3_req \ + -batch \ + -extensions server_ext + + echo "Import back to keystore (including CA chain)" + + keytool \ + -import \ + -file $dir/ca.crt \ + -keystore $dir/$NODE_NAME.jks \ + -storepass $ks_pass \ + -noprompt -alias sig-ca + + keytool \ + -import \ + -file $dir/$NODE_NAME.crt \ + -keystore $dir/$NODE_NAME.jks \ + -storepass $ks_pass \ + -noprompt \ + -alias $NODE_NAME + + echo All done for $NODE_NAME +} - echo All done for $NODE_NAME +function generate_JKS_client_cert() { + NODE_NAME="$1" + ks_pass=${KS_PASS:-kspass} + ts_pass=${TS_PASS:-tspass} + dir=${SCRATCH_DIR:-_output} # for writing files to bundle into secrets + + echo Generating keystore and certificate for node ${NODE_NAME} + + keytool -genkey \ + -alias $NODE_NAME \ + -keystore $dir/$NODE_NAME.jks \ + -keyalg RSA \ + -keysize 2048 \ + -validity 712 \ + -keypass $ks_pass \ + -storepass $ks_pass \ + -dname "CN=$NODE_NAME, OU=OpenShift, O=Logging" + + echo Generating certificate signing request for node $NODE_NAME + + keytool -certreq \ + -alias $NODE_NAME \ + -keystore $dir/$NODE_NAME.jks \ + -file $dir/$NODE_NAME.csr \ + -keyalg rsa \ + -keypass $ks_pass \ + -storepass $ks_pass \ + -dname "CN=$NODE_NAME, OU=OpenShift, O=Logging" + + echo Sign certificate request with CA + openssl ca \ + -in "$dir/$NODE_NAME.csr" \ + -notext \ + -out "$dir/$NODE_NAME.crt" \ + -config $dir/signing.conf \ + -extensions v3_req \ + -batch \ + -extensions server_ext + + echo "Import back to keystore (including CA chain)" + + keytool \ + -import \ + -file $dir/ca.crt \ + -keystore $dir/$NODE_NAME.jks \ + -storepass $ks_pass \ + -noprompt -alias sig-ca + + keytool \ + -import \ + -file $dir/$NODE_NAME.crt \ + -keystore $dir/$NODE_NAME.jks \ + -storepass $ks_pass \ + -noprompt \ + -alias $NODE_NAME + + echo All done for $NODE_NAME } +function join { local IFS="$1"; shift; echo "$*"; } + function createTruststore() { echo "Import CA to truststore for validating client certs" @@ -43,29 +147,22 @@ function createTruststore() { -noprompt -alias sig-ca } -dir="/opt/deploy/" +dir="$CERT_DIR" SCRATCH_DIR=$dir -admin_user='system.admin' - if [[ ! -f $dir/system.admin.jks || -z "$(keytool -list -keystore $dir/system.admin.jks -storepass kspass | grep sig-ca)" ]]; then - importPKCS "system.admin" - mv $dir/keystore.jks $dir/system.admin.jks + generate_JKS_client_cert "system.admin" fi -if [[ ! -f $dir/searchguard_node_key || -z "$(keytool -list -keystore $dir/searchguard_node_key -storepass kspass | grep sig-ca)" ]]; then - importPKCS "elasticsearch" - mv $dir/keystore.jks $dir/searchguard_node_key +if [[ ! -f $dir/elasticsearch.jks || -z "$(keytool -list -keystore $dir/elasticsearch.jks -storepass kspass | grep sig-ca)" ]]; then + generate_JKS_chain true elasticsearch "$(join , logging-es{,-ops})" fi - -if [[ ! -f $dir/system.admin.jks || -z "$(keytool -list -keystore $dir/system.admin.jks -storepass kspass | grep sig-ca)" ]]; then - importPKCS "logging-es" +if [[ ! -f $dir/logging-es.jks || -z "$(keytool -list -keystore $dir/logging-es.jks -storepass kspass | grep sig-ca)" ]]; then + generate_JKS_chain false logging-es "$(join , logging-es{,-ops}{,-cluster}{,.${PROJECT}.svc.cluster.local})" fi [ ! -f $dir/truststore.jks ] && createTruststore -[ ! -f $dir/searchguard_node_truststore ] && cp $dir/truststore.jks $dir/searchguard_node_truststore - # necessary so that the job knows it completed successfully exit 0 diff --git a/roles/openshift_logging/tasks/generate_certs.yaml b/roles/openshift_logging/tasks/generate_certs.yaml index 161d51055..6bfeccf61 100644 --- a/roles/openshift_logging/tasks/generate_certs.yaml +++ b/roles/openshift_logging/tasks/generate_certs.yaml @@ -102,61 +102,57 @@ loop_control: loop_var: node_name -- shell: certs=""; for cert in $(echo logging-es{,-ops}); do certs=$certs,dns:$cert; done; echo $certs - register: elasticsearch_certs - check_mode: no - -- shell: certs=""; for cert in $(echo logging-es{,-ops}{,-cluster}{,.logging.svc.cluster.local}); do certs=$certs,dns:$cert; done; echo $certs - register: logging_es_certs - check_mode: no - -#- shell: index=2; certs=""; for cert in $(echo logging-es{,-ops}); do certs=$certs,DNS.$index=$cert; index=$(($index+1)); done; echo $certs -# register: elasticsearch_certs -# check_mode: no - -#- shell: index=2; certs=""; for cert in $(echo logging-es{,-ops}{,-cluster}{,.logging.svc.cluster.local}); do certs=$certs,DNS.$index=$cert; index=$(($index+1)); done; echo $certs -# register: logging_es_certs -# check_mode: no +- name: Check for jks-generator service account + command: > + {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig get serviceaccount/jks-generator --no-headers -n {{openshift_logging_namespace}} + register: serviceaccount_result + ignore_errors: yes + when: not ansible_check_mode -- name: Generate PKCS12 chains -# include: generate_pkcs12.yaml component='system.admin' - include: generate_jks_chain.yaml component='system.admin' +- name: Create jks-generator service account + command: > + {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig create serviceaccount jks-generator -n {{openshift_logging_namespace}} + when: not ansible_check_mode and "not found" in serviceaccount_result.stderr + +- name: Check for hostmount-anyuid scc entry + shell: > + {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig get scc hostmount-anyuid -o go-template='{{ '{{' }}.users{{ '}}' }}' | + grep system:serviceaccount:{{openshift_logging_namespace}}:jks-generator + register: scc_result + ignore_errors: yes + when: not ansible_check_mode + +- name: Add to hostmount-anyuid scc + command: > + {{ openshift.common.admin_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig policy add-scc-to-user hostmount-anyuid -z jks-generator -n {{openshift_logging_namespace}} + when: not ansible_check_mode and scc_result.rc == 1 + +- name: Copy jks script + copy: + src: generate-jks.sh + dest: "{{generated_certs_dir}}/generate-jks.sh" + +- name: Generate JKS chains + template: + src: jks_pod.j2 + dest: "{{mktemp.stdout}}/jks_pod.yaml" + +- name: create pod + shell: > + {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig create -f {{mktemp.stdout}}/jks_pod.yaml -n {{openshift_logging_namespace}} + register: podoutput + +- shell: > + echo {{podoutput.stdout}} | awk -v podname='\\\".*\\\"' '{print $2}' + register: podname + +- shell: > + {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig get pod {{podname.stdout}} -o go-template='{{ '{{' }}index .status "phase"{{ '}}' }}' -n {{openshift_logging_namespace}} + register: result + until: result.stdout.find("Succeeded") != -1 + retries: 5 + delay: 10 -- name: Generate PKCS12 chains -# include: generate_pkcs12.yaml component={{node.name}} oid={{node.oid | default(False)}} chain_certs={{node.certs}} - include: generate_jks_chain.yaml component={{node.name}} oid={{node.oid | default(False)}} chain_certs={{node.certs}} - with_items: - - {name: 'elasticsearch', oid: True, certs: '{{elasticsearch_certs.stdout}}'} - - {name: 'logging-es', certs: '{{logging_es_certs.stdout}}'} - loop_control: - loop_var: node -# This should be handled within the ES image instead... --- -#- name: Copy jks script -# copy: -# src: generate-jks.sh -# dest: "{{etcd_generated_certs_dir}}/logging" - -#- name: Generate JKS chains -# template: -# src: job.j2 -# dest: "{{mktemp.stdout}}/jks_job.yaml" - -#- name: kick off job -# shell: > -# {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig create -f {{mktemp.stdout}}/jks_job.yaml -n {{logging_namespace}} -# register: podoutput - -#- shell: > -# echo {{podoutput.stdout}} | awk -v podname='\\\".*\\\"' '{print $2}' -# register: podname - -#- action: shell > -# {{ openshift.common.client_binary }} --config={{ mktemp.stdout }}/admin.kubeconfig oc get pod/{{podname.stdout}} -o go-template='{{ '{{' }}index .status "phase"{{ '}}' }}' -n {{logging_namespace}} -# register: result -# until: result.stdout.find("Succeeded") != -1 -# retries: 5 -# delay: 10 -# --- This should be handled within the ES image instead... - name: Generate proxy session shell: tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 200 register: session_secret diff --git a/roles/openshift_logging/templates/job.j2 b/roles/openshift_logging/templates/jks_pod.j2 index d7794a407..8b1c74211 100644 --- a/roles/openshift_logging/templates/job.j2 +++ b/roles/openshift_logging/templates/jks_pod.j2 @@ -9,17 +9,19 @@ spec: - name: jks-cert-gen image: {{openshift_logging_image_prefix}}logging-deployer:{{openshift_logging_image_version}} imagePullPolicy: Always - command: ["sh", "generate-jks.sh"] + command: ["sh", "{{generated_certs_dir}}/generate-jks.sh"] securityContext: privileged: true volumeMounts: - - mountPath: /opt/deploy + - mountPath: {{generated_certs_dir}} name: certmount env: - name: PROJECT value: {{openshift_logging_namespace}} + - name: CERT_DIR + value: {{generated_certs_dir}} restartPolicy: Never - serviceAccount: aggregated-logging-fluentd + serviceAccount: jks-generator volumes: - hostPath: path: "{{generated_certs_dir}}" |