aboutsummaryrefslogtreecommitdiff
path: root/files
diff options
context:
space:
mode:
authorCullum Smith <cullum@sacredheartsc.com>2024-09-24 22:35:45 -0400
committerCullum Smith <cullum@sacredheartsc.com>2024-09-24 22:35:45 -0400
commit6e00c9e8137aae1fb8dd568a62d9fb5fc4a277cb (patch)
tree9279f7a330affbb5da6a1f147739b8dfd92d4a19 /files
parentd9c18b3fcb9b036b6cdf69397828b59ab4c53091 (diff)
downloadinfrastructure-6e00c9e8137aae1fb8dd568a62d9fb5fc4a277cb.tar.gz
finish up idm_server hostclass
Diffstat (limited to 'files')
-rw-r--r--files/etc/krb5.conf.idm_server27
-rw-r--r--files/etc/nscd.conf.freebsd27
-rw-r--r--files/etc/nsswitch.conf.freebsd10
-rw-r--r--files/etc/pam.d/sshd.freebsd17
-rw-r--r--files/etc/resolv.conf.common1
-rw-r--r--files/etc/resolv.conf.idm_server2
-rw-r--r--files/usr/local/etc/nslcd.conf.idm_server14
-rw-r--r--files/usr/local/etc/openldap/ldap.conf.idm_server2
-rw-r--r--files/usr/local/etc/openldap/slapd.ldif.idm_server4
-rw-r--r--files/usr/local/etc/pdns/pdns.conf.idm_server2
-rw-r--r--files/usr/local/etc/poudriere.d/idm-make.conf.pkg_repository4
-rw-r--r--files/usr/local/etc/poudriere.d/idm-pkglist.pkg_repository1
-rw-r--r--files/usr/local/etc/poudriere.d/make.conf.pkg_repository4
-rw-r--r--files/usr/local/etc/poudriere.d/pkglist.pkg_repository1
-rw-r--r--files/usr/local/etc/ssh/ssh_config.freebsd (renamed from files/etc/ssh/ssh_config.freebsd)0
l---------files/usr/local/etc/ssh/ssh_config.freebsd_hypervisor (renamed from files/etc/ssh/ssh_config.freebsd_hypervisor)0
-rw-r--r--files/usr/local/etc/ssh/ssh_config.no_idm (renamed from files/etc/ssh/ssh_config.no_idm)0
l---------files/usr/local/etc/ssh/ssh_config.roadwarrior_laptop (renamed from files/etc/ssh/ssh_config.roadwarrior_laptop)0
-rw-r--r--files/usr/local/etc/ssh/sshd_config.freebsd (renamed from files/etc/ssh/sshd_config.freebsd)2
l---------files/usr/local/etc/ssh/sshd_config.freebsd_hypervisor (renamed from files/etc/ssh/sshd_config.freebsd_hypervisor)0
-rw-r--r--files/usr/local/etc/ssh/sshd_config.no_idm (renamed from files/etc/ssh/sshd_config.no_idm)2
-rw-r--r--files/usr/local/etc/unbound/unbound.conf.idm_server68
-rw-r--r--files/usr/local/libexec/idm-ssh-authorized-keys.common43
-rw-r--r--files/usr/local/libexec/idm-ssh-known-hosts.common51
-rw-r--r--files/usr/local/libexec/idm-update-unbound-blocklists.idm_server32
-rw-r--r--files/usr/local/var/krb5kdc/kadm5.acl.idm_server2
-rw-r--r--files/usr/local/var/krb5kdc/kdc.conf.idm_server23
27 files changed, 328 insertions, 11 deletions
diff --git a/files/etc/krb5.conf.idm_server b/files/etc/krb5.conf.idm_server
new file mode 100644
index 0000000..422d0e4
--- /dev/null
+++ b/files/etc/krb5.conf.idm_server
@@ -0,0 +1,27 @@
+[libdefaults]
+ default_realm = ${realm}
+ dns_lookup_kdc = false
+ dns_lookup_realm = false
+ allow_weak_crypto = false
+ permitted_enctypes = aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96
+ verify_ap_req_nofail = true
+
+[appdefaults]
+ pam = {
+ minimum_uid = 1000
+ ccache = FILE:/tmp/krb5cc_%u_XXXXXX
+ forwardable = true
+ ticket_lifetime = ${krb5_ticket_lifetime}
+ renew_lifetime = ${krb5_renew_lifetime}
+ }
+
+[realms]
+ ${realm} = {
+ kdc = ${fqdn}
+ admin_server = ${fqdn}
+ default_domain = ${domain}
+ }
+
+[domain_realm]
+ .${domain} = ${realm}
+ ${domain} = ${realm}
diff --git a/files/etc/nscd.conf.freebsd b/files/etc/nscd.conf.freebsd
new file mode 100644
index 0000000..9105cb5
--- /dev/null
+++ b/files/etc/nscd.conf.freebsd
@@ -0,0 +1,27 @@
+enable-cache passwd yes
+positive-time-to-live passwd ${nscd_ttl}
+negative-time-to-live passwd ${nscd_negative_ttl}
+
+enable-cache group yes
+positive-time-to-live group ${nscd_ttl}
+negative-time-to-live group ${nscd_negative_ttl}
+
+enable-cache hosts yes
+positive-time-to-live hosts ${nscd_ttl}
+negative-time-to-live hosts ${nscd_negative_ttl}
+
+enable-cache services yes
+positive-time-to-live services ${nscd_ttl}
+negative-time-to-live services ${nscd_negative_ttl}
+
+enable-cache protocols yes
+positive-time-to-live protocols ${nscd_ttl}
+negative-time-to-live protocols ${nscd_negative_ttl}
+
+enable-cache rpc yes
+positive-time-to-live rpc ${nscd_ttl}
+negative-time-to-live rpc ${nscd_negative_ttl}
+
+enable-cache networks yes
+positive-time-to-live networks ${nscd_ttl}
+negative-time-to-live networks ${nscd_negative_ttl}
diff --git a/files/etc/nsswitch.conf.freebsd b/files/etc/nsswitch.conf.freebsd
new file mode 100644
index 0000000..19c9f22
--- /dev/null
+++ b/files/etc/nsswitch.conf.freebsd
@@ -0,0 +1,10 @@
+group: files cache ldap
+hosts: files cache dns
+netgroup: files
+networks: files
+passwd: files cache ldap
+shells: files
+services: files
+protocols: files
+rpc: files
+sudoers: files ldap
diff --git a/files/etc/pam.d/sshd.freebsd b/files/etc/pam.d/sshd.freebsd
new file mode 100644
index 0000000..57b281b
--- /dev/null
+++ b/files/etc/pam.d/sshd.freebsd
@@ -0,0 +1,17 @@
+# auth
+auth sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
+auth required pam_unix.so no_warn try_first_pass
+
+# account
+account required pam_nologin.so
+account required /usr/local/lib/security/pam_krb5.so
+account required pam_login_access.so
+account required pam_unix.so
+
+# session
+session required /usr/local/lib/security/pam_krb5.so
+session required pam_permit.so
+
+# password
+password sufficient /usr/local/lib/security/pam_krb5.so try_first_pass
+password required pam_unix.so no_warn try_first_pass
diff --git a/files/etc/resolv.conf.common b/files/etc/resolv.conf.common
index 24c2044..475ea9d 100644
--- a/files/etc/resolv.conf.common
+++ b/files/etc/resolv.conf.common
@@ -1,3 +1,2 @@
$(printf 'nameserver %s\n' $resolvers)
domain ${domain}
-options timeout:1
diff --git a/files/etc/resolv.conf.idm_server b/files/etc/resolv.conf.idm_server
new file mode 100644
index 0000000..9a87112
--- /dev/null
+++ b/files/etc/resolv.conf.idm_server
@@ -0,0 +1,2 @@
+nameserver 127.0.0.1
+domain ${domain}
diff --git a/files/usr/local/etc/nslcd.conf.idm_server b/files/usr/local/etc/nslcd.conf.idm_server
new file mode 100644
index 0000000..1f74779
--- /dev/null
+++ b/files/usr/local/etc/nslcd.conf.idm_server
@@ -0,0 +1,14 @@
+uid ${nslcd_user}
+gid ${nslcd_user}
+
+uri ${slapd_ldapi_uri}
+
+base ${basedn}
+base passwd ${accounts_basedn}
+base group ${groups_basedn}
+
+sasl_mech EXTERNAL
+
+nss_min_uid ${nslcd_min_uid}
+nss_initgroups_ignoreusers ALLLOCAL
+nss_nested_groups yes
diff --git a/files/usr/local/etc/openldap/ldap.conf.idm_server b/files/usr/local/etc/openldap/ldap.conf.idm_server
index 3b285f7..a3e18f2 100644
--- a/files/usr/local/etc/openldap/ldap.conf.idm_server
+++ b/files/usr/local/etc/openldap/ldap.conf.idm_server
@@ -1,4 +1,4 @@
-URI ldapi:///
+URI ${slapd_ldapi_uri}
BASE ${basedn}
USE_SASL yes
ROOTUSE_SASL yes
diff --git a/files/usr/local/etc/openldap/slapd.ldif.idm_server b/files/usr/local/etc/openldap/slapd.ldif.idm_server
index 784c63a..9dc0086 100644
--- a/files/usr/local/etc/openldap/slapd.ldif.idm_server
+++ b/files/usr/local/etc/openldap/slapd.ldif.idm_server
@@ -119,8 +119,8 @@ olcAccess: {1}to dn.base="cn=Subschema"
by * read
olcAccess: {3}to *
by dn.exact=${slapd_replicator_dn} read
- by dn.exact=uid=${idm_admin_username},${robots_basedn} manage
- by group/groupOfMembers/member=cn=${idm_admin_groupname},${groups_basedn} manage
+ by dn.exact=krbPrincipalName=${boxconf_username},${robots_basedn} manage
+ by set="[cn=${slapd_admin_role},${roles_basedn}]/member* & user" manage
by * break
olcAccess: {4}to dn.subtree=${sudo_basedn}
by dn.children=${hosts_basedn} read
diff --git a/files/usr/local/etc/pdns/pdns.conf.idm_server b/files/usr/local/etc/pdns/pdns.conf.idm_server
index fc63bd6..2d49dc3 100644
--- a/files/usr/local/etc/pdns/pdns.conf.idm_server
+++ b/files/usr/local/etc/pdns/pdns.conf.idm_server
@@ -4,7 +4,7 @@
#
# You must set ldap-bindmethod=gssapi (?!) for this to work. This behavior doesn't
# seem to be documented anywhere, but hey, it's nice!
-ldap-host=ldapi:///
+ldap-host=${slapd_ldapi_uri}
ldap-bindmethod=gssapi
ldap-basedn=${dns_basedn}
diff --git a/files/usr/local/etc/poudriere.d/idm-make.conf.pkg_repository b/files/usr/local/etc/poudriere.d/idm-make.conf.pkg_repository
index 1d5ce20..ad5304f 100644
--- a/files/usr/local/etc/poudriere.d/idm-make.conf.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/idm-make.conf.pkg_repository
@@ -4,8 +4,8 @@ DEFAULT_VERSIONS+=${poudriere_default_versions:-}
MAKE_JOBS_NUMBER=${poudriere_make_jobs_number}
# Global port options
-OPTIONS_UNSET=TEST DEBUG GSSAPI_HEIMDAL GSSAPI_BASE GSSAPI_NONE HEIMDAL NLS DOCS AVAHI LIBWRAP MYSQL MSQLND ODBC READLINE PULSEAUDIO UPNP BASH ZSH INFO ALSA SAMBA WAYLAND PLATFORM_WAYLAND PIPEWIRE
-OPTIONS_SET=GSSAPI GSSAPI_MIT NONFREE LIBEDIT
+OPTIONS_UNSET=TEST DEBUG GSSAPI_HEIMDAL GSSAPI_BASE GSSAPI_NONE HEIMDAL HEIMDAL_BASE NLS DOCS AVAHI LIBWRAP MYSQL MSQLND ODBC READLINE PULSEAUDIO UPNP BASH ZSH INFO ALSA SAMBA WAYLAND PLATFORM_WAYLAND PIPEWIRE TCP_WRAPPERS
+OPTIONS_SET=GSSAPI GSSAPI_MIT MIT NONFREE LIBEDIT
# Per-port options
dns_powerdns_SET=OPENLDAP
diff --git a/files/usr/local/etc/poudriere.d/idm-pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/idm-pkglist.pkg_repository
index 86c102e..9504faa 100644
--- a/files/usr/local/etc/poudriere.d/idm-pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/idm-pkglist.pkg_repository
@@ -12,6 +12,7 @@ net/py-python-ldap
net/rsync
security/cyrus-sasl2-saslauthd
security/krb5
+security/openssh-portable
security/pam_krb5@mit
security/pam_mkhomedir
security/sudo
diff --git a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
index 8348621..b0ae948 100644
--- a/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/make.conf.pkg_repository
@@ -4,8 +4,8 @@ DEFAULT_VERSIONS+=${poudriere_default_versions:-}
MAKE_JOBS_NUMBER=${poudriere_make_jobs_number}
# Global port options
-OPTIONS_UNSET=TEST DEBUG GSSAPI_HEIMDAL GSSAPI_BASE GSSAPI_NONE HEIMDAL NLS DOCS AVAHI LIBWRAP MYSQL MSQLND ODBC READLINE PULSEAUDIO UPNP BASH ZSH INFO ALSA SAMBA WAYLAND PLATFORM_WAYLAND PIPEWIRE
-OPTIONS_SET=GSSAPI GSSAPI_MIT NONFREE LIBEDIT
+OPTIONS_UNSET=TEST DEBUG GSSAPI_HEIMDAL GSSAPI_BASE GSSAPI_NONE HEIMDAL HEIMDAL_BASE NLS DOCS AVAHI LIBWRAP MYSQL MSQLND ODBC READLINE PULSEAUDIO UPNP BASH ZSH INFO ALSA SAMBA WAYLAND PLATFORM_WAYLAND PIPEWIRE TCP_WRAPPERS
+OPTIONS_SET=GSSAPI GSSAPI_MIT MIT NONFREE LIBEDIT
# Per-port options
databases_akonadi_SET=MYSQL
diff --git a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
index 80fc5e5..157ae8e 100644
--- a/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
+++ b/files/usr/local/etc/poudriere.d/pkglist.pkg_repository
@@ -19,6 +19,7 @@ security/cyrus-sasl2-saslauthd
security/kstart
security/krb5@default
security/krb5@ldap
+security/openssh-portable
security/pam_krb5@mit
security/pam_mkhomedir
security/sshpass
diff --git a/files/etc/ssh/ssh_config.freebsd b/files/usr/local/etc/ssh/ssh_config.freebsd
index 9be624a..9be624a 100644
--- a/files/etc/ssh/ssh_config.freebsd
+++ b/files/usr/local/etc/ssh/ssh_config.freebsd
diff --git a/files/etc/ssh/ssh_config.freebsd_hypervisor b/files/usr/local/etc/ssh/ssh_config.freebsd_hypervisor
index 338cdba..338cdba 120000
--- a/files/etc/ssh/ssh_config.freebsd_hypervisor
+++ b/files/usr/local/etc/ssh/ssh_config.freebsd_hypervisor
diff --git a/files/etc/ssh/ssh_config.no_idm b/files/usr/local/etc/ssh/ssh_config.no_idm
index 97f3ba8..97f3ba8 100644
--- a/files/etc/ssh/ssh_config.no_idm
+++ b/files/usr/local/etc/ssh/ssh_config.no_idm
diff --git a/files/etc/ssh/ssh_config.roadwarrior_laptop b/files/usr/local/etc/ssh/ssh_config.roadwarrior_laptop
index 338cdba..338cdba 120000
--- a/files/etc/ssh/ssh_config.roadwarrior_laptop
+++ b/files/usr/local/etc/ssh/ssh_config.roadwarrior_laptop
diff --git a/files/etc/ssh/sshd_config.freebsd b/files/usr/local/etc/ssh/sshd_config.freebsd
index c933741..df46af6 100644
--- a/files/etc/ssh/sshd_config.freebsd
+++ b/files/usr/local/etc/ssh/sshd_config.freebsd
@@ -13,4 +13,4 @@ GSSAPICleanupCredentials yes
UsePAM yes
UseDNS no
-Subsystem sftp /usr/libexec/sftp-server
+Subsystem sftp /usr/local/libexec/sftp-server
diff --git a/files/etc/ssh/sshd_config.freebsd_hypervisor b/files/usr/local/etc/ssh/sshd_config.freebsd_hypervisor
index 355377d..355377d 120000
--- a/files/etc/ssh/sshd_config.freebsd_hypervisor
+++ b/files/usr/local/etc/ssh/sshd_config.freebsd_hypervisor
diff --git a/files/etc/ssh/sshd_config.no_idm b/files/usr/local/etc/ssh/sshd_config.no_idm
index f38720c..8a15559 100644
--- a/files/etc/ssh/sshd_config.no_idm
+++ b/files/usr/local/etc/ssh/sshd_config.no_idm
@@ -7,4 +7,4 @@ PasswordAuthentication yes
UsePAM yes
UseDNS no
-Subsystem sftp /usr/libexec/sftp-server
+Subsystem sftp /usr/local/libexec/sftp-server
diff --git a/files/usr/local/etc/unbound/unbound.conf.idm_server b/files/usr/local/etc/unbound/unbound.conf.idm_server
new file mode 100644
index 0000000..762fe09
--- /dev/null
+++ b/files/usr/local/etc/unbound/unbound.conf.idm_server
@@ -0,0 +1,68 @@
+server:
+ module-config: "respip validator iterator"
+ verbosity: 1
+ num-threads: ${unbound_threads}
+ interface: 0.0.0.0
+ interface: ::0
+ do-ip6: no
+ prefer-ip6: no
+ prefetch: yes
+ prefetch-key: yes
+ so-rcvbuf: 425984
+ do-not-query-localhost: no
+ access-control: 0.0.0.0/0 allow
+ access-control: ::0/0 allow
+
+ cache-max-negative-ttl: ${unbound_cache_max_negative_ttl}
+ rrset-cache-size: ${unbound_rrset_cache_size}
+ msg-cache-size: ${unbound_msg_cache_size}
+ msg-cache-slabs: ${unbound_slabs}
+ rrset-cache-slabs: ${unbound_slabs}
+ infra-cache-slabs: ${unbound_slabs}
+ key-cache-slabs: ${unbound_slabs}
+
+ private-address: 192.168.0.0/16
+ private-address: 169.254.0.0/16
+ private-address: 172.16.0.0/12
+ private-address: 10.0.0.0/8
+
+ domain-insecure: "${domain}"
+$([ -z "$unbound_insecure_domains" ] || printf ' domain-insecure: "%s"\n' $unbound_insecure_domains)
+
+ local-zone: "10.in-addr.arpa" nodefault
+ local-zone: "16.172.in-addr.arpa" nodefault
+ local-zone: "17.172.in-addr.arpa" nodefault
+ local-zone: "18.172.in-addr.arpa" nodefault
+ local-zone: "19.172.in-addr.arpa" nodefault
+ local-zone: "20.172.in-addr.arpa" nodefault
+ local-zone: "21.172.in-addr.arpa" nodefault
+ local-zone: "22.172.in-addr.arpa" nodefault
+ local-zone: "23.172.in-addr.arpa" nodefault
+ local-zone: "24.172.in-addr.arpa" nodefault
+ local-zone: "25.172.in-addr.arpa" nodefault
+ local-zone: "26.172.in-addr.arpa" nodefault
+ local-zone: "27.172.in-addr.arpa" nodefault
+ local-zone: "28.172.in-addr.arpa" nodefault
+ local-zone: "29.172.in-addr.arpa" nodefault
+ local-zone: "30.172.in-addr.arpa" nodefault
+ local-zone: "31.172.in-addr.arpa" nodefault
+ local-zone: "168.192.in-addr.arpa" nodefault
+
+$([ -z "$unbound_local_zones" ] || printf ' local-zone: "%s" typetransparent\n' $unbound_local_zones)
+
+ private-domain: "${domain}"
+$([ -z "$unbound_local_zones" ] || printf ' private-domain: "%s"\n' $unbound_local_zones)
+
+$([ -z "$unbound_local_data" ] || printf ' local-data: "%s"\n' $unbound_local_data)
+
+$(echo "$unbound_blocklists" | while read -r name _url; do
+ [ -n "$name" ] && printf "rpz:\n name: %s\n zonefile: ${unbound_blocklist_dir}/%s.zone\n" "$name" "$name"; done)
+
+stub-zone:
+ name: "${domain}"
+ stub-addr: 127.0.0.1@${pdns_port}
+$(printf "\
+stub-zone:
+ name: \"%s\"
+ stub-addr: 127.0.0.1@${pdns_port}
+" $reverse_dns_zones)
diff --git a/files/usr/local/libexec/idm-ssh-authorized-keys.common b/files/usr/local/libexec/idm-ssh-authorized-keys.common
new file mode 100644
index 0000000..d18b199
--- /dev/null
+++ b/files/usr/local/libexec/idm-ssh-authorized-keys.common
@@ -0,0 +1,43 @@
+#!/usr/local/bin/perl
+
+use strict;
+use warnings;
+
+use Net::LDAP;
+use Net::LDAP::Util qw(escape_filter_value);
+use Authen::SASL;
+
+open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or quit($!);
+my %config;
+while (<$fh>) {
+ chomp;
+ next if /^#/;
+ my @pair = split(' ', $_, 2);
+ next unless (@pair == 2);
+ $config{$pair[0]} = $pair[1];
+}
+close($fh);
+
+my $mech = $config{SASL_MECH} // 'GSSAPI';
+my $uri = $config{URI} // quit('URI not specified');
+my $basedn = $config{BASE} // quit('BASE not specified');
+
+@ARGV == 1 or die "usage: $0 USERNAME\n";
+my $username = $ARGV[0];
+
+my $conn = Net::LDAP->new($uri, version => '3') or die "$0: $@";
+my $sasl = Authen::SASL->new($mech);
+my $status = $conn->bind(sasl => $sasl);
+$status->code and die "$0: ".$status->error;
+
+my $search = $conn->search(
+ scope => 'sub',
+ base => "ou=accounts,$basedn",
+ filter => '(&(objectClass=posixAccount)(sshPublicKey=*)(uid=' . escape_filter_value($username) . '))',
+ attrs => ['sshPublicKey']);
+$search->code and die "$0: ".$search->error;
+
+exit 0 if $search->entries == 0;
+die "$0: multiple LDAP entries returned for user: $username\n" if $search->entries > 1;
+
+print "$_\n" foreach (($search->entries)[0]->get_value('sshPublicKey'));
diff --git a/files/usr/local/libexec/idm-ssh-known-hosts.common b/files/usr/local/libexec/idm-ssh-known-hosts.common
new file mode 100644
index 0000000..78b48fc
--- /dev/null
+++ b/files/usr/local/libexec/idm-ssh-known-hosts.common
@@ -0,0 +1,51 @@
+#!/usr/local/bin/perl
+
+use strict;
+use warnings;
+
+use Net::LDAP;
+use Net::LDAP::Util qw(escape_filter_value);
+use Authen::SASL;
+
+sub quit {
+ # Prints an error message and exits with code 0.
+ # NB: If KnownHostsCommand returns nonzero, the entire SSH connection aborts,
+ # which isn't what we want.
+ print STDERR "$0: $_[0]" if @_ > 0;
+ exit 0
+}
+
+@ARGV == 1 or die "usage: $0 HOSTNAME\n";
+my $hostname = $ARGV[0];
+
+open my $fh, '<', '/usr/local/etc/openldap/ldap.conf' or quit($!);
+my %config;
+while (<$fh>) {
+ chomp;
+ next if /^#/;
+ my @pair = split(' ', $_, 2);
+ next unless (@pair == 2);
+ $config{$pair[0]} = $pair[1];
+}
+close($fh);
+
+my $mech = $config{SASL_MECH} // 'GSSAPI';
+my $uri = $config{URI} // quit('URI not specified');
+my $basedn = $config{BASE} // quit('BASE not specified');
+
+my $conn = Net::LDAP->new($uri, version => '3') or quit($@);
+my $sasl = Authen::SASL->new($mech);
+my $status = $conn->bind(sasl => $sasl);
+$status->code and quit($status->error);
+
+my $search = $conn->search(
+ scope => 'sub',
+ base => "ou=hosts,ou=accounts,$basedn",
+ filter => '(&(sshPublicKey=*)(associatedDomain=' . escape_filter_value($hostname) . '))',
+ attrs => ['sshPublicKey']);
+$search->code and quit($search->error);
+
+quit if $search->entries == 0;
+quit("multiple LDAP entries returned for host: $hostname\n") if $search->entries > 1;
+
+print "$hostname $_\n" foreach (($search->entries)[0]->get_value('sshPublicKey'));
diff --git a/files/usr/local/libexec/idm-update-unbound-blocklists.idm_server b/files/usr/local/libexec/idm-update-unbound-blocklists.idm_server
new file mode 100644
index 0000000..c33b909
--- /dev/null
+++ b/files/usr/local/libexec/idm-update-unbound-blocklists.idm_server
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -eu -o pipefail
+
+prog=$(basename "$(readlink -f "$0")")
+usage="${prog} BLOCKLIST_DIR
+ Blocklist URLs are read from stdin."
+
+die() {
+ printf '%s: %s\n' "$prog" "$*" 1>&2
+ exit 1
+}
+
+usage(){
+ printf 'usage: %s\n' "$usage" 1>&2
+ exit 2
+}
+
+[ $# -eq 1 ] || usage
+case $1 in
+ -h|--help) usage ;;
+esac
+
+[ -d "$1" ] || die "not a directory: ${1}"
+
+cd "$1"
+
+find . -maxdepth 1 -type f -exec rm {} +
+
+while read -r name url; do
+ [ -n "$url" ] && curl -sSfL -o "${name}.zone" "$url"
+done
diff --git a/files/usr/local/var/krb5kdc/kadm5.acl.idm_server b/files/usr/local/var/krb5kdc/kadm5.acl.idm_server
new file mode 100644
index 0000000..c2a454b
--- /dev/null
+++ b/files/usr/local/var/krb5kdc/kadm5.acl.idm_server
@@ -0,0 +1,2 @@
+*/admin@${realm} * * -maxlife 1h -postdateable
+${boxconf_username}@${realm} * * -maxlife 5m -postdateable
diff --git a/files/usr/local/var/krb5kdc/kdc.conf.idm_server b/files/usr/local/var/krb5kdc/kdc.conf.idm_server
new file mode 100644
index 0000000..ab16965
--- /dev/null
+++ b/files/usr/local/var/krb5kdc/kdc.conf.idm_server
@@ -0,0 +1,23 @@
+[realms]
+ ${realm} = {
+ database_module = openldap_ldapconf
+ key_stash_file = ${kdc_master_key_path}
+ max_life = ${kdc_max_life}
+ max_renewable_life = ${kdc_max_renewable_life}
+ default_principal_flags = +preauth
+ }
+
+[dbdefaults]
+ ldap_kerberos_container_dn = ${kdc_basedn}
+ ldap_kdc_sasl_mech = EXTERNAL
+ ldap_kadmind_sasl_mech = EXTERNAL
+ ldap_conns_per_server = 5
+
+[dbmodules]
+ openldap_ldapconf = {
+ ldap_servers = ${slapd_ldapi_uri}
+ db_library = kldap
+ }
+
+[logging]
+ default = SYSLOG