-
Notifications
You must be signed in to change notification settings - Fork 0
/
gencert.sh
executable file
·219 lines (194 loc) · 6.31 KB
/
gencert.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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env bash
#
# Generates certs using 'cfssl'
# Instructions taken from: https://coreos.com/os/docs/latest/generate-self-signed-certificates.html
# Print cert (openssl): openssl x509 -in ca.pem -text -noout
# Print cert (cfssl): cfssl certinfo -cert ca.pem
declare -A humans
#### Config
apiserver_fqdn=con.kube #the DNS "A" record that round-robins all master nodes
api_service_IP=10.3.0.1 #the service IP of kube-apiserver
controllers=(con{0..2}.kube) #hostnames of controller nodes
workers=(work{0..2}.kube) #hostnames of worker nodes
humans=(["admin"]="system:masters" ["dude"]="group1,group2,group3") #human users
#### Helpers
error() {
echo "$1 Exiting."
exit 1
}
toolcheck() {
which dig &> /dev/null || error "'dig' not found."
which cfssl &> /dev/null || error "'cfssl' not found."
which cfssljson &> /dev/null || error "'cfssljson' not found."
}
# homebrew's default cfssl binary doesn't support multiple Organizations
# in the cert, although it does for the CSR. This is because it was compiled
# against Go 1.7. See https://github.com/cloudflare/cfssl/issues/599
#
# Run these commands to compile 'cfssl' against Go 1.8
# brew remove cfssl
# brew upgrade go
# brew install --build-from-source cfssl
gen_certs() {
local element="$1"
local name="$2"
local groups="$3"
# Set profile and other variables based on element type
local app_cert_dir="kubernetes" #default app subfolder for certs is "kubernetes"
local cn="$name" #CN is the hostname/username by default
local profile=""
local alt_names=""
case $element in
etcd )
profile=peer
app_cert_dir="etcd"
alt_names="$name,$(dig +short $name),$apiserver_fqdn"
;;
flannel )
profile=client
app_cert_dir="flannel"
;;
calico )
profile=client
app_cert_dir="calico"
;;
kube-apiserver_server )
profile=server
alt_names="$name,$(dig +short $name),$apiserver_fqdn,$api_service_IP,localhost,127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local"
;;
kube-apiserver_client )
profile=client
;;
kubelet_server )
profile=server
alt_names="$name,$(dig +short $name)"
;;
kubelet_client )
profile=client
cn="system:node:$controller"
groups="system:nodes" #overwrite the original groups
;;
kube-controller-manager )
profile=client
cn="system:kube-controller-manager"
;;
kube-scheduler )
profile=client
cn="system:kube-scheduler"
;;
kube-proxy )
profile=client
cn="system:kube-proxy"
;;
person )
profile=client
;;
* )
echo "'$element' doesn't match: etcd, kubelet_server, kubelet_client, kube-apiserver_server, kube-apiserver_client, kube-controller-manager, kube-scheduler, kube-proxy, person. Skipping."
return
;;
esac
# Configure cert parameters
element_dir=$(cut -d_ -f1 <<< "$element")
local dst_dir="$name/$app_cert_dir/$element_dir"
if [ "$element" == "person" ]; then #no subfolders for client certs for a "person"
dst_dir="$name"
elif [ "$element" == "etcd" ] || [ "$element" == "flannel" ] || [ "$element" == "calico" ]; then #etcd/calico/flannel doesn't need yet another subfolder
dst_dir="$name/$element_dir"
fi
local certname="$profile.pem"
local keyname="$profile-key.pem"
# Check if certs have been generated
if [ -e "$dst_dir/$keyname" ] || [ -e "$dst_dir/$certname" ]; then
printf "Exists"
return
fi
# Add groups only if it's a client cert
local groups_json=""
if [ "$profile" == "client" ] && [ -n "$groups" ]; then
groups_json='"names":['
IFS=,; for group in $groups; do
groups_json="$groups_json"'{"O":"'$group'"},'
done
groups_json=",${groups_json:0:${#groups_json}-1}"']'
fi
echo '{"CN":"'$cn'"'"$groups_json"',"hosts":[""],"key":{"algo":"rsa","size":2048}}' |\
cfssl -loglevel 5 gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=$profile \
-hostname="$alt_names" - |\
cfssljson -bare $profile
# Rename files to the component's name
mkdir -p $dst_dir
cp -n ca.pem $name/$app_cert_dir
cp -n ca.pem $dst_dir
rm $profile.csr
mv $profile.pem $dst_dir/$certname
chmod 400 $profile-key.pem
mv $profile-key.pem $dst_dir/$keyname
printf "Done"
}
#### Main
## Check that the tools are present
toolcheck
## Generate CA cert if ca.pem or ca-key.pem are absent
printf "+ Generate CA cert: "
if !( [ -e ca-key.pem ] && [ -e ca.pem ] ); then
cfssl -loglevel 5 gencert -initca ca-csr.json | cfssljson -bare ca -
printf "Done\n"
else
printf "Exists\n"
fi
printf "\n+ Generate ServiceAccount cert: "
if !( [ -e serviceaccount-key.pem ] && [ -e serviceaccount.pem ] ); then
echo '{"CN":"serviceaccount","hosts":[""],"key":{"algo":"rsa","size":2048}}' |\
cfssl -loglevel 5 gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=server - |\
cfssljson -bare server
# Rename files according to its usage
rm server.csr
mv server.pem serviceaccount.pem
chmod 400 server-key.pem
mv server-key.pem serviceaccount-key.pem
printf "Done\n"
else
printf "Exists\n"
fi
printf "\n+ Generate controller node certs\n"
for controller in ${controllers[@]}; do
elements=("etcd" "flannel" "calico" "kube-apiserver_server" "kube-apiserver_client" "kubelet_server" "kubelet_client" "kube-controller-manager" "kube-scheduler" "kube-proxy")
printf "[$controller]"
for element in ${elements[@]}; do
printf " $element:"
gen_certs $element $controller
done
printf "\n"
# Copy ServiceAccount certs to the controllers
apiserver_dir="$controller/kubernetes/kube-apiserver"
if [ -d $apiserver_dir ]; then
rm -f $apiserver_dir/serviceaccount*.pem #cannot overwrite serviceaccount-key.pem due to permissions
cp serviceaccount*.pem $apiserver_dir
fi
done
printf "Done\n"
printf "\n+ Generate worker node certs\n"
for worker in ${workers[@]}; do
elements=("flannel" "calico" "kubelet_server" "kubelet_client" "kube-proxy")
printf "[$worker]"
for element in ${elements[@]}; do
printf " $element:"
gen_certs $element $worker
done
printf "\n"
done
printf "\n+ Generate human certs\n"
for person in ${!humans[@]}; do
printf "$person:"
gen_certs person $person ${humans[$person]}
printf "\n"
done