- Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathself-signed-ca.sh
executable file
·190 lines (175 loc) · 7.91 KB
/
self-signed-ca.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/bin/bash
# Copyright 2023 The KServe Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o pipefail
usage() {
cat <<EOF
Generate certificate suitable for use with an KFServing webhook service.
This script uses openssl to generate self-signed CA certificate that is
suitable for use with KFServing webhook services. See
https://kubernetes.io/docs/concepts/cluster-administration/certificates/#distributing-self-signed-ca-certificate
for detailed explanation and additional instructions.
The server key/cert CA cert are stored in a k8s secret.
usage: ${0} [OPTIONS]
The following flags are optional.
--service Service name of webhook. Default: kserve-webhook-server-service
--namespace Namespace where webhook service and secret reside. Default: kserve
--secret Secret name for CA certificate and server certificate/key pair. Default: kserve-webhook-server-cert
--mutatingWebhookName Name for the mutating webhook config. This can be specified multiple times. Default: inferenceservice.serving.kserve.io
--validatingWebhookName Name for the validating webhook config. This can be specified multiple times. Default: All validating webhooks
--webhookDeployment Deployment name of the webhook controller. Default: kserve-controller-manager
EOF
exit 1
}
mutatingWebhookNames=()
validatingWebhookNames=()
while [[ $#-gt 0 ]];do
case${1}in
--service)
service="$2"
shift
;;
--secret)
secret="$2"
shift
;;
--namespace)
namespace="$2"
shift
;;
--mutatingWebhookName)
mutatingWebhookNames+=("$2")
shift
;;
--validatingWebhookName)
validatingWebhookNames+=("$2")
shift
;;
--webhookDeployment)
webhookDeployment="$2"
shift
;;
*)
usage
;;
esac
shift
done
#TODO check backward compatibility
[ -z"${secret}" ] && secret=kserve-webhook-server-cert
[ -z"${namespace}" ] && namespace=kserve
[ -z"${webhookDeployment}" ] && webhookDeployment=kserve-controller-manager
[ "${#validatingWebhookNames[@]}"-eq 0 ] && validatingWebhookNames=("inferenceservice.serving.kserve.io""inferencegraph.serving.kserve.io""servingruntime.serving.kserve.io""clusterservingruntime.serving.kserve.io""trainedmodel.serving.kserve.io""localmodelcache.serving.kserve.io")
[ "${#mutatingWebhookNames[@]}"-eq 0 ] && mutatingWebhookNames=("inferenceservice.serving.kserve.io")
[ -z"${service}" ] && service=kserve-webhook-server-service
webhookDeploymentName=${webhookDeployment}
mutatingWebhookConfigNames=("${mutatingWebhookNames[@]}")
validatingWebhookConfigNames=("${validatingWebhookNames[@]}")
echo service: "${service}"
echo namespace: "${namespace}"
echo secret: "${secret}"
echo webhookDeploymentName: "${webhookDeploymentName}"
echo mutatingWebhookConfigNames: "${mutatingWebhookConfigNames[@]}"
echo validatingWebhookConfigNames: "${validatingWebhookConfigNames[@]}"
if [ !-x"$(command -v openssl)" ];then
echo"openssl not found"
exit 1
fi
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 = ${service}
DNS.2 = ${service}.${namespace}
DNS.3 = ${service}.${namespace}.svc
DNS.4 = ${service}.${namespace}.svc.cluster
DNS.5 = ${service}.${namespace}.svc.cluster.local
EOF
# Create CA and Server key/certificate
openssl genrsa -out "${tmpdir}"/ca.key 2048
openssl req -x509 -newkey rsa:2048 -key "${tmpdir}"/ca.key -out "${tmpdir}"/ca.crt -days 365 -nodes -subj "/CN=${service}.${namespace}.svc"
openssl genrsa -out "${tmpdir}"/server.key 2048
openssl req -new -key "${tmpdir}"/server.key -subj "/CN=${service}.${namespace}.svc" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf
# Self sign
openssl x509 -extensions v3_req -req -days 365 -in "${tmpdir}"/server.csr -CA "${tmpdir}"/ca.crt -CAkey "${tmpdir}"/ca.key -CAcreateserial -out "${tmpdir}"/server.crt -extfile "${tmpdir}"/csr.conf
# create the secret with server cert/key
kubectl create secret generic ${secret} \
--from-file=tls.key="${tmpdir}"/server.key \
--from-file=tls.crt="${tmpdir}"/server.crt \
--dry-run=client -o yaml |
kubectl -n ${namespace} apply -f -
# Webhook pod needs to be restarted so that the service reload the secret
# http://github.com/kubeflow/kubeflow/issues/3227
webhookPod=$(kubectl get pods -n ${namespace}| grep ${webhookDeploymentName}| awk '{print $1;}')
# ignore error if webhook pod does not exist
kubectl delete pod "${webhookPod}" -n "${namespace}"2>/dev/null ||true
echo"webhook ${webhookPod} is restarted to utilize the new secret"
echo"CA Certificate:"
cat "${tmpdir}"/ca.crt
# -a means base64 encode
caBundle=$(cat "${tmpdir}"/ca.crt | openssl enc -a -A)
echo"Encoded CA:"
echo -e "${caBundle} \n"
# check if jq is installed
if [ !-x"$(command -v jq)" ];then
echo"jq not found"
exit 1
fi
forwebhookConfigNamein"${mutatingWebhookConfigNames[@]}";do
echo"Patching mutating webhook ${webhookConfigName}"
# Patch CA Certificate to mutatingWebhook
mutatingWebhookCount=$(kubectl get mutatingwebhookconfiguration "${webhookConfigName}" -ojson | jq -r '.webhooks'| jq length)
# build patchstring based on webhook counts
mutatingPatchString='['
foriin$(seq 0 $(($mutatingWebhookCount-1)));do
mutatingPatchString=$mutatingPatchString'{"op": "replace", "path": "/webhooks/'$i'/clientConfig/caBundle", "value":"{{CA_BUNDLE}}"}, '
done
# strip ', '
mutatingPatchString=${mutatingPatchString%, }']'
mutatingPatchString=$(echo ${mutatingPatchString}| sed "s|{{CA_BUNDLE}}|${caBundle}|g")
echo"patching ca bundle for mutating webhook configuration(${webhookConfigName})..."
kubectl patch mutatingwebhookconfiguration "${webhookConfigName}" \
--type='json' -p="${mutatingPatchString}"
done
forwebhookConfigNamein"${validatingWebhookConfigNames[@]}";do
echo"Patching validating webhook ${webhookConfigName}"
# Patch CA Certificate to validatingWebhook
validatingWebhookCount=$(kubectl get validatingwebhookconfiguration "${webhookConfigName}" -ojson | jq -r '.webhooks'| jq length)
validatingPatchString='['
foriin$(seq 0 $(($validatingWebhookCount-1)));do
validatingPatchString=$validatingPatchString'{"op": "replace", "path": "/webhooks/'$i'/clientConfig/caBundle", "value":"{{CA_BUNDLE}}"}, '
done
validatingPatchString=${validatingPatchString%, }']'
validatingPatchString=$(echo ${validatingPatchString}| sed "s|{{CA_BUNDLE}}|${caBundle}|g")
echo"patching ca bundle for validating webhook configuration(${webhookConfigName})..."
kubectl patch validatingwebhookconfiguration "${webhookConfigName}" \
--type='json' -p="${validatingPatchString}"
done
# The conversion webhook has been removed: https://github.com/kserve/kserve/pull/3700/files.
# However, this is kept as a reference for potential future use of the conversion webhook.
# echo "patching ca bundler for conversion webhook configuration.."
# conversionPatchString='[{"op": "replace", "path": "/spec/conversion/webhook/clientConfig/caBundle", "value":"{{CA_BUNDLE}}"}]'
# conversionPatchString=$(echo ${conversionPatchString} | sed "s|{{CA_BUNDLE}}|${caBundle}|g")
# kubectl patch CustomResourceDefinition inferenceservices.serving.kserve.io \
# --type='json' -p="${conversionPatchString}"