doc: add documentation for "samba-tool" contact management
[Samba.git] / selftest / manage-ca / manage-ca.sh
blob8e09a93fbd8f013a717fc29ec4f9c42bbe64239b
1 #!/bin/bash
4 set -e
5 set -u
6 #set -x
8 umask 022
10 function print_usage()
12 echo "Usage:"
13 echo ""
14 echo "${0} <CNF_FILE> <CMD> [<ARG1> [<ARG2>]]"
15 echo ""
16 echo "${0} <CNF_FILE> init_ca"
17 echo "${0} <CNF_FILE> update_crl"
18 echo "${0} <CNF_FILE> publish_crl"
19 echo "${0} <CNF_FILE> create_dc <DC_DNS_NAME> <DC_OBJECTGUID_HEX>"
20 echo "${0} <CNF_FILE> revoke_dc <DC_DNS_NAME> <REVOKE_RESON>"
21 echo "${0} <CNF_FILE> create_user <USER_PRINCIPAL_NAME>"
22 echo "${0} <CNF_FILE> revoke_user <USER_PRINCIPAL_NAME> <REVOKE_RESON>"
23 echo ""
26 function check_arg()
28 local k="${1}"
29 local v="${2}"
31 test -n "${v}" || {
32 print_usage
33 echo "ERROR: CMD[${CMD}] argument <${k}> missing"
34 return 1
37 return 0
39 CNF="${1-}"
40 test -n "${CNF}" || {
41 print_usage
42 echo "ERROR: speficy <CNF_FILE> see manage-ca.templates.d/manage-CA-example.com.cnf"
43 exit 1
45 test -e "${CNF}" || {
46 print_usage
47 echo "ERROR: CNF_FILE[${CNF}] does not exist"
48 exit 1
50 CMD="${2-}"
51 CMDARG1="${3-}"
52 CMDARG2="${4-}"
54 TEMPLATE_DIR="manage-ca.templates.d"
55 DEFAULT_VARS=""
56 DEFAULT_VARS="${DEFAULT_VARS} CRL_HTTP_BASE DNS_DOMAIN DEFAULT_BITS"
57 DEFAULT_VARS="${DEFAULT_VARS} DEFAULT_BITS DEFAULT_DAYS DEFAULT_CRL_DAYS"
58 DEFAULT_VARS="${DEFAULT_VARS} COUNTRY_NAME STATE_NAME LOCALITY_NAME ORGANIZATION_NAME"
59 DEFAULT_VARS="${DEFAULT_VARS} ORGANIZATIONAL_UNIT_NAME COMMON_NAME EMAIL_ADDRESS"
61 source "${CNF}"
63 DEFAULT_BITS=${DEFAULT_BITS:=8192}
64 CA_BITS=${CA_BITS:=${DEFAULT_BITS}}
65 DC_BITS=${DC_BITS:=${DEFAULT_BITS}}
66 USER_BITS=${USER_BITS:=${DEFAULT_BITS}}
68 CA_DAYS=${CA_DAYS:=3650}
69 CRL_DAYS=${CRL_DAYS:=30}
70 DC_DAYS=${DC_DAYS:=730}
71 USER_DAYS=${USER_DAYS:=730}
73 CA_DIR="CA-${DNS_DOMAIN}"
74 DEFAULT_VARS="${DEFAULT_VARS} CA_DIR"
76 CACERT_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.pem"
77 CACERT_CER="${CA_DIR}/Public/CA-${DNS_DOMAIN}-cert.cer"
78 CACRL_PEM="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.pem"
79 CACRL_CRL="${CA_DIR}/Public/CA-${DNS_DOMAIN}-crl.crl"
80 CA_SERIAL="${CA_DIR}/Private/CA-${DNS_DOMAIN}-serial.txt"
82 function generate_from_template()
84 local base_template="${TEMPLATE_DIR}/$1"
85 local cmd_template="${TEMPLATE_DIR}/$2"
86 local cnf_file="$3"
87 shift 3
88 local vars="$@"
90 test -f "${base_template}" || {
91 echo "base_template[${base_template}] does not exists"
92 return 1
94 test -f "${cmd_template}" || {
95 echo "cmd_template[${cmd_template}] does not exists"
96 return 1
98 test -e "${cnf_file}" && {
99 echo "cnf_file[${cnf_file}] already exists"
100 return 1
103 local sedargs=""
104 for k in $vars; do
105 v=$(eval echo "\${${k}}")
106 sedargs="${sedargs} -e 's!@@${k}@@!${v}!g'"
107 done
109 #echo "sedargs[${sedargs}]"
110 cat "${base_template}" "${cmd_template}" | eval sed ${sedargs} > "${cnf_file}"
111 grep '@@' "${cnf_file}" | wc -l | grep -q '^0' || {
112 echo "invalid context in cnf_file[${cnf_file}]"
113 grep '@@' "${cnf_file}"
114 return 1
117 return 0
120 case "${CMD}" in
121 init_ca)
122 test -e "${CA_DIR}" && {
123 echo "CA with CA_DIR[${CA_DIR}] already exists"
124 exit 1
127 OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
128 CA_INDEX="${CA_DIR}/Private/CA-${DNS_DOMAIN}-index.txt"
129 CA_CRLNUMBER="${CA_DIR}/Private/CA-${DNS_DOMAIN}-crlnumber.txt"
130 PRIVATEKEY="${CA_DIR}/Private/CA-${DNS_DOMAIN}-private-key.pem"
132 ORGANIZATIONAL_UNIT_NAME="CA Administration"
133 COMMON_NAME="CA of ${DNS_DOMAIN}"
134 EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
136 DEFAULT_BITS="${CA_BITS}"
137 DEFAULT_DAYS="1"
138 DEFAULT_CRL_DAYS="${CRL_DAYS}"
140 mkdir -p "${CA_DIR}/"{,Public}
141 umask 077
142 mkdir -p "${CA_DIR}/"{,Private,NewCerts,DCs,Users}
143 umask 022
144 touch "${CA_INDEX}"
145 echo "00" > "${CA_SERIAL}"
146 echo "00" > "${CA_CRLNUMBER}"
148 generate_from_template \
149 "openssl-BASE-template.cnf" \
150 "openssl-CA-template.cnf" \
151 "${OPENSSLCNF}" \
152 ${DEFAULT_VARS}
153 openssl req -new -x509 -sha256 -extensions v3_ca -days "${CA_DAYS}" -keyout "${PRIVATEKEY}" -out "${CACERT_PEM}" -config "${OPENSSLCNF}"
154 openssl x509 -in "${CACERT_PEM}" -inform PEM -out "${CACERT_CER}" -outform DER
155 echo -n "Generate CRL [ENTER] to continue"
156 read
157 openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
158 openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
159 ls -la "${CA_DIR}"/Public/CA-*
160 echo "Please run: '${0} ${CNF} publish_crl'"
161 exit 0
163 update_crl)
164 test -e "${CA_DIR}" || {
165 echo "CA with CA_DIR[${CA_DIR}] does not exists"
166 exit 1
169 OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
170 openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
171 openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
172 ls -la "${CACRL_PEM}" "${CACRL_CRL}"
173 echo "Please run: '${0} ${CNF} publish_crl'"
174 exit 0
176 publish_crl)
177 test -e "${CA_DIR}" || {
178 echo "CA with CA_DIR[${CA_DIR}] does not exists"
179 exit 1
182 echo "Upload ${CACRL_CRL} to ${CRL_SSH_BASE}/"
183 rsync -a -P "${CACRL_CRL}" "${CRL_SSH_BASE}/"
184 echo "Check ${CRL_HTTP_BASE}/CA-${DNS_DOMAIN}-crl.crl"
185 exit 0
187 create_dc)
188 test -e "${CA_DIR}" || {
189 echo "CA with CA_DIR[${CA_DIR}] does not exists"
190 exit 1
194 # ldbsearch -H ldap://DC_DNS_NAME '(dnsHostName=DC_DNS_NAME)' distinguishedName --controls=search_options:1:1 --controls=extended_dn:1:0
195 DC_DNS_NAME="${CMDARG1}"
196 check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
197 DC_OBJECTGUID_HEX=$(echo "${CMDARG2}" | tr a-z A-Z)
198 check_arg "DC_OBJECTGUID_HEX" "${DC_OBJECTGUID_HEX}"
200 DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
201 test -e "${DC_DIR}" && {
202 echo "DC with DC_DIR[${DC_DIR}] already exists"
203 exit 1
206 NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
207 DCFILE_BASE="DC-${DC_DNS_NAME}-S${NEXT_SERIAL}"
208 OPENSSLCNF="${DC_DIR}/${DCFILE_BASE}-openssl.cnf"
209 DCKEY_PEM="${DC_DIR}/${DCFILE_BASE}-key.pem"
210 DCKEY_PRIVATE_PEM="${DC_DIR}/${DCFILE_BASE}-private-key.pem"
211 DCKEY_PRIVATE_PEM_BASE="${DCFILE_BASE}-private-key.pem"
212 DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
213 DCREQ_PEM="${DC_DIR}/${DCFILE_BASE}-req.pem"
214 DCCERT_PEM="${DC_DIR}/${DCFILE_BASE}-cert.pem"
215 DCCERT_PEM_BASE="${DCFILE_BASE}-cert.pem"
216 DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
217 DCCERT_CER="${DC_DIR}/${DCFILE_BASE}-cert.cer"
218 DCCERT_P12="${DC_DIR}/${DCFILE_BASE}-private.p12"
220 ORGANIZATIONAL_UNIT_NAME="Domain Controllers"
221 COMMON_NAME="${DC_DNS_NAME}"
222 EMAIL_ADDRESS="ca-${DNS_DOMAIN}@${DNS_DOMAIN}"
224 DEFAULT_BITS="${DC_BITS}"
225 DEFAULT_DAYS="${DC_DAYS}"
226 DEFAULT_CRL_DAYS="${CRL_DAYS}"
228 umask 077
229 mkdir -p "${DC_DIR}/"
231 generate_from_template \
232 "openssl-BASE-template.cnf" \
233 "openssl-DC-template.cnf" \
234 "${OPENSSLCNF}" \
235 ${DEFAULT_VARS} DC_DNS_NAME DC_OBJECTGUID_HEX
237 openssl req -new -newkey rsa:${DC_BITS} -keyout "${DCKEY_PEM}" -out "${DCREQ_PEM}" -config "${OPENSSLCNF}"
238 openssl rsa -in "${DCKEY_PEM}" -inform PEM -out "${DCKEY_PRIVATE_PEM}" -outform PEM
239 openssl ca -config "${OPENSSLCNF}" -in "${DCREQ_PEM}" -out "${DCCERT_PEM}"
240 ln -s "${DCKEY_PRIVATE_PEM_BASE}" "${DCKEY_PRIVATE_PEM_LINK}"
241 ln -s "${DCCERT_PEM_BASE}" "${DCCERT_PEM_LINK}"
242 openssl x509 -in "${DCCERT_PEM}" -inform PEM -out "${DCCERT_CER}" -outform DER
243 echo "Generate ${DCCERT_P12}"
244 openssl pkcs12 -in "${DCCERT_PEM}" -inkey "${DCKEY_PRIVATE_PEM}" -export -out "${DCCERT_P12}"
245 ls -la "${DC_DIR}"/*.*
246 exit 0
248 revoke_dc)
249 test -e "${CA_DIR}" || {
250 echo "CA with CA_DIR[${CA_DIR}] does not exists"
251 exit 1
253 DC_DNS_NAME="${CMDARG1}"
254 check_arg "DC_DNS_NAME" "${DC_DNS_NAME}"
255 REVOKE_REASON="${CMDARG2}"
256 check_arg "REVOKE_REASON" "${REVOKE_REASON}"
258 DC_DIR="${CA_DIR}/DCs/${DC_DNS_NAME}"
259 test -e "${DC_DIR}" || {
260 echo "DC with DC_DIR[${DC_DIR}] does not exists"
261 exit 1
264 OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
265 DCKEY_PRIVATE_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-private-key.pem"
266 DCCERT_PEM_LINK="${DC_DIR}/DC-${DC_DNS_NAME}-cert.pem"
268 REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
269 REVOKE_DC_DIR="${DC_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
271 openssl ca -config "${OPENSSLCNF}" -revoke "${DCCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
273 mv "${DCKEY_PRIVATE_PEM_LINK}" "${DCKEY_PRIVATE_PEM_LINK}.revoked"
274 mv "${DCCERT_PEM_LINK}" "${DCCERT_PEM_LINK}.revoked"
275 mv "${DC_DIR}" "${REVOKE_DC_DIR}"
276 echo "${REVOKE_DC_DIR}"
278 openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
279 openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
280 ls -la "${CACRL_PEM}" "${CACRL_CRL}"
281 echo "Please run: '${0} ${CNF} publish_crl'"
282 exit 0
284 create_user)
285 test -e "${CA_DIR}" || {
286 echo "CA with CA_DIR[${CA_DIR}] does not exists"
287 exit 1
289 USER_PRINCIPAL_NAME="${CMDARG1}"
290 check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
292 USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
293 test -e "${USER_DIR}" && {
294 echo "USER with USER_DIR[${USER_DIR}] already exists"
295 exit 1
298 NEXT_SERIAL=$(cat "${CA_SERIAL}" | xargs)
299 USERFILE_BASE="USER-${USER_PRINCIPAL_NAME}-S${NEXT_SERIAL}"
300 OPENSSLCNF="${USER_DIR}/${USERFILE_BASE}-openssl.cnf"
301 USERKEY_PEM="${USER_DIR}/${USERFILE_BASE}-key.pem"
302 USERKEY_PRIVATE_PEM="${USER_DIR}/${USERFILE_BASE}-private-key.pem"
303 USERKEY_PRIVATE_PEM_BASE="${USERFILE_BASE}-private-key.pem"
304 USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
305 USERREQ_PEM="${USER_DIR}/${USERFILE_BASE}-req.pem"
306 USERCERT_PEM="${USER_DIR}/${USERFILE_BASE}-cert.pem"
307 USERCERT_PEM_BASE="${USERFILE_BASE}-cert.pem"
308 USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
309 USERCERT_CER="${USER_DIR}/${USERFILE_BASE}-cert.cer"
310 USERCERT_P12="${USER_DIR}/${USERFILE_BASE}-private.p12"
312 ORGANIZATIONAL_UNIT_NAME="Users"
313 COMMON_NAME="${USER_PRINCIPAL_NAME}"
314 EMAIL_ADDRESS="${USER_PRINCIPAL_NAME}"
316 DEFAULT_BITS="${USER_BITS}"
317 DEFAULT_DAYS="${USER_DAYS}"
318 DEFAULT_CRL_DAYS="${CRL_DAYS}"
320 umask 077
321 mkdir -p "${USER_DIR}/"
323 generate_from_template \
324 "openssl-BASE-template.cnf" \
325 "openssl-USER-template.cnf" \
326 "${OPENSSLCNF}" \
327 ${DEFAULT_VARS} USER_PRINCIPAL_NAME
329 openssl req -new -newkey rsa:${USER_BITS} -keyout "${USERKEY_PEM}" -out "${USERREQ_PEM}" -config "${OPENSSLCNF}"
330 openssl rsa -in "${USERKEY_PEM}" -inform PEM -out "${USERKEY_PRIVATE_PEM}" -outform PEM
331 openssl ca -config "${OPENSSLCNF}" -in "${USERREQ_PEM}" -out "${USERCERT_PEM}"
332 ln -s "${USERKEY_PRIVATE_PEM_BASE}" "${USERKEY_PRIVATE_PEM_LINK}"
333 ln -s "${USERCERT_PEM_BASE}" "${USERCERT_PEM_LINK}"
334 openssl x509 -in "${USERCERT_PEM}" -inform PEM -out "${USERCERT_CER}" -outform DER
335 echo "Generate ${USERCERT_P12}"
336 openssl pkcs12 -in "${USERCERT_PEM}" -inkey "${USERKEY_PRIVATE_PEM}" -export -out "${USERCERT_P12}"
337 ls -la "${USER_DIR}"/*.*
338 exit 0
340 revoke_user)
341 test -e "${CA_DIR}" || {
342 echo "CA with CA_DIR[${CA_DIR}] does not exists"
343 exit 1
345 USER_PRINCIPAL_NAME="${CMDARG1}"
346 check_arg "USER_PRINCIPAL_NAME" "${USER_PRINCIPAL_NAME}"
347 REVOKE_REASON="${CMDARG2}"
348 check_arg "REVOKE_REASON" "${REVOKE_REASON}"
350 USER_DIR="${CA_DIR}/Users/${USER_PRINCIPAL_NAME}"
351 test -e "${USER_DIR}" || {
352 echo "USER with USER_DIR[${USER_DIR}] does not exists"
353 exit 1
356 OPENSSLCNF="${CA_DIR}/Private/CA-${DNS_DOMAIN}-openssl.cnf"
357 USERKEY_PRIVATE_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-private-key.pem"
358 USERCERT_PEM_LINK="${USER_DIR}/USER-${USER_PRINCIPAL_NAME}-cert.pem"
360 REVOKE_DATE=$(date +%Y%m%d-%H%M%S)
361 REVOKE_USER_DIR="${USER_DIR}.${REVOKE_DATE}.revoked-${REVOKE_REASON}"
363 openssl ca -config "${OPENSSLCNF}" -revoke "${USERCERT_PEM_LINK}" -crl_reason "${REVOKE_REASON}"
365 mv "${USERKEY_PRIVATE_PEM_LINK}" "${USERKEY_PRIVATE_PEM_LINK}.revoked"
366 mv "${USERCERT_PEM_LINK}" "${USERCERT_PEM_LINK}.revoked"
367 mv "${USER_DIR}" "${REVOKE_USER_DIR}.revoked"
368 echo "${REVOKE_USER_DIR}"
370 openssl ca -config "${OPENSSLCNF}" -gencrl -out "${CACRL_PEM}"
371 openssl crl -in "${CACRL_PEM}" -inform PEM -out "${CACRL_CRL}" -outform DER
372 ls -la "${CACRL_PEM}" "${CACRL_CRL}"
373 echo "Please run: '${0} ${CNF} publish_crl'"
374 exit 0
376 usage)
377 print_usage
378 exit 1
381 print_usage
382 echo "ERROR: CMD[${CMD}] - unknown"
383 exit 1
385 esac
387 exit 1