apiVersion: batch/v1
kind: Job
metadata:
  name: webhook-certs-job
  namespace: kube-system
  labels:
    app.kubernetes.io/component: webhook-certs-job
spec:
  template:
    metadata:
      name: webhook-certs-job
    spec:
      restartPolicy: Never
      serviceAccountName: chaosblade
      containers:
        - name: webhook-job-certs
          image: bitnami/kubectl:latest
          imagePullPolicy: IfNotPresent
          command:
            - "sh"
            - "-c"
            - |
              set -e
              set -x
              K8S_SERVICE=chaosblade-webhook-server
              K8S_SECRET=chaosblade-webhook-server-cert
              K8S_NAMESPACE=kube-system

              # test if secret already exists
              certs=$(kubectl get secret ${K8S_SECRET} --ignore-not-found -n ${K8S_NAMESPACE} -o name)
              if [ "${certs}" = "secret/${K8S_SECRET}" ];then
                echo "Secret already exists"
                exit 0
              fi

              csrName=${K8S_SERVICE}.${K8S_NAMESPACE}
              tmpdir=$(mktemp -d)
              echo "Creating certs in tmpdir ${tmpdir} "

              cat <<EOF >> ${tmpdir}/csr.conf
              [req]
              req_extensions = v3_req
              distinguished_name = req_distinguished_name
              [req_distinguished_name]
              [ v3_req ]
              basicConstraints = CA:FALSE
              keyUsage = nonRepudiation, digitalSignature, keyEncipherment
              extendedKeyUsage = serverAuth
              subjectAltName = @alt_names
              [alt_names]
              DNS.1 = ${K8S_SERVICE}
              DNS.2 = ${K8S_SERVICE}.${K8S_NAMESPACE}
              DNS.3 = ${K8S_SERVICE}.${K8S_NAMESPACE}.svc
              EOF

              openssl genrsa -out ${tmpdir}/server-key.pem 2048
              openssl req -new -key ${tmpdir}/server-key.pem -subj "/CN=${K8S_SERVICE}.${K8S_NAMESPACE}.svc" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf

              # clean-up any previously created CSR for our service. Ignore errors if not present.
              kubectl delete csr ${csrName} 2>/dev/null || true

              # create server cert/key CSR and send to k8s API
              cat <<EOF | kubectl create -f -
              apiVersion: certificates.k8s.io/v1beta1
              kind: CertificateSigningRequest
              metadata:
                name: ${csrName}
              spec:
                groups:
                - system:authenticated
                request: $(cat ${tmpdir}/server.csr | base64 | tr -d '\n')
                usages:
                - digital signature
                - key encipherment
                - server auth
              EOF

              # verify CSR has been created
              while true; do
                  kubectl get csr ${csrName}
                  if [ "$?" -eq 0 ]; then
                      break
                  fi
              done

              # approve and fetch the signed certificate
              kubectl certificate approve ${csrName}

              # verify certificate has been signed
              for x in $(seq 10); do
                  serverCert=$(kubectl get csr ${csrName} -o jsonpath='{.status.certificate}')
                  if [ -n "${serverCert}" ]; then
                      break
                  fi
                  sleep 1
              done

              if [ -z "${serverCert}" ]; then
                  echo "ERROR: After approving csr ${csrName}, the signed certificate did not appear on the resource. Giving up after 10 attempts." >&2
                  exit 1
              fi

              echo ${serverCert} | openssl base64 -d -A -out ${tmpdir}/server-cert.pem

              # create the secret with CA cert and server cert/key
              kubectl create secret generic ${K8S_SECRET} \
                      --from-file=tls.key=${tmpdir}/server-key.pem \
                      --from-file=tls.crt=${tmpdir}/server-cert.pem \
                      --dry-run -o yaml |
                  kubectl -n ${K8S_NAMESPACE} apply -f -

