kdc: Add httpkadmind

TBD:

 - improve error handling, logging, tracing!
 - move all REST services out of kdc/
This commit is contained in:
Nicolas Williams
2020-08-19 01:43:06 -05:00
parent ea83f068e9
commit 9574783d04
8 changed files with 3330 additions and 4 deletions

View File

@@ -44,6 +44,24 @@ bx509d_LDADD = -ldl \
$(top_builddir)/lib/hx509/libhx509.la \
$(top_builddir)/lib/gssapi/libgssapi.la
libexec_PROGRAMS += bx509d
httpkadmind_SOURCES = httpkadmind.c
httpkadmind_AM_CPPFLAGS = $(AM_CPPFLAGS) $(MICROHTTPD_CFLAGS)
httpkadmind_LDADD = -ldl \
$(top_builddir)/lib/hdb/libhdb.la \
$(top_builddir)/lib/kadm5/libkadm5clnt.la \
$(top_builddir)/lib/kadm5/libkadm5srv.la \
libkdc.la \
$(MICROHTTPD_LIBS) \
$(LIB_roken) \
$(LIB_heimbase) \
$(LIB_hcrypto) \
$(top_builddir)/lib/sl/libsl.la \
$(top_builddir)/lib/asn1/libasn1.la \
$(top_builddir)/lib/krb5/libkrb5.la \
$(top_builddir)/lib/hx509/libhx509.la \
$(top_builddir)/lib/gssapi/libgssapi.la
libexec_PROGRAMS += httpkadmind
endif
digest_service_SOURCES = \
@@ -116,6 +134,7 @@ ALL_OBJECTS += $(hprop_OBJECTS)
ALL_OBJECTS += $(hpropd_OBJECTS)
ALL_OBJECTS += $(digest_service_OBJECTS)
ALL_OBJECTS += $(bx509d_OBJECTS)
ALL_OBJECTS += $(httpkadmind_OBJECTS)
ALL_OBJECTS += $(cjwt_token_validator_la_OBJECTS)
ALL_OBJECTS += $(simple_csr_authorizer_la_OBJECTS)
ALL_OBJECTS += $(test_token_validator_OBJECTS)

407
kdc/httpkadmind.8 Normal file
View File

@@ -0,0 +1,407 @@
.\" Copyright (c) 2020 Kungliga Tekniska Högskolan
.\" (Royal Institute of Technology, Stockholm, Sweden).
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" 3. Neither the name of the Institute nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.Dd January 2, 2020
.Dt HTTPKADMIND 8
.Os HEIMDAL
.Sh NAME
.Nm httpkadmind
.Nd HTTP HDB Administration Interface
.Sh SYNOPSIS
.Nm
.Op Fl h | Fl Fl help
.Op Fl Fl version
.Op Fl H Ar HOSTNAME
.Op Fl d | Fl Fl daemon
.Op Fl Fl daemon-child
.Op Fl Fl reverse-proxied
.Op Fl p Ar port number (default: 443)
.Op Fl Fl temp-dir= Ns Ar DIRECTORY
.Op Fl Fl cert=HX509-STORE
.Op Fl Fl private-key=HX509-STORE
.Op Fl T | Fl Fl token-authentication-type=Negotiate|Bearer
.Op Fl Fl realm=REALM
.Op Fl Fl read-only
.Op Fl l | Fl Fl local
.Op Fl Fl local-read-only
.Op Fl Fl hdb=HDB
.Op Fl Fl stash-file=FILENAME
.Op Fl Fl primary-server-uri=URI
.Op Fl Fl read-only-admin-server=HOSTNAME[:PORT]
.Op Fl Fl writable-admin-server=HOSTNAME[:PORT]
.Op Fl Fl kadmin-client-name=PRINCIPAL
.Op Fl Fl kadmin-client-keytab=KEYTAB
.Op Fl t | Fl Fl thread-per-client
.Oo Fl v \*(Ba Xo
.Fl Fl verbose= Ns Ar run verbosely
.Xc
.Oc
.Sh DESCRIPTION
Serves the following resources:
.Ar /get-keys and
.Ar /get-config .
.Pp
The
.Ar /get-keys
end-point allows callers to get keytab content for named
principals, possibly performing write operations such as creating
a non-existent principal, or rotating its keys, if requested.
.Pp
The
.Ar /get-config
end-point allows callers to get
.Nm krb5.conf
contents for a given principal.
.Pp
This service can run against a local HDB, or against a remote HDB
via the
.Nm kadmind(8)
protocol.
Read operations are always allowed, but write operations can be
preformed either against writable
.Nm kadmind(8)
server(s) or redirected to another
.Nm httpkadmind(8).
.Pp
The
.Ar /get-config
end-point accepts a single query parameter:
.Bl -tag -width Ds -offset indent
.It Ar princ=PRINCIPAL .
.El
.Pp
The
.Ar /get-keys
end-point accepts various parameters:
.Bl -tag -width Ds -offset indent
.It Ar spn=PRINCIPAL
Names the host-based service principal whose keys to get.
May be given multiple times, and all named principal's keys will
be fetched.
.It Ar dNSName=HOSTNAME
Names the host-based service principal's hostname whose keys to get.
May be given multiple times, and all named principal's keys will
be fetched.
.It Ar service=SERVICE
Hostnames given with
.Ar dNSName=HOSTNAME
will be qualified with this service name to form a host-based
service principal.
May be given multiple times, in which case the cartesian product
of
.Ar dNSName=HOSTNAME
ad
.Ar service=SERVICE
will be used.
Defaults to
.Ar HTTP .
.It realm=REALM
Must be present if the
.Nm httpkadmind
daemon's default realm is not desired.
.It Ar enctypes=ENCTYPE,...
A comma-separated list of enctypes that the principal is expected
to support (used for Kerberos Ticket session key negotiation).
Defaults to the
.Ar supported_enctypes
configured in
.Nm krb5.conf(5) .
.It Ar materialize=true
If the named principal(s) is (are) virtual, this will cause it
(them) to be materialized as a concrete principal.
(Currently not supported.)
.It Ar create=true
If the named principal(s) does not (do not) exist, this will
cause it (them) to be created.
.It Ar rotate=true
This will cause the keys of concrete principals to be rotated.
.It Ar revoke=true
This will cause old keys of concrete principals to be deleted
if their keys are being rotated.
This means that extant service tickets with those principals as
the target will not be able to be decrypted by the caller as it
will not have the necessary keys.
.El
.Pp
Authorization is handled via the same mechanism as in
.Nm bx509d(8)
which was originally intended to authorize certification requests
(CSRs).
Authorization for extracting keys is specified like for
.Nm bx509d(8) ,
but using
.Nm [ext_keytab]
as the
.Nm krb5.conf(5) section.
.Pp
Supported options:
.Bl -tag -width Ds -offset indent
.It Xo
.Fl h ,
.Fl Fl help
.Xc
Print usage message.
.It Xo
.Fl Fl version
.Xc
Print version.
.It Xo
.Fl H Ar HOSTNAME
.Xc
Expected audience(s) of bearer tokens (i.e., acceptor name).
.It Xo
.Fl d ,
.Fl Fl daemon
.Xc
Detach from TTY and run in the background.
.It Xo
.Fl Fl reverse-proxied
.Xc
Serves HTTP instead of HTTPS, accepting only looped-back connections.
.It Xo
.Fl p Ar port number (default: 443)
.Xc
PORT
.It Xo
.Fl Fl temp-dir= Ns Ar DIRECTORY
.Xc
Directory for temp files.
If not specified then a temporary directory will be made.
.It Xo
.Fl Fl cert= Ns Ar HX509-STORE
.Xc
Certificate file path (PEM) for HTTPS service.
May contain private key as well.
.It Xo
.Fl Fl private-key= Ns Ar HX509-STORE
.Xc
Private key file path (PEM), if the private key is not stored along with the
certificiate.
.It Xo
.Fl T Ar HTTP-AUTH-TYPE,
.Fl Fl token-authentication-type= Ns Ar HTTP-AUTH-TYPE
.Xc
HTTP bearer token authentication type(s) supported (may be given more than
once).
For example,
.Ar Negotiate
or
.Ar Bearer
(JWT).
.It Xo
.Fl t ,
.Fl Fl thread-per-client
.Xc
Uses a thread per-client instead of as many threads as there are CPUs.
.It Xo
.Fl Fl realm= Ns Ar REALM
.Xc
The realm to serve, if not the default realm.
Note that clients can request keys for principals in other realms, and
.Nm httpkadmind
will attempt to satisfy those requests too.
.It Xo
.Fl Fl read-only
.Xc
Do not perform write operations.
Write operations will either fail or if a primary
.Nm httpkadmind
URI is configured, then they will be redirected there.
.It Xo
.Fl Fl local
.Xc
Use a local HDB, at least for read operations, and, if
.Fl Fl local-read-only
is not given, then also write operations.
.It Xo
.Fl Fl local-read-only
.Xc
Do not perform writes on a local HDB.
Either redirect write operations if a primary
.Nm httpkadmind
URI is configured, or use a writable remote
.Nm kadmind
server.
.It Xo
.Fl Fl hdb=HDB
.Xc
A local HDB to serve.
Note that this can be obtained from the
.Nm krb5.conf .
.It Xo
.Fl Fl stash-file=FILENAME
.Xc
A stash file containing a master key for a local HDB.
Note that this can be obtained from the
.Nm krb5.conf .
.It Xo
.Fl Fl primary-server-uri=URI
.Xc
The URL of an httpkadmind to which to redirect write operations.
.It Xo
.Fl Fl read-only-admin-server=HOSTNAME[:PORT]
.Xc
The hostname (and possibly port number) of a
.Nm kadmind(8)
service to use for read-only operations.
Recall that the
.Nm kadmind(8)
service's principal name is
.Ar kadmin/admin .
The
.Ar HOSTNAME
given here can be a name that resolves to the IP addresses of all
the
.Nm kadmind(8)
services for the
.Ar REALM .
If not specified, but needed, this will be obtained by looking for
.Nm readonly_admin_server
in
.Nm krb5.conf
or, if enabled, performing
DNS lookups for SRV resource records named
.Ar _kerberos-adm-readonly._tcp.<realm> .
.It Xo
.Fl Fl writable-admin-server=HOSTNAME[:PORT]
.Xc
The hostname (and possibly port number) of a
.Nm kadmind(8)
service to use for write operations.
If not specified, but needed, this will be obtained by looking for
.Nm admin_server
in
.Nm krb5.conf
or, if enabled, performing DNS lookups for SRV resource records named
.Ar _kerberos-adm._tcp.<realm> .
.It Xo
.Fl Fl kadmin-client-name=PRINCIPAL
.Xc
The client principal name to use when connecting to a
.Nm kadmind(8)
server.
Defaults to
.Ar httpkadmind/admin .
.It Xo
.Fl Fl kadmin-client-keytab=KEYTAB
.Xc
The keytab containing keys for the
.Ar kadmin-client-name .
Note that you may use an
.Ar HDB
as a keytab as
.Ar HDBGET:/var/heimdal/heimdal.db
(or whatever the HDB specification is).
.It Xo
.Fl v ,
.Fl Fl verbose= Ns Ar run verbosely
.Xc
verbose
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It Ev KRB5_CONFIG
The file name of
.Pa krb5.conf ,
the default being
.Pa /etc/krb5.conf .
.El
.Sh FILES
.Bl -tag -width Ds
.It Pa /etc/krb5.conf
.El
.Sh CONFIGURATION
Authorizer configuration goes in
.Br
.Ar [ext_keytab]
in
.Nm krb5.conf(5). For example:
.Pp
[ext_keytab]
simple_csr_authorizer_directory = /etc/krb5/simple_csr_authz
ipc_csr_authorizer = {
service = UNIX:/var/heimdal/csr_authorizer_sock
}
.Sh EXAMPLES
To start
.Nm httpkadmind
on a primary KDC:
.Pp
.Ar $ httpkadmind -d --cert=PEM-FILE:/etc/httpkadmind.pem
\\
.Br
--local -T Negotiate
.Pp
To start
.Nm httpkadmind
on a secondary KDC, using redirects for write operations:
.Pp
.Ar $ httpkadmind -d --cert=PEM-FILE:/etc/httpkadmind.pem
\\
.Br
--local-read-only -T Negotiate
\\
.Br
--primary-server-uri=https://the-primary-server.fqdn/
.Pp
To start
.Nm httpkadmind
on a secondary KDC, proxying kadmin to perform writes at the primary KDC, using
DNS to discover the kadmin server:
.Pp
.Ar $ httpkadmind -d --cert=PEM-FILE:/etc/httpkadmind.pem
\\
.Br
--local-read-only -T Negotiate
\\
.Br
--kadmin-client-keytab=FILE:/etc/krb5.keytab
.Pp
To start
.Nm httpkadmind
on a non-KDC:
.Pp
.Ar $ httpkadmind -d --cert=PEM-FILE:/etc/httpkadmind.pem
\\
.Br
-T Negotiate --kadmin-client-keytab=FILE:/etc/krb5.keytab
.Pp
.Sh DIAGNOSTICS
See logging section of
.Nm krb5.conf.5
.Sh SEE ALSO
.Xr bx509d 8 ,
.Xr kadmin 1 ,
.Xr kadmind 8 ,
.Xr krb5.conf 5 .
.\".Sh STANDARDS
.\".Sh HISTORY
.\".Sh AUTHORS
.\".Sh BUGS

2187
kdc/httpkadmind.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@ NO_AFS="@NO_AFS@"
# regular apps
bx509d="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/bx509d"
httpkadmind="${TESTS_ENVIRONMENT} ${top_builddir}/kdc/httpkadmind"
hxtool="${TESTS_ENVIRONMENT} ${top_builddir}/lib/hx509/hxtool"
iprop_log="${TESTS_ENVIRONMENT} ${top_builddir}/lib/kadm5/iprop-log"
ipropd_master="${TESTS_ENVIRONMENT} ${top_builddir}/lib/kadm5/ipropd-master"

View File

@@ -13,6 +13,7 @@ noinst_DATA = \
krb5-weak.conf \
krb5-pkinit.conf \
krb5-bx509.conf \
krb5-httpkadmind.conf \
krb5-pkinit-win.conf \
krb5-slave2.conf \
krb5-slave.conf
@@ -35,6 +36,7 @@ SCRIPT_TESTS = \
check-kpasswdd \
check-pkinit \
check-bx509 \
check-httpkadmind \
check-iprop \
check-referral \
check-tester \
@@ -44,9 +46,11 @@ TESTS = $(SCRIPT_TESTS)
port = 49188
admport = 49189
pwport = 49190
bx509port = 49191
ipropport = 49192
admport2 = 49190
pwport = 49191
restport = 49192
restport2 = 49193
ipropport = 49194
if HAVE_DLOPEN
do_dlopen = -e 's,[@]DLOPEN[@],true,g'
@@ -60,7 +64,10 @@ do_subst = $(heim_verbose)sed $(do_dlopen) \
-e 's,[@]srcdir[@],$(srcdir),g' \
-e 's,[@]port[@],$(port),g' \
-e 's,[@]admport[@],$(admport),g' \
-e 's,[@]bx509port[@],$(bx509port),g' \
-e 's,[@]admport2[@],$(admport2),g' \
-e 's,[@]bx509port[@],$(restport),g' \
-e 's,[@]restport[@],$(restport),g' \
-e 's,[@]restport2[@],$(restport2),g' \
-e 's,[@]pwport[@],$(pwport),g' \
-e 's,[@]ipropport[@],$(ipropport),g' \
-e 's,[@]objdir[@],$(top_builddir)/tests/kdc,g' \
@@ -153,6 +160,11 @@ check-bx509: check-bx509.in Makefile krb5-bx509.conf
$(chmod) +x check-bx509.tmp && \
mv check-bx509.tmp check-bx509
check-httpkadmind: check-httpkadmind.in Makefile krb5-httpkadmind.conf
$(do_subst) < $(srcdir)/check-httpkadmind.in > check-httpkadmind.tmp && \
$(chmod) +x check-httpkadmind.tmp && \
mv check-httpkadmind.tmp check-httpkadmind
check-iprop: check-iprop.in Makefile krb5.conf krb5-slave.conf krb5-slave2.conf
$(do_subst) < $(srcdir)/check-iprop.in > check-iprop.tmp && \
$(chmod) +x check-iprop.tmp && \
@@ -249,6 +261,10 @@ krb5-bx509.conf: krb5-bx509.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-bx509.conf.in > krb5-bx509.conf.tmp && \
mv krb5-bx509.conf.tmp krb5-bx509.conf
krb5-httpkadmind.conf: krb5-httpkadmind.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],no,g' < $(srcdir)/krb5-httpkadmind.conf.in > krb5-httpkadmind.conf.tmp && \
mv krb5-httpkadmind.conf.tmp krb5-httpkadmind.conf
krb5-pkinit-win.conf: krb5-pkinit.conf.in Makefile
$(do_subst) -e 's,[@]w2k[@],yes,g' < $(srcdir)/krb5-pkinit.conf.in > krb5-pkinit-win.conf.tmp && \
mv krb5-pkinit-win.conf.tmp krb5-pkinit-win.conf
@@ -274,6 +290,8 @@ CLEANFILES= \
current-db* \
current.log* \
digest-reply \
extracted_config \
extracted_keytab* \
foopassword \
foopassword.rkpty \
iprop-stats \
@@ -290,11 +308,13 @@ CLEANFILES= \
krb5-pkinit-win.conf \
krb5-pkinit.conf \
krb5-bx509.conf \
krb5-httpkadmind.conf \
krb5-slave2.conf \
krb5-slave.conf \
krb5-weak.conf \
krb5.conf \
krb5.conf.keys \
kt \
leaks-log \
localname \
malloc-log \
@@ -306,6 +326,7 @@ CLEANFILES= \
o2digest-reply \
ocache.krb5 \
out-log \
response-headers \
s2digest-reply \
sdb \
sdigest-init \
@@ -337,6 +358,7 @@ EXTRA_DIST = \
check-kpasswdd.in \
check-pkinit.in \
check-bx509.in \
check-httpkadmind.in \
check-referral.in \
check-tester.in \
check-uu.in \
@@ -352,6 +374,7 @@ EXTRA_DIST = \
kdc-tester4.json.in \
krb5-pkinit.conf.in \
krb5-bx509.conf.in \
krb5-httpkadmind.conf.in \
krb5.conf.in \
krb5-authz.conf.in \
krb5-authz2.conf.in \

View File

@@ -0,0 +1,588 @@
#!/bin/sh
#
# Copyright (c) 2020 Kungliga Tekniska Högskolan
# (Royal Institute of Technology, Stockholm, Sweden).
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the Institute nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
top_builddir="@top_builddir@"
env_setup="@env_setup@"
objdir="@objdir@"
testfailed="echo test failed; cat messages.log; exit 1"
. ${env_setup}
# If there is no useful db support compiled in, disable test
${have_db} || exit 77
if ! which curl > /dev/null; then
echo "curl is not available -- not testing httpkadmind"
exit 77
fi
if ! test -x ${objdir}/../../kdc/httpkadmind; then
echo "Configured w/o libmicrohttpd -- not testing httpkadmind"
exit 77
fi
R=TEST.H5L.SE
domain=test.h5l.se
port=@port@
admport=@admport@
admport1=@admport@
admport2=@admport2@
restport=@restport@
restport1=@restport@
restport2=@restport2@
server=datan.test.h5l.se
otherserver=other.test.h5l.se
cache="FILE:${objdir}/cache.krb5"
admincache="FILE:${objdir}/cache2.krb5"
keyfile="${hx509_data}/key.der"
keyfile2="${hx509_data}/key2.der"
kt=${objdir}/kt
keytab=FILE:${kt}
ukt=${objdir}/ukt
ukeytab=FILE:${ukt}
kdc="${kdc} --addresses=localhost -P $port"
kadminr="${kadmin} -r $R -a $(uname -n)"
kadmin="${kadmin} -l -r $R"
kadmind2="${kadmind} --keytab=${keytab} --detach -p $admport2 --read-only"
kadmind="${kadmind} --keytab=${keytab} --detach -p $admport"
httpkadmind2="${httpkadmind} --reverse-proxied -T Negotiate -p $restport2"
httpkadmind="${httpkadmind} --reverse-proxied -T Negotiate -p $restport1"
kinit="${kinit} -c $cache ${afs_no_afslog}"
adminklist="${klist} --hidden -v -c $admincache"
klist="${klist} --hidden -v -c $cache"
kgetcred="${kgetcred} -c $cache"
kdestroy="${kdestroy} -c $cache ${afs_no_unlog}"
kx509="${kx509} -c $cache"
KRB5_CONFIG="${objdir}/krb5-httpkadmind.conf"
export KRB5_CONFIG
KRB5CCNAME=$cache
export KRB5CCNAME
rm -f current-db*
rm -f out-*
rm -f mkey.file*
rm -f *.pem *.crt *.der
rm -rf simple_csr_authz
rm -f extracted_keytab*
mkdir -p simple_csr_authz
> messages.log
# We'll avoid using a KDC for now. For testing /httpkadmind we only need keys
# for Negotiate tokens, and we'll use ktutil and kimpersonate to make it
# possible to create and accept those without a KDC.
# grant ext-type value grantee_principal
grant() {
mkdir -p "${objdir}/simple_csr_authz/${3}"
touch "${objdir}/simple_csr_authz/${3}/${1}-${2}"
}
revoke() {
rm -rf "${objdir}/simple_csr_authz"
mkdir -p "${objdir}/simple_csr_authz"
}
if set -o|grep 'verbose.*on' > /dev/null ||
set -o|grep 'xtrace.*on' > /dev/null; then
verbose=-vvv
else
verbose=
fi
# HTTP curl-opts
HTTP() {
curl -g --resolve ${server}:${restport2}:127.0.0.1 \
--resolve ${server}:${restport}:127.0.0.1 \
-u: --negotiate $verbose "$@"
}
# get_config QPARAMS curl-opts
get_config() {
url="http://${server}:${restport}/get-config?$1"
shift
HTTP $verbose "$@" "$url"
}
# get_keytab QPARAMS curl-opts
get_keytab() {
url="http://${server}:${restport}/get-keys?$1"
shift
HTTP $verbose "$@" "$url"
}
# get_keytab_POST QPARAMS curl-opts
get_keytab_POST() {
# Curl is awful, so if you don't use -f, you don't get non-zero exit codes on
# error responses, but if you do use -f then -D doesn't work. Ugh.
#
# So first we check that POST w/o CSRF token fails:
q=$1
shift
get_keytab "$q" -X POST --data-binary @/dev/null -f "$@" &&
{ echo "POST succeeded w/o CSRF token!"; return 1; }
get_keytab "$q" -X POST --data-binary @/dev/null -D response-headers "$@"
grep ^X-CSRF-Token: response-headers >/dev/null ||
{ echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
get_keytab "$q" -X POST --data-binary @/dev/null -f \
-H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" "$@"
return $?
}
get_keytab_POST_redir() {
url="http://${server}:${restport}/get-keys?$1"
shift
HTTP -X POST --data-binary @/dev/null -D response-headers "$@" "$url"
grep ^X-CSRF-Token: response-headers >/dev/null ||
{ echo "POST w/o CSRF token had response w/o CSRF token!"; return 1; }
HTTP -X POST --data-binary @/dev/null -f \
-H "$(sed -e 's/\r//' response-headers | grep ^X-CSRF-Token:)" \
--location --location-trusted "$@" "$url"
}
kdcpid=
httpkadmindpid=
httpkadmind2pid=
kadmindpid=
kadmind2pid=
cleanup() {
test -n "$kdcpid" &&
{ echo signal killing kdc; kill -9 "$kdcpid"; }
test -n "$httpkadmindpid" &&
{ echo signal killing httpkadmind; kill -9 "$httpkadmindpid"; }
test -n "$httpkadmind2pid" &&
{ echo signal killing httpkadmind; kill -9 "$httpkadmind2pid"; }
test -n "$kadmindpid" &&
{ echo signal killing kadmind; kill -9 "$kadmindpid"; }
test -n "$kadmind2pid" &&
{ echo signal killing kadmind; kill -9 "$kadmind2pid"; }
}
trap cleanup EXIT
rm -f extracted_keytab
echo "Creating database"
rm -f $kt $ukt
${kadmin} init \
--realm-max-ticket-life=1day \
--realm-max-renewable-life=1month \
${R} || exit 1
${kadmin} add -r --use-defaults foo@${R} || exit 1
${kadmin} add -r --use-defaults httpkadmind/admin@${R} || exit 1
${kadmin} add -r --use-defaults WELLKNOWN/CSRFTOKEN@${R} || exit 1
${kadmin} add -r --use-defaults HTTP/localhost@${R} || exit 1
${kadmin} add -r --use-defaults HTTP/xyz.${domain}@${R} || exit 1
${kadmin} add_ns --key-rotation-epoch=-1d --key-rotation-period=5m \
--max-ticket-life=1d --max-renewable-life=5d \
--attributes= HTTP/ns.${domain}@${R} || exit 1
${kadmin} add -r --use-defaults HTTP/${server}@${R} || exit 1
${kadmin} ext_keytab -r -k $keytab kadmin/admin@${R} || exit 1
${kadmin} ext_keytab -r -k $keytab httpkadmind/admin@${R} || exit 1
${kadmin} ext_keytab -r -k $keytab HTTP/${server}@${R} || exit 1
${kadmin} ext_keytab -r -k $keytab HTTP/localhost@${R} || exit 1
${kadmin} add -r --use-defaults HTTP/${otherserver}@${R} || exit 1
${kadmin} ext_keytab -r -k $ukeytab foo@${R} || exit 1
${kdestroy}
# For a while let's not bother with a KDC
$kimpersonate --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
-c foo@${R} -s HTTP/datan.test.h5l.se@${R} ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
$kimpersonate -A --ccache=$cache -k $keytab -R -t aes128-cts-hmac-sha1-96 \
-c foo@${R} -s HTTP/localhost@${R} ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
$klist -t >/dev/null ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
echo "Starting httpkadmind"
${httpkadmind} -H $server -H localhost --local -t --daemon ||
{ echo "httpkadmind failed to start"; exit 2; }
httpkadmindpid=`getpid httpkadmind`
ec=0
echo "Checking that concrete principal exists"
${kadmin} get HTTP/xyz.${domain} > /dev/null ||
{ echo "Failed to create HTTP/xyz.${domain}"; exit 1; }
echo "Checking that virtual principal exists"
${kadmin} get HTTP/foo.ns.${domain} > /dev/null ||
{ echo "Virtual principals not working"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching krb5.conf for $p"
get_config "princ=$p" -sf -o "${objdir}/extracted_config" ||
{ echo "Failed to get config for $p"; exit 1; }
read config < "${objdir}/extracted_config"
test "$config" = "include /etc/krb5.conf" ||
{ echo "Got unexpected default config for $p"; exit 1; }
${kadmin} mod --krb5-config-file="$KRB5_CONFIG" $p ||
{ echo "Failed to set config for $p"; exit 1; }
get_config "princ=$p" -sf -o "${objdir}/extracted_config" ||
{ echo "Failed to get config for $p"; exit 1; }
cmp "${objdir}/extracted_config" "$KRB5_CONFIG" ||
{ echo "Got unexpected config for $p"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
hn=foo.ns.${domain}
p=HTTP/$hn
echo "Fetching keytab for virtual principal $p"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
hn1=foo.ns.${domain}
hn2=foobar.ns.${domain}
hn3=xyz.${domain}
p1=HTTP/$hn1
p2=HTTP/$hn2
p3=HTTP/$hn3
echo "Fetching keytabs for more than one principal"
rm -f extracted_keytab*
grant dnsname $hn1 foo@${R}
grant dnsname $hn2 foo@${R}
grant dnsname $hn3 foo@${R}
# Note that httpkadmind will first process dNSName q-params, then the spn
# q-params.
${kadmin} ext_keytab -k extracted_keytab $p1 ||
{ echo "Failed to get a keytab for $p1 with kadmin"; exit 1; }
${kadmin} ext_keytab -k extracted_keytab $p3 ||
{ echo "Failed to get a keytab for $p3 with kadmin"; exit 1; }
${kadmin} ext_keytab -k extracted_keytab $p2 ||
{ echo "Failed to get a keytab for $p2 with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for multiple principals"; exit 1; }
get_keytab "dNSName=${hn1}&spn=${p2}&dNSName=${hn3}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for multiple principals with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
grep $hn1 extracted_keytab.rest > /dev/null ||
{ echo "Keytab does not include keys for $p1"; exit 1; }
grep $hn2 extracted_keytab.rest > /dev/null ||
{ echo "Keytab does not include keys for $p2"; exit 1; }
grep $hn3 extracted_keytab.rest > /dev/null ||
{ echo "Keytab does not include keys for $p3"; exit 1; }
p=host/foo.ns.${domain}
echo "Checking that $p doesn't exist (no namespace for host service)"
get_keytab "svc=host&dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab.rest" &&
{ echo "Got a keytab for host/foo.ns.${domain} when not namespaced!"; }
echo "Checking that authorization is enforced"
revoke
get_keytab "dNSName=xyz.${domain}" -sf -o "${objdir}/extracted_keytab" &&
{ echo "Got a keytab for HTTP/xyz.${domain} when not authorized!"; exit 1; }
get_keytab "dNSName=foo.ns.${domain}" -sf -o "${objdir}/extracted_keytab" &&
{ echo "Got a keytab for HTTP/foo.ns.${domain} when not authorized!"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
{ echo "Failed to list keytab for $p"; exit 1; }
test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
{ echo "Wrong number of new keys!"; exit 1; }
get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to rotate keys for $p"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
{ echo "Keys for $p did not change!"; exit 1; }
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
{ echo "Wrong number of new keys!"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation w/ revocation for concrete principal $p"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
{ echo "Failed to list keytab for $p"; exit 1; }
get_keytab "dNSName=${hn}&revoke=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&revoke=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
{ echo "Keys for $p did not change!"; exit 1; }
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 1 ||
{ echo "Wrong number of new keys!"; exit 1; }
hn=abc.${domain}
p=HTTP/$hn
echo "Checking concrete principal creation ($p)"
rm -f extracted_keytab
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}&create=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&create=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
rm -f extracted_keytab
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
if false; then
hn=bar.ns.${domain}
p=HTTP/$hn
echo "Checking materialization of virtual principal ($p)"
rm -f extracted_keytab
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}&materialize=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&materialize=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to materialize and get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
rm -f extracted_keytab
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
fi
echo "Starting secondary httpkadmind to test HTTP redirection"
${httpkadmind2} --primary-server-uri=http://localhost:$restport \
-H $server --local --local-read-only -t --daemon ||
{ echo "httpkadmind failed to start"; exit 2; }
httpkadmind2pid=`getpid httpkadmind`
ec=0
hn=def.${domain}
p=HTTP/$hn
restport=$restport2
echo "Checking principal creation at secondary yields redirect"
rm -f extracted_keytab
grant dnsname $hn foo@${R}
get_keytab_POST_redir "dNSName=${hn}&create=true" \
-s -o "${objdir}/extracted_keytab"
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
rm -f extracted_keytab
${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
echo "killing httpkadmind (${httpkadmindpid} ${httpkadmind2pid})"
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
sh ${leaks_kill} httpkadmind $httpkadmind2pid || ec=1
httpkadmindpid=
httpkadmind2pid=
test $ec = 1 &&
{ echo "Error killing httpkadmind instances or memory errors found"; exit 1; }
echo "Starting primary kadmind for testing httpkadmind with remote HDB"
${kadmind} ||
{ echo "Read-write kadmind failed to start"; exit 2; }
kadmindpid=`getpid kadmind`
echo "Starting secondray (read-only) kadmind for testing httpkadmind with remote HDB"
${kadmind2} ||
{ echo "Read-only kadmind failed to start"; exit 2; }
kadmind2pid=`getpid kadmind`
# Make a ccache for use with kadmin(1)
$kimpersonate --ticket-flags=initial --ccache=$admincache -k $keytab -t aes128-cts-hmac-sha1-96 \
-c httpkadmind/admin@${R} -s kadmin/admin@${R} ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
$adminklist -t >/dev/null ||
{ echo "failed to setup kimpersonate credentials"; exit 2; }
echo "Starting kdc needed for httpkadmind authentication to kadmind"
${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
kdcpid=`getpid kdc`
echo "Starting httpkadmind with remote HDBs only"
restport=$restport1
${httpkadmind} -H $server -H localhost -t --daemon \
--writable-admin-server=$(uname -n):$admport \
--read-only-admin-server=$(uname -n):$admport2 \
--kadmin-client-name=httpkadmind/admin@${R} \
--kadmin-client-keytab=$keytab ||
{ echo "httpkadmind failed to start"; exit 2; }
httpkadmindpid=`getpid httpkadmind`
ec=0
hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p using remote HDB"
rm -f extracted_keytab*
grant dnsname $hn httpkadmind/admin@${R}
KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
get_keytab "spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p using remote HDB"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
{ echo "Failed to list keytab for $p"; exit 1; }
test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 1 ||
{ echo "Wrong number of new keys!"; exit 1; }
get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to rotate keys for $p"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
{ echo "Keys for $p did not change!"; exit 1; }
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 2 ||
{ echo "Wrong number of new keys!"; exit 1; }
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
httpkadmindpid=
echo "Starting httpkadmind with local read-only HDB and remote read-write HDB"
${httpkadmind} -H $server -H localhost -t --daemon \
--local-read-only \
--writable-admin-server=$(uname -n):$admport \
--kadmin-client-name=httpkadmind/admin@${R} \
--kadmin-client-keytab=$keytab ||
{ echo "httpkadmind failed to start"; exit 2; }
httpkadmindpid=`getpid httpkadmind`
ec=0
hn=xyz.${domain}
p=HTTP/$hn
echo "Fetching keytab for concrete principal $p using local read-only HDB"
rm -f extracted_keytab*
grant dnsname $hn httpkadmind/admin@${R}
KRB5CCNAME=$admincache ${kadmin} ext_keytab -k extracted_keytab $p ||
{ echo "Failed to get a keytab for $p with kadmin"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.kadmin ||
{ echo "Failed to list keytab for $p"; exit 1; }
get_keytab "spn=${p}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.kadmin extracted_keytab.rest ||
{ echo "Keytabs for $p don't match!"; exit 1; }
hn=xyz.${domain}
p=HTTP/$hn
echo "Checking key rotation for concrete principal $p using local read-only HDB and remote HDB"
rm -f extracted_keytab*
grant dnsname $hn foo@${R}
get_keytab "dNSName=${hn}" -sf -o "${objdir}/extracted_keytab" ||
{ echo "Failed to get a keytab for $p with curl"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest1 ||
{ echo "Failed to list keytab for $p"; exit 1; }
test "$(grep $p extracted_keytab.rest1 | wc -l)" -eq 2 ||
{ echo "Wrong number of new keys!"; exit 1; }
get_keytab "dNSName=${hn}&rotate=true" -sf -o "${objdir}/extracted_keytab" &&
{ echo "GET succeeded for write operation!"; exit 1; }
get_keytab_POST "dNSName=${hn}&rotate=true" -s -o "${objdir}/extracted_keytab" ||
{ echo "Failed to rotate keys for $p"; exit 1; }
${ktutil} -k "${objdir}/extracted_keytab" list --keys > extracted_keytab.rest2 ||
{ echo "Failed to list keytab for $p"; exit 1; }
cmp extracted_keytab.rest1 extracted_keytab.rest2 > /dev/null &&
{ echo "Keys for $p did not change!"; exit 1; }
test "$(grep $p extracted_keytab.rest2 | wc -l)" -eq 3 ||
{ echo "Wrong number of new keys!"; exit 1; }
sh ${leaks_kill} httpkadmind $httpkadmindpid || ec=1
sh ${leaks_kill} kadmind $kadmindpid || ec=1
sh ${leaks_kill} kadmind $kadmind2pid || ec=1
sh ${leaks_kill} kdc $kdcpid || ec=1
trap "" EXIT
# TODO
#
# - implement and test that we can materialize a principal yet leave it with
# virtual keys
# - test new key delay? this one is tricky
exit $ec

View File

@@ -1,4 +1,5 @@
foo/admin@TEST.H5L.SE all
httpkadmind/admin@TEST.H5L.SE all,get-keys
bar@TEST.H5L.SE all
baz@TEST.H5L.SE get,add *
bez@TEST.H5L.SE get,add *@TEST.H5L.SE

View File

@@ -0,0 +1,100 @@
[libdefaults]
default_realm = TEST.H5L.SE
no-addresses = TRUE
allow_weak_crypto = TRUE
rdns = false
fcache_strict_checking = false
name_canon_rules = as-is:realm=TEST.H5L.SE
[appdefaults]
pkinit_anchors = FILE:@objdir@/pkinit-anchor.pem
pkinit_pool = FILE:@objdir@/pkinit-anchor.pem
[realms]
TEST.H5L.SE = {
kdc = localhost:@port@
pkinit_win2k = @w2k@
}
[kdc]
num-kdc-processes = 1
strict-nametypes = true
enable-pkinit = true
pkinit_identity = PEM-FILE:@objdir@/user-issuer.pem
pkinit_anchors = PEM-FILE:@objdir@/pkinit-anchor.pem
pkinit_mappings_file = @srcdir@/pki-mapping
# Locate kdc plugins for testing
plugin_dir = @objdir@/../../kdc/.libs
# Configure kdc plugins for testing
simple_csr_authorizer_directory = @objdir@/simple_csr_authz
enable-pkinit = true
pkinit_identity = PEM-FILE:@objdir@/user-issuer.pem
pkinit_anchors = PEM-FILE:@objdir@/pkinit-anchor.pem
pkinit_mappings_file = @srcdir@/pki-mapping
database = {
dbname = @objdir@/current-db
realm = TEST.H5L.SE
mkey_file = @objdir@/mkey.file
log_file = @objdir@/log.current-db.log
acl_file = @srcdir@/heimdal.acl
}
negotiate_token_validator = {
keytab = FILE:@objdir@/kt
}
realms = {
TEST.H5L.SE = {
kx509 = {
user = {
include_pkinit_san = true
subject_name = CN=${principal-name-without-realm},DC=test,DC=h5l,DC=se
ekus = 1.3.6.1.5.5.7.3.2
ca = PEM-FILE:@objdir@/user-issuer.pem
}
hostbased_service = {
HTTP = {
include_dnsname_san = true
ekus = 1.3.6.1.5.5.7.3.1
ca = PEM-FILE:@objdir@/server-issuer.pem
}
}
client = {
ekus = 1.3.6.1.5.5.7.3.2
ca = PEM-FILE:@objdir@/user-issuer.pem
}
server = {
ekus = 1.3.6.1.5.5.7.3.1
ca = PEM-FILE:@objdir@/server-issuer.pem
}
mixed = {
ekus = 1.3.6.1.5.5.7.3.1
ekus = 1.3.6.1.5.5.7.3.2
ca = PEM-FILE:@objdir@/mixed-issuer.pem
}
}
}
}
[hdb]
db-dir = @objdir@
enable_virtual_hostbased_princs = true
virtual_hostbased_princ_mindots = 1
virtual_hostbased_princ_maxdots = 3
virtual_hostbased_princ_svcs = HTTP host
[ext_keytab]
simple_csr_authorizer_directory = @objdir@/simple_csr_authz
[logging]
kdc = 0-/FILE:@objdir@/messages.log
bx509d = 0-/FILE:@objdir@/messages.log
httpkadmind = 0-/FILE:@objdir@/messages.log
default = 0-/FILE:@objdir@/messages.log
[domain_realm]
. = TEST.H5L.SE