#!/bin/bash
# net/k5 - Kerberos 5 helper

set -e

source "/home/zwelch/src/mcf/mcsh-release/install/share/mcsh/mcsh.sh"

lib_load 'sys/server'


######
# Native dependencies

k5_client_packages=(
		krb5-user
		sasl2-bin
		libsasl2-2
		libsasl2-modules
		libsasl2-modules-gssapi-mit
	)


######
# Configuration

k5_config_init() {
	script_setting_vars kdc_host kdc_server admin_host admin_server

	script_setting_vars -ro KADMIN KTUTIL KRB5_CONF KRB5_KEYTAB KEYTAB_DIR

	KADMIN="kadmin.local"
	KTUTIL="ktutil"

	KRB5_CONF="/etc/krb5.conf"
	KRB5_KEYTAB="/etc/krb5.keytab"
	KEYTAB_DIR="/etc/krb5.keytab.d"
}

k5_config_check() {
	kdc_server=$(server_name "$kdc_host")
	admin_server=$(server_name "$admin_host")
}


######
# Kerberos 5 utility wrappers

run_ktutil() { run $KTUTIL -p "$USER"; }
run_kadmin() { run_sudo $KADMIN -p "$USER" -q "$*"; }


######
# service management

k5_srv() { cmd_dispatch "$@"; }

k5_srv_usage() {
	cat <<EOF
<cmd> ...
Kerberos 5 Service Commands:
	add <name>			Adds a new service principle
EOF
}

k5_srv_add() {
	has_args 1 "$@"
	run_kadmin addprinc -randkey "$1";
}


######
# principle management

k5_pr() { cmd_dispatch "$@"; }

k5_pr_usage() {
	cat <<EOF
<cmd> [...]
Kerberos 5 Principle Commands:
	list				Lists all principles
	add <name>			Creates a new principle
	delete <name>			Deletes a principle
EOF
}

k5_pr_add() {
	has_args 1 "$@"
	run_kadmin addprinc "$1"
}

k5_pr_delete() {
	has_args 1 "$@"
	run_kadmin delprinc "$1"
}

k5_pr_list() {
	has_args 0 "$@"
	run_kadmin listprincs
}


######
# Key Table Management

k5_kt() { cmd_dispatch "$@"; }

k5_kt_usage() {
	cat <<EOF
<cmd> [...]
Kerberos 5 Key Table Commands:
	list [<keytab>+]
	add <keytab> <name>+		Adds named principles to key list
	delete <keytab> <name>+		Removes named principles from key list
	keys				Prints all key lists
	gen <keytab> < <keylist>	Builds a keytab from a key list

	hosts [...]			Host key table commands
EOF
}

krb5_host_keyfile() { echo $KEYTAB_DIR/$1.keys; }
krb5_host_ktfile() { echo $KEYTAB_DIR/$1.keytab; }

k5_kt_new() {
	has_args 2 "$@"
	run_kadmin ktadd -k $1 $2
}

k5_kt_add() { file_test -f "$1"; k5_kt_new "$@"; }

k5_kt_delete() {
	has_args 2 "$@"
	file_test -f "$1"
	run_kadmin ktremove -k $1 $2
}

k5_kt_list() {
	local -a files=( "$@" )
	[ "$*" ] || files=( "/etc/krb5.keytab" )
	file_test -f "${files[@]}"
	for f in "${files[@]}"; do
		info "$f:"
		run_ktutil <<EOF
rkt $f
l
q
EOF
	done | egrep -v 'ktutil:  [ql]' |sed -e 's,^ktutil:  rkt ,\n,'
}

k5_kt_keys() {
	has_args 0 "$@"
	local -a keys=( $(k5_host_list) )
	local kf
	for kf in "${keys[@]}"; do
		local f="$KEYTAB_DIR/$kf"
		echo "$kf:"
		sudo sed -e 's,^,\t,' "$f.keys"
	done
}

k5_kt_gen() {
	has_args 1 "$@"
	local out=$1
	run rm -vf "$out"
	while read p; do
		run k5_kt_new "$out" "$p"
	done
}

######
# Host Key Tables

kt_hosts_make() {
	has_args 1 "$@"
	run_sudo test -f $KEYTAB_DIR/Makefile || k5_kt_hosts_init
	run_sudo make --silent -C $KEYTAB_DIR $1;
}


k5_kt_hosts() { cmd_dispatch "$@"; }

k5_kt_hosts_usage() {
	cat <<EOF
<cmd> ...
Kerberos 5 Host Key Table Commands:
	keys				Prints the host key file names
	build				Builds keytabs from key lists
	print				Print contents of keytabs
	clean				Removes the generated keytabs
EOF
}

k5_kt_hosts_all()     { has_args 0 "$@"; kt_hosts_make all; }
k5_kt_hosts_keys()    { has_args 0 "$@"; kt_hosts_make keys; }
k5_kt_hosts_print()   { has_args 0 "$@"; kt_hosts_make print; }
k5_kt_hosts_clean()   { has_args 0 "$@"; kt_hosts_make clean; }

k5_admin_init_keytabs() {
	local makefile
	makefile=$(cmd_tempfile)
	cat >$makefile <<'EOF'
KEYS := $(wildcard *.keys)
KEYTABS = $(patsubst %.keys,%.keytab,$(KEYS))

all: $(KEYTABS)

keys:
	echo $(KEYS)

print: $(KEYTABS)
	k5 kt list "$*"

clean:
	rm -f $(KEYTABS)
	rm Makefile

%.keytab: %.keys
	k5 kt gen "$@" < "$<"
EOF
	run_sudo mkdir -p $KEYTAB_DIR
	run_sudo mv $makefile $KEYTAB_DIR/Makefile
	run_sudo chown root:root $KEYTAB_DIR/Makefile
	run_sudo chmod 0600 $KEYTAB_DIR/Makefile
}


######
# Host Management

is_admin_host() {
	has_args 1 "$@"
	[ "$1" = "$admin_host" -o "$1" = "$admin_server" ]
}

require_admin_host() {
	is_admin_host "$host" || error "must be run on admin host"
}

k5_host() { cmd_dispatch "$@"; }

k5_host_usage() {
	cat <<EOF
...
Kerberos 5 Host Commands:
	new <hostname>			Creates a new Kerberos 5 host
	delete <hostname>		Deletes a Kerberos 5 host
	init ...			Host initialization commands
	list				Prints the list of Kerberos 5 hosts

Kerberos 5 Host Key List Commands:
	keys <hostname>			Print the list of host keys
	edit <hostname>			Edit the list of host keys
EOF
}

k5_host_new() {
	has_args 1 "$@"
	local fqdn=$1
	local host=${fqdn%%.*}
	local name="host/$fqdn"

	local keys
	keys=$(krb5_host_keyfile "$host")

	run k5_srv_add "$name"
	if [ ! -f "$keys" ]; then
		info "creating $keys..."
		echo $name | sudo_pipe_to_file "$keys"
	else
		error "$host: host exists"
	fi
}

k5_host_delete() {
	has_args 1 "$@"
	local fqdn=$1
	local host=${fqdn%%.*}
	local name="host/$fqdn"

	local keys
	keys=$(krb5_host_keyfile "$host")

	run_sudo rm -if "$keys"
	k5_pr_delete "$name"
}

k5_host_list() {
	run_sudo find "$KEYTAB_DIR" -name '*.keys' \
		| sed -e "s,^$KEYTAB_DIR/,," -e 's,\.keys$,,'
}

k5_host_keys() {
	has_args 1 "$@"
	local keys
	keys=$(krb5_host_keyfile "$1")
	run_sudo cat "$keys"
}

k5_host_edit() {
	has_args 1 "$@"
	local keys
	keys=$(krb5_host_keyfile "$1")
	run_editor "$keys"
}


######
# Host Initialization CLI

k5_host_init() {
	require_admin_host
	cmd_dispatch "$@"
}

k5_host_init_usage() {
	cat <<USAGE
...
Kerberos 5 Host Commands:
	all <host>			Performs all initialization for <host>
	deps <host>			Installs native dependencies on <host>
	config <host>			Installs new /etc/krb5.conf on <host>
	keytab <host>			Installs new /etc/krb5.keytab on <host>
USAGE
}

k5_host_init_all() {
	k5_host_init_deps "$@"
	k5_host_init_config "$@"
	k5_host_init_keytab "$@"
}

k5_host_init_deps() {
	has_args 1 "$@"
	apt_install_remote "$1" "${k5_client_packages[@]}"
}

k5_host_init_config() {
	has_args 1 "$@"
	remote_deploy_file "$1" $KRB5_CONF $KRB5_CONF
}

k5_host_init_keytab() {
	has_args 1 "$@"
	local host=$1
	local ktfile=$(krb5_host_ktfile "$host")
	remote_deploy_file "$host" "$ktfile" $KRB5_KEYTAB
}


######
# kadmin commands

k5_admin() {
	require_admin_host
	cmd_dispatch "$@"
}

k5_admin_usage() {
	cat <<USAGE
...
Kerberos 5 Admin Commands:
	init ...			Kerberos 5 server initialization
	run ...				Runs kadmin with the given arguments
USAGE
}

k5_admin_run() {
	run_kadmin "$@"
}


######
# Administative Initialization

k5_admin_init() { cmd_dispatch "$@"; }

k5_admin_init_usage() {
	cat <<USAGE
...
Kerberos 5 Admin Setup Commands:
	all				Performs all initialization steps
	server				Installs server key table
	keytabs				Installs server key table
	hosts [<name>+]			Installs host configuration
USAGE
}

k5_admin_init_server() {
	has_args 0 "$@"

	local host_keytab
	host_keytab=$(krb5_host_ktfile $host)
	[ -f "$host_keytab" ] || error "$host_keytab: key table file not found"

	# setup a link to this host's keytab
	run_sudo rm -f $KRB5_KEYTAB
	run_sudo ln -s $host_keytab $KRB5_KEYTAB
}

k5_admin_init_hosts() {
	local -a hosts=( "$@" )
	[ "$*" ] || hosts=( $(k5_host_list) )
	for_each k5_host_init_all "${hosts[@]}"
}


######
# Check

k5_check() {
	if $intense; then
		k5_pr_list
		k5_kt_hosts
		k5_host_list
	else
		app_help
	fi
}


######
# Main

k5_desc() {
	echo "Kerberos 5 management tool"
}

k5_usage() {
	cat <<USAGE
...
Kerberos 5 Commands:
	pr ...				Principle management commands
	srv ...				Service management commands
	host ...			Host management commands
	kt ...				Key table management commands
	admin ...			Low-level administration commands
USAGE
}

k5_help() {
	cat<<HELP
The $script_name tool automates Kerberos 5 server management, including
installation, configuration, creation and updates, and host setup.
HELP
}

app_run "$@"

View the Developer Guide Index

View the Reference Manual Index


Generated on Fri Jul 28 14:34:33 PDT 2017 by mcsh d14 v0.23.0.