3 # Copyright (c) 2020 Kungliga Tekniska Högskolan
4 # (Royal Institute of Technology, Stockholm, Sweden).
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
11 # 1. Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
14 # 2. Redistributions in binary form must reproduce the above copyright
15 # notice, this list of conditions and the following disclaimer in the
16 # documentation and/or other materials provided with the distribution.
18 # 3. Neither the name of the Institute nor the names of its contributors
19 # may be used to endorse or promote products derived from this software
20 # without specific prior written permission.
22 # THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 # ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 top_builddir
="@top_builddir@"
35 env_setup
="@env_setup@"
38 testfailed
="echo test failed; cat messages.log; exit 1"
42 # If there is no useful db support compiled in, disable test
45 if ! which curl
> /dev
/null
; then
46 echo "curl is not available -- not testing httpkadmind"
49 if ! test -x ${objdir}/..
/..
/kdc
/httpkadmind
; then
50 echo "Configured w/o libmicrohttpd -- not testing httpkadmind"
65 server
=datan.
test.h5l.se
66 otherserver
=other.
test.h5l.se
67 cache
="FILE:${objdir}/cache.krb5"
68 cache2
="FILE:${objdir}/cache2.krb5"
69 admincache
="FILE:${objdir}/cache3.krb5"
70 keyfile
="${hx509_data}/key.der"
71 keyfile2
="${hx509_data}/key2.der"
77 kdc
="${kdc} --addresses=localhost -P $port"
78 kadminr
="${kadmin} -r $R -a $(uname -n)"
79 kadmin
="${kadmin} -l -r $R"
80 kadmind2
="${kadmind} --keytab=${keytab} --detach -p $admport2 --read-only"
81 kadmind
="${kadmind} --keytab=${keytab} --detach -p $admport"
82 httpkadmind2
="${httpkadmind} --reverse-proxied -T Negotiate -p $restport2"
83 httpkadmind
="${httpkadmind} --reverse-proxied -T Negotiate -p $restport1"
85 kinit2
="${kinit} -c $cache2 ${afs_no_afslog}"
86 kinit
="${kinit} -c $cache ${afs_no_afslog}"
87 adminklist
="${klist} --hidden -v -c $admincache"
88 klist2
="${klist} --hidden -v -c $cache2"
89 klist
="${klist} --hidden -v -c $cache"
90 kgetcred2
="${kgetcred} -c $cache2"
91 kgetcred
="${kgetcred} -c $cache"
92 kdestroy2
="${kdestroy} -c $cache2 ${afs_no_unlog}"
93 kdestroy
="${kdestroy} -c $cache ${afs_no_unlog}"
94 kx509
="${kx509} -c $cache"
96 KRB5_CONFIG
="${objdir}/krb5-httpkadmind.conf"
104 rm -f *.pem
*.crt
*.der
105 rm -rf simple_csr_authz
106 rm -f extracted_keytab
*
108 mkdir
-p simple_csr_authz
112 # We'll avoid using a KDC for now. For testing /httpkadmind we only need keys
113 # for Negotiate tokens, and we'll use ktutil and kimpersonate to make it
114 # possible to create and accept those without a KDC.
116 # grant ext-type value grantee_principal
118 mkdir
-p "${objdir}/simple_csr_authz/${3}"
119 touch "${objdir}/simple_csr_authz/${3}/${1}-${2}"
123 rm -rf "${objdir}/simple_csr_authz"
124 mkdir
-p "${objdir}/simple_csr_authz"
127 if set -o|
grep 'verbose.*on' > /dev
/null ||
128 set -o|
grep 'xtrace.*on' > /dev
/null
; then
136 curl
-g --resolve ${server}:${restport2}:127.0.0.1 \
137 --resolve ${server}:${restport}:127.0.0.1 \
138 -u: --negotiate $verbose \
139 -D response-headers \
143 # get_config QPARAMS curl-opts
145 url
="http://${server}:${restport}/get-config?$1"
147 HTTP
$verbose "$@" "$url"
151 set -- $
(grep -i ^Cache-Control
: response-headers
)
152 if [ $# -eq 0 ]; then
156 for param
in "$@"; do
159 max-age
=0) return 1;;
167 # get_keytab QPARAMS curl-opts
169 url
="http://${server}:${restport}/get-keys?$1"
171 HTTP
$verbose "$@" "$url"
174 # get_keytab_POST QPARAMS curl-opts
176 # Curl is awful, so if you don't use -f, you don't get non-zero exit codes on
177 # error responses, but if you do use -f then -D doesn't work. Ugh.
179 # So first we check that POST w/o CSRF token fails:
183 get_keytab
"$q" -X POST
--data-binary @
/dev
/null
-f "$@" &&
184 { echo "POST succeeded w/o CSRF token!"; return 1; }
185 get_keytab
"$q" -X POST
--data-binary @
/dev
/null
"$@"
186 grep ^X-CSRF-Token
: response-headers
>/dev
/null ||
return 1
187 get_keytab
"$q" -X POST
--data-binary @
/dev
/null \
188 -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" "$@"
189 grep '^HTTP/1.1 200' response-headers
>/dev
/null ||
return $?
193 get_keytab_POST_redir
() {
194 url
="http://${server}:${restport}/get-keys?$1"
196 HTTP
-X POST
--data-binary @
/dev
/null
"$@" "$url"
197 grep ^X-CSRF-Token
: response-headers
>/dev
/null ||
198 { echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
199 HTTP
-X POST
--data-binary @
/dev
/null
-f \
200 -H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \
201 --location --location-trusted "$@" "$url"
211 { echo signal killing kdc
; kill -9 "$kdcpid"; }
212 test -n "$httpkadmindpid" &&
213 { echo signal killing httpkadmind
; kill -9 "$httpkadmindpid"; }
214 test -n "$httpkadmind2pid" &&
215 { echo signal killing httpkadmind
; kill -9 "$httpkadmind2pid"; }
216 test -n "$kadmindpid" &&
217 { echo signal killing kadmind
; kill -9 "$kadmindpid"; }
218 test -n "$kadmind2pid" &&
219 { echo signal killing kadmind
; kill -9 "$kadmind2pid"; }
223 rm -f extracted_keytab
225 echo "Creating database"
228 --realm-max-ticket-life=1day \
229 --realm-max-renewable-life=1month \
231 ${kadmin} add
-r --use-defaults foo@
${R} ||
exit 1
232 ${kadmin} add
-r --use-defaults httpkadmind
/admin@
${R} ||
exit 1
233 ${kadmin} add
-r --use-defaults WELLKNOWN
/CSRFTOKEN@
${R} ||
exit 1
234 ${kadmin} add
-r --use-defaults HTTP
/localhost@
${R} ||
exit 1
235 ${kadmin} add -r --use-defaults host/xyz.${domain}@${R} ||
exit 1
236 ${kadmin} add -r --use-defaults HTTP/xyz.${domain}@${R} ||
exit 1
237 ${kadmin} add_ns
--key-rotation-epoch=-1d --key-rotation-period=5m \
238 --max-ticket-life=1d
--max-renewable-life=5d \
239 --attributes= HTTP
/ns.
${domain}@
${R} ||
exit 1
240 ${kadmin} add_ns
--key-rotation-epoch=-1d --key-rotation-period=5m \
241 --max-ticket-life=1d
--max-renewable-life=5d \
242 --attributes=ok-as-delegate host
/.ns2.
${domain}@
${R} ||
exit 1
243 ${kadmin} add -r --use-defaults HTTP/${server}@${R} ||
exit 1
244 ${kadmin} ext_keytab
-r -k $keytab kadmin
/admin@
${R} ||
exit 1
245 ${kadmin} ext_keytab
-r -k $keytab httpkadmind
/admin@
${R} ||
exit 1
246 ${kadmin} ext_keytab -r -k $keytab HTTP/${server}@${R} ||
exit 1
247 ${kadmin} ext_keytab
-r -k $keytab HTTP
/localhost@
${R} ||
exit 1
248 ${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} ||
exit 1
249 ${kadmin} ext_keytab
-r -k $ukeytab foo@
${R} ||
exit 1
252 # For a while let's not bother with a KDC
253 $kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
254 -c foo@
${R} -s HTTP
/datan.
test.h5l.se@
${R} ||
255 { echo "failed to setup kimpersonate credentials"; exit 2; }
256 $kimpersonate -A --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
257 -c foo@
${R} -s HTTP
/localhost@
${R} ||
258 { echo "failed to setup kimpersonate credentials"; exit 2; }
259 $klist -t >/dev
/null ||
260 { echo "failed to setup kimpersonate credentials"; exit 2; }
262 echo "Starting httpkadmind"
263 ${httpkadmind} -H $server -H localhost
--local -t --daemon ||
264 { echo "httpkadmind failed to start"; exit 2; }
265 httpkadmindpid
=`getpid httpkadmind`
268 echo "Checking that concrete principal exists"
269 ${kadmin} get HTTP
/xyz.
${domain} > /dev
/null ||
270 { echo "Failed to create HTTP/xyz.${domain}"; exit 1; }
271 echo "Checking that virtual principal exists"
272 ${kadmin} get HTTP
/foo.ns.
${domain} > /dev
/null ||
273 { echo "Virtual principals not working"; exit 1; }
277 echo "Fetching krb5.conf for $p"
278 get_config
"princ=$p" -sf -o "${objdir}/extracted_config" ||
279 { echo "Failed to get config for $p"; exit 1; }
280 read config
< "${objdir}/extracted_config"
281 test "$config" = "include /etc/krb5.conf" ||
282 { echo "Got unexpected default config for $p"; exit 1; }
283 ${kadmin} mod
--krb5-config-file="$KRB5_CONFIG" $p ||
284 { echo "Failed to set config for $p"; exit 1; }
285 get_config
"princ=$p" -sf -o "${objdir}/extracted_config" ||
286 { echo "Failed to get config for $p"; exit 1; }
287 cmp "${objdir}/extracted_config" "$KRB5_CONFIG" ||
288 { echo "Got unexpected config for $p"; exit 1; }
292 echo "Fetching keytab for concrete principal $p"
293 rm -f extracted_keytab
*
294 grant dnsname
$hn foo@
${R}
295 ${kadmin} ext_keytab
-k extracted_keytab
$p ||
296 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
297 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
298 { echo "Failed to list keytab for $p"; exit 1; }
299 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
300 { echo "Failed to get a keytab for $p with curl"; exit 1; }
301 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
302 { echo "Failed to list keytab for $p"; exit 1; }
303 cmp extracted_keytab.kadmin extracted_keytab.rest ||
304 { echo "Keytabs for $p don't match!"; exit 1; }
308 echo "Fetching keytab for virtual principal $p"
309 rm -f extracted_keytab
*
310 grant dnsname
$hn foo@
${R}
311 ${kadmin} ext_keytab
-k extracted_keytab
$p ||
312 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
313 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
314 { echo "Failed to list keytab for $p"; exit 1; }
315 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
316 { echo "Failed to get a keytab for $p with curl"; exit 1; }
318 grep -i ^Cache-Control response-headers
319 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
320 { echo "Failed to list keytab for $p"; exit 1; }
321 cmp extracted_keytab.kadmin extracted_keytab.rest ||
322 { echo "Keytabs for $p don't match!"; exit 1; }
325 hn2
=foobar.ns.
${domain}
330 echo "Fetching keytabs for more than one principal"
331 rm -f extracted_keytab
*
332 grant dnsname
$hn1 foo@
${R}
333 grant dnsname
$hn2 foo@
${R}
334 grant dnsname
$hn3 foo@
${R}
335 # Note that httpkadmind will first process dNSName q-params, then the spn
337 ${kadmin} ext_keytab
-k extracted_keytab
$p1 ||
338 { echo "Failed to get a keytab for $p1 with kadmin"; exit 1; }
339 ${kadmin} ext_keytab
-k extracted_keytab
$p3 ||
340 { echo "Failed to get a keytab for $p3 with kadmin"; exit 1; }
341 ${kadmin} ext_keytab
-k extracted_keytab
$p2 ||
342 { echo "Failed to get a keytab for $p2 with kadmin"; exit 1; }
343 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
344 { echo "Failed to list keytab for multiple principals"; exit 1; }
345 get_keytab
"dNSName=${hn1}&spn=${p2}&dNSName=${hn3}" -sf -o "${objdir}/extracted_keytab" ||
346 { echo "Failed to get a keytab for multiple principals with curl"; exit 1; }
347 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
348 { echo "Failed to list keytab for $p"; exit 1; }
349 cmp extracted_keytab.kadmin extracted_keytab.rest ||
350 { echo "Keytabs for $p don't match!"; exit 1; }
351 grep $hn1 extracted_keytab.rest
> /dev
/null ||
352 { echo "Keytab does not include keys for $p1"; exit 1; }
353 grep $hn2 extracted_keytab.rest
> /dev
/null ||
354 { echo "Keytab does not include keys for $p2"; exit 1; }
355 grep $hn3 extracted_keytab.rest
> /dev
/null ||
356 { echo "Keytab does not include keys for $p3"; exit 1; }
358 p
=host
/foo.ns.
${domain}
359 echo "Checking that $p doesn't exist (no namespace for host service)"
360 get_keytab
"svc=host&dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab.rest" &&
361 { echo "Got a keytab for host/foo.ns.${domain} when not namespaced!"; }
363 echo "Checking that authorization is enforced"
365 get_keytab
"dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
366 { echo "Got a keytab for HTTP/xyz.${domain} when not authorized!"; exit 1; }
367 get_keytab
"dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab" &&
368 { echo "Got a keytab for HTTP/foo.ns.${domain} when not authorized!"; exit 1; }
370 echo "Checking that host service keys are not served"
373 echo "Fetching keytab for virtual principal $p"
374 rm -f extracted_keytab
*
375 grant dnsname
$hn foo@
${R}
376 get_keytab
"service=host&dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
377 { echo "Got a keytab for $p even though it is a host service!"; exit 1; }
378 get_keytab
"spn=host/xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
379 { echo "Got a keytab for $p even though it is a host service!"; exit 1; }
384 echo "Checking key rotation for concrete principal $p"
385 rm -f extracted_keytab
*
386 grant dnsname
$hn foo@
${R}
387 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
388 { echo "Failed to get a keytab for $p with curl"; exit 1; }
389 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest1 ||
390 { echo "Failed to list keytab for $p"; exit 1; }
391 test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
392 { echo "Wrong number of new keys!"; exit 1; }
393 get_keytab
"dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
394 { echo "GET succeeded for write operation!"; exit 1; }
395 get_keytab_POST
"dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
396 { echo "Failed to rotate keys for $p"; exit 1; }
397 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest2 ||
398 { echo "Failed to list keytab for $p"; exit 1; }
399 cmp extracted_keytab.rest1 extracted_keytab.rest2
> /dev
/null
&&
400 { echo "Keys for $p did not change!"; exit 1; }
401 test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
402 { echo "Wrong number of new keys!"; exit 1; }
406 echo "Checking key rotation w/ revocation for concrete principal $p"
407 rm -f extracted_keytab
*
408 grant dnsname
$hn foo@
${R}
409 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
410 { echo "Failed to get a keytab for $p with curl"; exit 1; }
411 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest1 ||
412 { echo "Failed to list keytab for $p"; exit 1; }
413 get_keytab
"dNSName=${hn}&revoke=true" -sf -o "${objdir}/extracted_keytab" &&
414 { echo "GET succeeded for write operation!"; exit 1; }
415 get_keytab_POST
"dNSName=${hn}&revoke=true" -s -o "${objdir}/extracted_keytab" ||
416 { echo "Failed to get a keytab for $p with curl"; exit 1; }
417 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest2 ||
418 { echo "Failed to list keytab for $p"; exit 1; }
419 cmp extracted_keytab.rest1 extracted_keytab.rest2
> /dev
/null
&&
420 { echo "Keys for $p did not change!"; exit 1; }
421 test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 1 ||
422 { echo "Wrong number of new keys!"; exit 1; }
426 echo "Checking concrete principal creation ($p)"
427 rm -f extracted_keytab
428 grant dnsname
$hn foo@
${R}
429 get_keytab
"dNSName=${hn}&create=true" -sf -o "${objdir}/extracted_keytab" &&
430 { echo "GET succeeded for write operation!"; exit 1; }
431 get_keytab_POST
"dNSName=${hn}&create=true" -s -o "${objdir}/extracted_keytab" ||
432 { echo "Failed to get a keytab for $p with curl"; exit 1; }
433 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
434 { echo "Failed to list keytab for $p"; exit 1; }
435 rm -f extracted_keytab
436 ${kadmin} ext_keytab
-k extracted_keytab
$p ||
437 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
438 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
439 { echo "Failed to list keytab for $p"; exit 1; }
440 cmp extracted_keytab.kadmin extracted_keytab.rest ||
441 { echo "Keytabs for $p don't match!"; exit 1; }
445 echo "Checking materialization of virtual principal ($p)"
446 rm -f extracted_keytab
447 grant dnsname
$hn foo@
${R}
448 get_keytab
"dNSName=${hn}&materialize=true" -sf -o "${objdir}/extracted_keytab" &&
449 { echo "GET succeeded for write operation!"; exit 1; }
450 get_keytab_POST
"dNSName=${hn}&materialize=true" -s -o "${objdir}/extracted_keytab" ||
451 { echo "Failed to materialize and get a keytab for $p with curl"; exit 1; }
452 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
453 { echo "Failed to list keytab for $p"; exit 1; }
454 rm -f extracted_keytab
455 ${kadmin} ext_keytab
-k extracted_keytab
$p ||
456 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
457 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
458 { echo "Failed to list keytab for $p"; exit 1; }
459 cmp extracted_keytab.kadmin extracted_keytab.rest ||
460 { echo "Keytabs for $p don't match!"; exit 1; }
462 echo "Starting secondary httpkadmind to test HTTP redirection"
463 ${httpkadmind2} --primary-server-uri=http
://localhost
:$restport \
464 -H $server --local --local-read-only -t --daemon ||
465 { echo "httpkadmind failed to start"; exit 2; }
466 httpkadmind2pid
=`getpid httpkadmind`
472 echo "Checking principal creation at secondary yields redirect"
473 rm -f extracted_keytab
474 grant dnsname
$hn foo@
${R}
475 get_keytab_POST_redir
"dNSName=${hn}&create=true" \
476 -s -o "${objdir}/extracted_keytab"
477 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
478 { echo "Failed to list keytab for $p"; exit 1; }
479 rm -f extracted_keytab
480 ${kadmin} ext_keytab
-k extracted_keytab
$p ||
481 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
482 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
483 { echo "Failed to list keytab for $p"; exit 1; }
484 cmp extracted_keytab.kadmin extracted_keytab.rest ||
485 { echo "Keytabs for $p don't match!"; exit 1; }
487 echo "killing httpkadmind (${httpkadmindpid} ${httpkadmind2pid})"
488 sh
${leaks_kill} httpkadmind
$httpkadmindpid || ec
=1
489 sh
${leaks_kill} httpkadmind
$httpkadmind2pid || ec
=1
493 { echo "Error killing httpkadmind instances or memory errors found"; exit 1; }
495 echo "Starting primary kadmind for testing httpkadmind with remote HDB"
497 { echo "Read-write kadmind failed to start"; exit 2; }
498 kadmindpid
=`getpid kadmind`
499 echo "Starting secondray (read-only) kadmind for testing httpkadmind with remote HDB"
501 { echo "Read-only kadmind failed to start"; exit 2; }
502 kadmind2pid
=`getpid kadmind`
504 # Make a ccache for use with kadmin(1)
505 $kimpersonate --ticket-flags=initial
--ccache=$admincache -k $keytab -t aes128-cts-hmac-sha1-96 \
506 -c httpkadmind
/admin@
${R} -s kadmin
/admin@
${R} ||
507 { echo "failed to setup kimpersonate credentials"; exit 2; }
508 $adminklist -t >/dev
/null ||
509 { echo "failed to setup kimpersonate credentials"; exit 2; }
512 echo "Making PKINIT certs for KDC"
513 ${hxtool} issue-certificate \
516 --ca-private-key=FILE
:${keyfile} \
517 --subject="CN=CA,DC=test,DC=h5l,DC=se" \
518 --certificate="FILE:ca.crt" ||
exit 1
519 ${hxtool} request-create \
520 --subject="CN=kdc,DC=test,DC=h5l,DC=se" \
521 --key=FILE
:${keyfile2} \
522 req-kdc.der ||
exit 1
523 ${hxtool} issue-certificate \
524 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
525 --type="pkinit-kdc" \
526 --pk-init-principal="krbtgt/TEST.H5L.SE@TEST.H5L.SE" \
527 --req="PKCS10:req-kdc.der" \
528 --certificate="FILE:kdc.crt" ||
exit 1
529 ${hxtool} request-create \
530 --subject="CN=bar,DC=test,DC=h5l,DC=se" \
531 --key=FILE
:${keyfile2} \
533 { echo "Failed to make CSR for PKINIT client cert"; exit 1; }
534 ${hxtool} issue-certificate \
535 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
536 --type="pkinit-client" \
537 --pk-init-principal="host/synthesized.${domain}@$R" \
538 --req="PKCS10:req-pkinit.der" \
540 --certificate="FILE:pkinit-synthetic.crt" ||
541 { echo "Failed to make PKINIT client cert"; exit 1; }
543 echo "Starting kdc needed for httpkadmind authentication to kadmind"
544 ${kdc} --detach --testing ||
{ echo "kdc failed to start"; cat messages.log
; exit 1; }
547 echo "Starting httpkadmind with remote HDBs only"
549 ${httpkadmind} -H $server -H localhost
-t --daemon \
550 --writable-admin-server=$
(uname
-n):$admport \
551 --read-only-admin-server=$
(uname
-n):$admport2 \
552 --kadmin-client-name=httpkadmind
/admin@
${R} \
553 --kadmin-client-keytab=$keytab ||
554 { echo "httpkadmind failed to start"; exit 2; }
555 httpkadmindpid
=`getpid httpkadmind`
560 echo "Fetching keytab for concrete principal $p using remote HDB"
561 rm -f extracted_keytab
*
562 grant dnsname
$hn httpkadmind
/admin@
${R}
563 KRB5CCNAME
=$admincache ${kadmin} ext_keytab
-k extracted_keytab
$p ||
564 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
565 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
566 { echo "Failed to list keytab for $p"; exit 1; }
567 get_keytab
"spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
568 { echo "Failed to get a keytab for $p with curl"; exit 1; }
569 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
570 { echo "Failed to list keytab for $p"; exit 1; }
571 cmp extracted_keytab.kadmin extracted_keytab.rest ||
572 { echo "Keytabs for $p don't match!"; exit 1; }
576 echo "Checking key rotation for concrete principal $p using remote HDB"
577 rm -f extracted_keytab
*
578 grant dnsname
$hn foo@
${R}
579 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
580 { echo "Failed to get a keytab for $p with curl"; exit 1; }
581 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest1 ||
582 { echo "Failed to list keytab for $p"; exit 1; }
583 test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
584 { echo "Wrong number of new keys!"; exit 1; }
585 get_keytab
"dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
586 { echo "GET succeeded for write operation!"; exit 1; }
587 get_keytab_POST
"dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
588 { echo "Failed to rotate keys for $p"; exit 1; }
589 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest2 ||
590 { echo "Failed to list keytab for $p"; exit 1; }
591 cmp extracted_keytab.rest1 extracted_keytab.rest2
> /dev
/null
&&
592 { echo "Keys for $p did not change!"; exit 1; }
593 test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
594 { echo "Wrong number of new keys!"; exit 1; }
596 sh
${leaks_kill} httpkadmind
$httpkadmindpid || ec
=1
599 echo "Starting httpkadmind with local read-only HDB and remote read-write HDB"
600 ${httpkadmind} -H $server -H localhost
-t --daemon \
602 --writable-admin-server=$
(uname
-n):$admport \
603 --kadmin-client-name=httpkadmind
/admin@
${R} \
604 --kadmin-client-keytab=$keytab ||
605 { echo "httpkadmind failed to start"; exit 2; }
606 httpkadmindpid
=`getpid httpkadmind`
611 echo "Fetching keytab for concrete principal $p using local read-only HDB"
612 rm -f extracted_keytab
*
613 grant dnsname
$hn httpkadmind
/admin@
${R}
614 KRB5CCNAME
=$admincache ${kadmin} ext_keytab
-k extracted_keytab
$p ||
615 { echo "Failed to get a keytab for $p with kadmin"; exit 1; }
616 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.kadmin ||
617 { echo "Failed to list keytab for $p"; exit 1; }
618 get_keytab
"spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
619 { echo "Failed to get a keytab for $p with curl"; exit 1; }
620 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest ||
621 { echo "Failed to list keytab for $p"; exit 1; }
622 cmp extracted_keytab.kadmin extracted_keytab.rest ||
623 { echo "Keytabs for $p don't match!"; exit 1; }
627 echo "Checking key rotation for concrete principal $p using local read-only HDB and remote HDB"
628 rm -f extracted_keytab
*
629 grant dnsname
$hn foo@
${R}
630 get_keytab
"dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
631 { echo "Failed to get a keytab for $p with curl"; exit 1; }
632 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest1 ||
633 { echo "Failed to list keytab for $p"; exit 1; }
634 test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 ||
635 { echo "Wrong number of new keys!"; exit 1; }
636 get_keytab
"dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
637 { echo "GET succeeded for write operation!"; exit 1; }
638 get_keytab_POST
"dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
639 { echo "Failed to rotate keys for $p"; exit 1; }
640 ${ktutil} -k "${objdir}/extracted_keytab" list
--keys > extracted_keytab.rest2 ||
641 { echo "Failed to list keytab for $p"; exit 1; }
642 cmp extracted_keytab.rest1 extracted_keytab.rest2
> /dev
/null
&&
643 { echo "Keys for $p did not change!"; exit 1; }
644 test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 ||
645 { echo "Wrong number of new keys!"; exit 1; }
647 echo "Checking that host services as clients can self-create"
648 hn
=synthesized.
${domain}
650 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
&&
651 { echo "Internal error -- $p exists too soon"; exit 1; }
652 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
653 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
654 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
655 rm -f extracted_keytab
*
657 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
658 { echo "Failed to create and extract host keys for self"; exit 1; }
659 ${ktutil} -k "${objdir}/extracted_keytab" list
> /dev
/null ||
660 { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
661 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null ||
662 { echo "Failed to create and extract host keys for self"; exit 1; }
664 echo "Checking that host services can't get other host service principals"
665 hn
=nonexistent.
${domain}
668 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab2" &&
669 { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
670 ${ktutil} -k "${objdir}/extracted_keytab2" list
> /dev
/null || true
671 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
&&
672 { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
674 echo "Checking that host services can't get keys for themselves and others"
675 hn
=synthesized.
${domain}
677 p2
=host
/nonexistent.
${domain}
678 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
679 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
680 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
681 rm -f extracted_keytab
*
683 get_keytab_POST
"spn=$p&spn=$p2&create=true" -s -o "${objdir}/extracted_keytab" &&
684 { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
685 ${ktutil} -k "${objdir}/extracted_keytab2" list
> /dev
/null || true
686 KRB5CCNAME
=$admincache ${kadmin} get
-s $p2 >/dev
/null
&&
687 { echo "Failed to fail to create and extract host keys for other!"; exit 1; }
689 echo "Checking that attributes for new principals can be configured"
690 hn
=a-particular-hostname.
test.h5l.se
692 ${hxtool} issue-certificate \
693 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
694 --type="pkinit-client" \
695 --pk-init-principal="$p@$R" \
696 --req="PKCS10:req-pkinit.der" \
698 --certificate="FILE:pkinit-synthetic.crt" ||
699 { echo "Failed to make PKINIT client cert"; exit 1; }
700 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
2>&1 &&
701 { echo "Internal error -- $p exists too soon"; exit 1; }
702 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
703 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
704 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
705 rm -f extracted_keytab
*
707 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
708 { echo "Failed to create and extract host keys for self"; exit 1; }
709 ${ktutil} -k "${objdir}/extracted_keytab" list
> /dev
/null ||
710 { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
711 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null ||
712 { echo "Failed to create and extract host keys for self"; exit 1; }
713 KRB5CCNAME
=$admincache ${kadmin} get
$p |
714 grep 'Attributes:.*ok-as-delegate' > /dev
/null ||
715 { echo "Failed to create with configured attributes"; exit 1; }
716 KRB5CCNAME
=$admincache ${kadmin} get
$p |
717 grep 'Attributes:.*no-auth-data-reqd' > /dev
/null ||
718 { echo "Failed to create with configured attributes"; exit 1; }
720 hn
=other-hostname.
test.h5l.se
722 ${hxtool} issue-certificate \
723 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
724 --type="pkinit-client" \
725 --pk-init-principal="$p@$R" \
726 --req="PKCS10:req-pkinit.der" \
728 --certificate="FILE:pkinit-synthetic.crt" ||
729 { echo "Failed to make PKINIT client cert"; exit 1; }
730 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
2>&1 &&
731 { echo "Internal error -- $p exists too soon"; exit 1; }
732 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
733 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
734 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
735 rm -f extracted_keytab
*
737 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
738 { echo "Failed to create and extract host keys for self"; exit 1; }
739 ${ktutil} -k "${objdir}/extracted_keytab" list
> /dev
/null ||
740 { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
741 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null ||
742 { echo "Failed to create and extract host keys for self"; exit 1; }
743 KRB5CCNAME
=$admincache ${kadmin} get
$p |
744 grep 'Attributes:.*ok-as-delegate' > /dev
/null
&&
745 { echo "Create with unexpected attributes"; exit 1; }
746 KRB5CCNAME
=$admincache ${kadmin} get
$p |
747 grep 'Attributes:.*no-auth-data-reqd' > /dev
/null
&&
748 { echo "Create with unexpected attributes"; exit 1; }
750 hn
=a-server.prod.
test.h5l.se
752 ${hxtool} issue-certificate \
753 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
754 --type="pkinit-client" \
755 --pk-init-principal="$p@$R" \
756 --req="PKCS10:req-pkinit.der" \
758 --certificate="FILE:pkinit-synthetic.crt" ||
759 { echo "Failed to make PKINIT client cert"; exit 1; }
760 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
2>&1 &&
761 { echo "Internal error -- $p exists too soon"; exit 1; }
762 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
763 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
764 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
765 rm -f extracted_keytab
*
767 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
768 { echo "Failed to create and extract host keys for self"; exit 1; }
769 ${ktutil} -k "${objdir}/extracted_keytab" list
> /dev
/null ||
770 { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
771 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null ||
772 { echo "Failed to create and extract host keys for self"; exit 1; }
773 KRB5CCNAME
=$admincache ${kadmin} get
$p |
774 grep 'Attributes:.*ok-as-delegate' > /dev
/null ||
775 { echo "Failed to create with configured attributes"; exit 1; }
776 KRB5CCNAME
=$admincache ${kadmin} get
$p |
777 grep 'Attributes:.*no-auth-data-reqd' > /dev
/null ||
778 { echo "Failed to create with configured attributes"; exit 1; }
780 hn
=a-host.ns2.
test.h5l.se
782 ${hxtool} issue-certificate \
783 --ca-certificate=FILE
:$objdir/ca.crt
,${keyfile} \
784 --type="pkinit-client" \
785 --pk-init-principal="$p@$R" \
786 --req="PKCS10:req-pkinit.der" \
788 --certificate="FILE:pkinit-synthetic.crt" ||
789 { echo "Failed to make PKINIT client cert"; exit 1; }
790 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null
2>&1 &&
791 { echo "Internal error -- $p exists too soon"; exit 1; }
792 ${kinit2} -C "FILE:${objdir}/pkinit-synthetic.crt,${keyfile2}" ${p}@${R} || \
793 { echo "Failed to kinit with PKINIT client cert"; exit 1; }
794 ${kgetcred2} HTTP
/localhost@
$R ||
echo WAT
795 rm -f extracted_keytab
*
797 get_keytab_POST
"spn=$p&create=true" -s -o "${objdir}/extracted_keytab" ||
798 { echo "Failed to create and extract host keys for self"; exit 1; }
799 ${ktutil} -k "${objdir}/extracted_keytab" list
> /dev
/null ||
800 { echo "Failed to create and extract host keys for self (bogus keytab)"; exit 1; }
801 KRB5CCNAME
=$admincache ${kadmin} get
-s $p >/dev
/null ||
802 { echo "Failed to create and extract host keys for self"; exit 1; }
803 KRB5CCNAME
=$admincache ${kadmin} get
$p |
804 grep 'Attributes:.*ok-as-delegate' > /dev
/null ||
805 { echo "Failed to create with namespace attributes"; exit 1; }
806 KRB5CCNAME
=$admincache ${kadmin} get
$p |
807 grep 'Attributes:.*no-auth-data-reqd' > /dev
/null
&&
808 { echo "Create with unexpected attributes"; exit 1; }
810 grep 'Internal error' messages.log
&&
811 { echo "Internal errors in log"; exit 1; }
813 sh
${leaks_kill} httpkadmind
$httpkadmindpid || ec
=1
814 sh
${leaks_kill} kadmind
$kadmindpid || ec
=1
815 sh
${leaks_kill} kadmind
$kadmind2pid || ec
=1
816 sh
${leaks_kill} kdc
$kdcpid || ec
=1
825 # - implement and test that we can materialize a principal yet leave it with
827 # - test new key delay? this one is tricky