128 lines
3.6 KiB
Bash
128 lines
3.6 KiB
Bash
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Generate certificate suitable for use with an Istio webhook service.
|
|
This script uses k8s' CertificateSigningRequest API to a generate a
|
|
certificate signed by k8s CA suitable for use with Istio webhook
|
|
services. This requires permissions to create and approve CSR. See
|
|
https://kubernetes.io/docs/tasks/tls/managing-tls-in-a-cluster for
|
|
detailed explantion and additional instructions.
|
|
The server key/cert k8s CA cert are stored in a k8s secret.
|
|
usage: ${0} [OPTIONS]
|
|
The following flags are required.
|
|
--service Service name of webhook (e.g. cpx-sidecar-injector).
|
|
--namespace Namespace where webhook service and secret reside (e.g. citrix-system).
|
|
--secret Secret name for CA certificate and server certificate/key pair (e.g. cpx-sidecar-injector-certs).
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case ${1} in
|
|
--service)
|
|
service="$2"
|
|
shift
|
|
;;
|
|
--secret)
|
|
secret="$2"
|
|
shift
|
|
;;
|
|
--namespace)
|
|
namespace="$2"
|
|
shift
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
[ -z ${service} ] && service=cpx-sidecar-injector
|
|
[ -z ${secret} ] && secret=cpx-sidecar-injector-certs
|
|
[ -z ${namespace} ] && namespace=citrix-system
|
|
|
|
if [ ! -x "$(command -v openssl)" ]; then
|
|
echo "openssl not found"
|
|
exit 1
|
|
fi
|
|
|
|
csrName=${service}.${namespace}
|
|
#tmpdir=$(mktemp -d)
|
|
scriptdir="$(dirname "$BASH_SOURCE")"
|
|
certdir="$scriptdir/cpx-certs"
|
|
mkdir -p ${certdir}
|
|
echo "creating certs in directory ${certdir} "
|
|
cat <<EOF >> ${certdir}/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 = ${service}
|
|
DNS.2 = ${service}.${namespace}
|
|
DNS.3 = ${service}.${namespace}.svc
|
|
EOF
|
|
|
|
openssl genrsa -out ${certdir}/key.pem 2048
|
|
openssl req -new -key ${certdir}/key.pem -subj "/CN=${service}.${namespace}.svc" -out ${certdir}/server.csr -config ${certdir}/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 ${certdir}/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 [[ ${serverCert} != '' ]]; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if [[ ${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 ${certdir}/cert.pem
|
|
|
|
|
|
# create the secret with CA cert and server cert/key
|
|
kubectl create secret generic ${secret} \
|
|
--from-file=key.pem=${certdir}/key.pem \
|
|
--from-file=cert.pem=${certdir}/cert.pem \
|
|
--dry-run -o yaml |
|
|
kubectl -n ${namespace} apply -f -
|