#!/bin/bash
# net/l4 - LDAP helper
set -e
source "/home/zwelch/src/mcf/mcsh-release/install/share/mcsh/mcsh.sh"
lib_load 'net/ldap'
######
# Script Configuration
l4_config_files() {
case "$1" in
(tool|usertool) echo "$script_name.passwd" ;;
esac
}
######
# Low-level functions
client_gen_config() {
cat <<EOF
[krb5ldap]
nss_passwd=passwd: files ldap
nss_group=group: files ldap
nss_shadow=shadow: files ldap
nss_netgroup=netgroup: files ldap
pam_auth=auth sufficient pam_krb5.so
auth required pam_unix.so nullok_secure use_first_pass
pam_account=account sufficient pam_krb5.so
account required pam_unix.so
pam_password=password sufficient pam_krb5.so
password required pam_unix.so nullok obscure min=4 max=8 md5
pam_session=session required pam_unix.so
session required pam_mkhomedir.so skel=/etc/skel/
session optional pam_krb5.so
session optional pam_foreground.so
[krb5ldap.cached]
nss_passwd=passwd: files ldap [NOTFOUND=return] db
nss_group=group: files ldap [NOTFOUND=return] db
nss_shadow=shadow: files ldap
nss_netgroup=netgroup: files ldap
pam_auth=auth required pam_env.so
auth sufficient pam_unix.so likeauth nullok
auth [default=ignore success=1 service_err=reset] pam_krb5.so use_first_pass
auth [default=die success=done] pam_ccreds.so action=validate use_first_pass
auth sufficient pam_ccreds.so action=store use_first_pass
auth required pam_deny.so
pam_account=account sufficient pam_krb5.so
account required pam_unix.so
pam_password=password sufficient pam_krb5.so
password required pam_unix.so nullok obscure min=4 max=8 md5
pam_session=session required pam_unix.so
session required pam_mkhomedir.so skel=/etc/skel/
session optional pam_krb5.so
session optional pam_foreground.so
EOF
}
l4_remote() { cmd_dispatch "$@"; }
l4_remote_usage() {
cat <<USAGE
<cmd>
Remote Commands:
install <host> Installs LDAP packages on remote host
config <host> Deploys LDAP support on remote host
USAGE
}
l4_remote_install() {
has_args 1 "$@"
apt_install_remote "$1" "${ldap_client_packages[@]}"
}
l4_remote_config() {
has_args 1 "$@"
local host=$1
local src
src=$(cmd_tempfile)
client_gen_config >$src
local auth_config_file
auth_config_file=$etcdir/auth-client-config/profile.d/krb-auth-config
remote_deploy_file $host "$src" "$auth_config_file"
run rm -f $src
remote_sudo $host chown root:root $auth_config_file
remote_sudo $host chmod go-rwx $auth_config_file
remote_sudo $host auth-client-config -a -p krb5ldap
}
setup_schema() {
cat <<EOF
dn: $ldap_hosts_dn
objectClass: organizationalUnit
ou: $ldap_hosts_ou
dn: $ldap_users_dn
objectClass: organizationalUnit
ou: $ldap_users_ou
dn: $ldap_groups_dn
objectClass: organizationalUnit
ou: $ldap_groups_ou
EOF
}
setup_sasl() {
cat <<EOF
olcSaslHost: $kdc_host.$domain
olcSaslRealm: $ldap_realm
olcSaslSecProps: noplain,noactive,noanonymous,minssf=56
olcAuthzRegexp: {0}"uid=([^/]*),cn=$domain,cn=GSSAPI,cn=auth" "uid=\$1,$ldap_users_dn"
olcAuthzRegexp: {1}"uid=host/([^/]*).$domain,cn=$domain,cn=gssapi,cn=auth" "cn=\$1,$ldap_hosts_dn"
olcAuthzRegexp: {2}"uid=ldap/admin,cn=$domain,cn=gssapi,cn=auth" "cn=admin,cn=config"
EOF
}
######
# Host CLI (incomplete)
l4_host() { cmd_dispatch "$@"; }
l4_host_exists() { entity_exists host "$@"; }
l4_host_extract() { entity_extract host "$@"; }
l4_host_id() { entity_extract host "$1" hid?; }
l4_host_ids() { entity_ids host hid? "$@"; }
l4_host_next_id() { entity_next_id host; }
l4_host_delete() { entity_delete host "$@"; }
l4_host_dn() { cmd_dispatch "$@"; }
l4_host_dn_usage() { entity_dn_usage; }
l4_host_dn_add() { entity_dn_modify host cn add "$@"; }
l4_host_dn_edit() { entity_dn_modify host cn modify "$@"; }
l4_host_dn_delete() { entity_dn_modify host cn delete "$@"; }
l4_host_attr() { cmd_dispatch "$@"; }
l4_host_attr_usage() { entity_attr_usage hid?; }
l4_host_attr_add() { entity_attr_modify host modify add "$@"; }
l4_host_attr_edit() { entity_attr_modify host modify replace "$@"; }
l4_host_attr_delete() { entity_attr_modify host modify delete "$@"; }
######
# Group CLI
l4_group() { cmd_dispatch "$@"; }
l4_group_usage() {
cat <<EOF
<cmd> [...]
Group Commands:
info [<name>+] Prints human readable list
list Prints list of group names
ids Prints list of group ids
add <name> <gid> <desc> Adds a new group
delete <name>+ Deletes one or more groups
Group Query Commands:
next_id Prints next available group ID
exists <name> Returns true if group exists
show <name> [<attrs>+] Displays group record
id <name> Displays group id
Group Command Groups:
dn .... Group of DN commands
attr .... Group of attribute commands
user .... Group of member user commands
EOF
}
l4_group_exists() { entity_exists group "$@"; }
l4_group_extract() { entity_extract group "$@"; }
l4_group_id() { entity_extract group "$1" gidNumber; }
l4_group_ids() { entity_ids group gidNumber "$@"; }
l4_group_next_id() { entity_next_id group; }
l4_group_delete() { entity_delete group "$@"; }
l4_group_dn() { cmd_dispatch "$@"; }
l4_group_dn_usage() { entity_dn_usage; }
l4_group_dn_add() { entity_dn_modify group cn add "$@"; }
l4_group_dn_edit() { entity_dn_modify group cn modify "$@" ; }
l4_group_dn_delete() { entity_dn_modify group cn delete "$@" ; }
l4_group_attr() { cmd_dispatch "$@"; }
l4_group_attr_usage() { entity_attr_usage cn; }
l4_group_attr_add() { entity_attr_modify group modify add "$@"; }
l4_group_attr_edit() { entity_attr_modify group modify replace "$@"; }
l4_group_attr_delete() { entity_attr_modify group modify delete "$@"; }
l4_group_list() { l4_extract "(objectClass=posixGroup)" "cn" |sort; }
l4_group_show() {
min_args 1 "$@"
local cn=$1
shift
l4_search "(&(cn=$cn)(objectClass=posixGroup))" "$@"
}
l4_group_info() {
if [ -z "$*" ]; then
with_all_groups l4_group_info
return
fi
group_info Login GID Description
group_info ------- ----- -------------
{
for g in "$@"; do
local d
d=$(l4_group_extract "$g" description)
i=$(l4_group_extract "$g" gidNumber)
group_info "$g" "$i" "$d" "${u[*]}"
done
} | ldap_sort
}
group_info() {
printf "%-14s %-5s\t%-32s\t%s\n" "$@"
}
l4_group_users() {
if [ -z "$*" ]; then
with_all_groups l4_group_users
return
fi
for g in "$@"; do
local -a u
u=($(l4_group_user_list "$g"))
echo "$g: ${u[@]}"
done
}
l4_group_add() {
has_args 3 "$@"
local gid name
name=$1
gid=$2
desc=$3
openldap_add <<EOF
dn: cn=$name,$ldap_groups_dn
objectClass: posixGroup
cn: $name
gidNumber: $gid
description: $desc
EOF
}
l4_group_user() { cmd_dispatch "$@"; }
l4_group_user_usage() {
cat <<EOF
<cmd> [...]
Group User Commands:
list <name>
add <name> <uid>+
delete <name> <uid>+
modify <action> <name> <uid>+
EOF
}
l4_group_user_modify() {
min_args 3 "$@"
local action cn first
action=$1
cn=$2
shift 2
(
group_dn "$cn"
echo "changetype: modify"
echo "$action: memberUid"
for uid in "$@"; do
echo "memberUid: $uid"
done
) | openldap_modify
}
l4_group_user_add() { l4_group_user_modify add "$@"; }
l4_group_user_delete() { l4_group_user_modify delete "$@"; }
l4_group_user_list() {
has_args 1 "$@"
l4_group_extract "$1" memberUid
}
######
# User CLI
l4_user() { cmd_dispatch "$@"; }
l4_user_usage() {
cat <<EOF
<cmd> [...]
User Commands:
info [<name>+] Prints human readable list
list Prints list of user names
ids Prints list of user ids
names Prints list of user names
email [<name>+] Prints list of user emails
add <name> <uid> <gid> <first> <last> [<email>] [<passwd>]
Adds a new user
delete <name>+ Deletes one or more users
passwd <name> Changes the user password
User Query Commands:
next_id Prints next available group ID
exists <name> Returns true if group exists
show <name> [<attrs>+] Displays group record
id <name> Displays group id
User Command Groups:
dn .... Group of DN commands
attr .... Group of attribute commands
EOF
}
l4_user_exists() { entity_exists user "$@"; }
l4_user_extract() { entity_extract user "$@"; }
l4_user_id() { entity_extract user "$1" uidNumber; }
l4_user_ids() { entity_ids user uidNumber "$@"; }
l4_user_next_id() { entity_next_id user; }
l4_user_delete() { entity_delete user "$@"; }
l4_user_dn() { cmd_dispatch "$@"; }
l4_user_dn_usage() { entity_dn_usage; }
l4_user_dn_add() { entity_dn_modify user uid add "$@"; }
l4_user_dn_edit() { entity_dn_modify user uid modify "$@" ; }
l4_user_dn_delete() { entity_dn_modify user uid delete "$@" ; }
l4_user_attr() { cmd_dispatch "$@"; }
l4_user_attr_usage() { entity_attr_usage uid; }
l4_user_attr_add() { entity_attr_modify user modify add "$@"; }
l4_user_attr_edit() { entity_attr_modify user modify replace "$@"; }
l4_user_attr_delete() { entity_attr_modify user modify delete "$@"; }
l4_user_list() { l4_extract "(objectClass=posixAccount)" "uid" |sort; }
l4_user_show() {
min_args 1 "$@"
local uid=$1
shift 1
l4_search "(&(uid=$uid)(objectClass=posixAccount))" "$@"
}
l4_user_info() {
if [ -z "$*" ]; then
with_all_users l4_user_info
return
fi
user_info Login UID GID Name
user_info ------ ---- ---- -----
for_each_user _l4_user_info "$@" |ldap_sort
}
_l4_user_info() {
local u=$1
local f g
f=$(l4_user_extract "$u" uidNumber)
g=$(l4_user_extract "$u" gidNumber)
local -a n
n=($(l4_user_extract "$u" displayName))
user_info "$u" "$f" "$g" "${n[*]}"
}
user_info() { printf "%-14s\t%5s %4s\t%s\n" "$@"; }
l4_user_names() {
if [ -z "$*" ]; then
with_all_users l4_user_names
return
fi
user_names Login Given Surname 'Full Name' 'Display'
user_names ----- ----- ------- --------- -----
for_each_user _l4_user_names "$@"
}
_l4_user_names() {
local u=$1
local gn sn cn dn
gn=$(l4_user_extract "$u" givenName)
sn=$(l4_user_extract "$u" sn)
cn=$(l4_user_extract "$u" cn)
dn=$(l4_user_extract "$u" displayName)
user_names "$u" "$gn" "$sn" "$cn" "$dn"
}
user_names() { printf "%-14s\t%-10s %-10s %-16s\t%-16s\n" "$@"; }
_l4_user_email() {
local u=$1
n=$(l4_user_extract "$u" displayName)
e=$(l4_user_extract "$u" mail)
echo "$n <$e>"
}
l4_user_email() {
if [ -z "$*" ]; then
with_all_users l4_user_email
return
fi
for_each_user _l4_user_email "$@"
}
l4_user_add() {
min_args 5 "$@"
local login=$1
local uid=$2
local gid=$3
local gn=$4
local sn=$5
local mail=$6
local passwd=$7
if [ -z "$uid" -o $uid -eq 0 ]; then
uid=$(l4_user_next_id)
fi
if [ -z "$gid" -o $gid -eq 0 ]; then
gid=$(l4_group_next_id)
fi
local home
if [ "$mail" ]; then
home="/bin/false"
else
mail="$login@$domain"
home="/home/$login"
fi
[ "$passwd" ] || passwd=$(apg -n 1 -c "$login$uid")
local fn="$gn $sn"
if true; then
user_dn $login
cat <<EOF
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: $login
sn: $sn
givenName: $gn
cn: $fn
displayName: $fn
uidNumber: $uid
gidNumber: $gid
userPassword: $passwd
gecos: $fn
loginShell: /bin/false
homeDirectory: $home
mail: $mail
EOF
fi | openldap_add
l4_user_show "$login"
}
######
# Low-level commands
l4_extract() {
local search=$1
local field=$2
l4_search "$search" "$field" | ldif_extract $field
}
l4_search() {
openldap_search "$@"
}
l4_add() {
openldap_add "$@"
}
######
# Check
run_check() { echo "=== $@ ==="; "$@"; }
l4_check() {
if $intense; then
run_check l4_user_info
run_check l4_user_names
run_check l4_user_email
run_check l4_group_info
else
app_help
fi
}
######
# Main
l4_desc() { echo "LDAP management helper"; }
l4_usage() {
cat <<USAGE
<cmd> ...
General Commands:
add ... - run ldapadd
search <query> [<field>+] - Run a search
extract <query> <field> - Extract field values
Command Groups:
user ... User management
group ... Group management
host ... Host management
remote ... Remote host management
USAGE
}
l4_help() {
cat<<HELP
The $script_name tool automates an LDAP server and directory.
HELP
}
app_run "$@"
Generated on Sat Jul 8 19:28:47 PDT 2017 by mcsh d14 v0.22.0.