diff --git a/README.md b/README.md
index 6f2d8c4..4d3bfa9 100644
--- a/README.md
+++ b/README.md
@@ -41,28 +41,15 @@ NCSA allows `createhost` principals for projects. This allows for two automated
In order to support this, you need to request a `createhost` principal keytab for your project, then assign the base64 encoding of the keytab file to `profile_system_auth::kerberos::createhostkeytab` and the first part of the principal's username to `profile_system_auth::kerberos::createhostuser` parameters. NCSA staff can request a `createhost` principal by emailing service@ncsa.illinois.edu. They will provide you a principal username and either the keytab file for that user or a BASE64 encoding of that keytab.
-## Reference
+The same sort of approach can be done if using Active Directory (AD) to create a computer object for your host and save its keytab locally. This can be configured by specifying the following paraters:
+
+```
+profile_system_auth::kerberos::ad_computers_ou # AD OU FOR COMPUTER OBJECTS
+profile_system_auth::kerberos::ad_createhostkeytab # BASE64 ENCODING OF KRB5 CREATEHOST KEYTAB FILE
+profile_system_auth::kerberos::ad_createhostuser # AD CREATEHOST USER
+profile_system_auth::kerberos::ad_domain # AD DOMAIN
+```
-### class profile_system_auth::config (
-- String $authselect_profile,
-- Boolean $enable_mkhomedir,
-- String $oddjobd_mkhomedir_conf,
-- $removed_pkgs,
-- Array[ String[1] ] $required_pkgs,
-- Boolean $use_authconfig,
-### class profile_system_auth::kerberos (
-- Hash $cfg_file_settings, # cfg files and their contents
-- Optional[ String ] $createhostkeytab, # BASE64 ENCODING OF KRB5 CREATEHOST KEYTAB FILE
-- Optional[ String ] $createhostuser, # CREATEHOST USER
-- Hash $crons,
-- Hash $files_remove_setuid,
-- Array[ String[1] ] $required_pkgs, # DEFAULT SET VIA MODULE DATA
-- Optional[ Array[ String[1] ] ] $root_k5login_principals, # PRINCIPALS WITH ROOT PRIVILEGES
-### class profile_system_auth::ldap (
-- String $ldap_conf, # ldap.conf file contents
-- Array[ String[1] ] $required_pkgs, # DEFAULT SET VIA MODULE DATA
-### class profile_system_auth::su (
-- Boolean $disable_su,
-- String $su_path,
+## Reference
[REFERENCE.md](REFERENCE.md)
diff --git a/REFERENCE.md b/REFERENCE.md
index 5fb1ba8..351249e 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -109,6 +109,10 @@ include profile_system_auth::kerberos
The following parameters are available in the `profile_system_auth::kerberos` class:
+* [`ad_computers_ou`](#-profile_system_auth--kerberos--ad_computers_ou)
+* [`ad_createhostkeytab`](#-profile_system_auth--kerberos--ad_createhostkeytab)
+* [`ad_createhostuser`](#-profile_system_auth--kerberos--ad_createhostuser)
+* [`ad_domain`](#-profile_system_auth--kerberos--ad_domain)
* [`cfg_file_settings`](#-profile_system_auth--kerberos--cfg_file_settings)
* [`createhostkeytab`](#-profile_system_auth--kerberos--createhostkeytab)
* [`createhostuser`](#-profile_system_auth--kerberos--createhostuser)
@@ -118,6 +122,30 @@ The following parameters are available in the `profile_system_auth::kerberos` cl
* [`required_pkgs`](#-profile_system_auth--kerberos--required_pkgs)
* [`root_k5login_principals`](#-profile_system_auth--kerberos--root_k5login_principals)
+##### `ad_computers_ou`
+
+Data type: `Optional[String]`
+
+Optional String of AD OU where computer objects should be created
+
+##### `ad_createhostkeytab`
+
+Data type: `Optional[String]`
+
+Optional String of base64 encoding of AD krb5 createhost keytab file
+
+##### `ad_createhostuser`
+
+Data type: `Optional[String]`
+
+Optional String of user with permissions to create host in AD
+
+##### `ad_domain`
+
+Data type: `Optional[String]`
+
+Optional String of the Active Directory domain that the computer should join
+
##### `cfg_file_settings`
Data type: `Hash`
diff --git a/data/common.yaml b/data/common.yaml
index 93e2bdb..788d4fc 100644
--- a/data/common.yaml
+++ b/data/common.yaml
@@ -27,6 +27,12 @@ profile_system_auth::config::oddjobd_mkhomedir_conf: |
profile_system_auth::config::pam_config: {}
+
+profile_system_auth::kerberos::ad_computers_ou: null
+profile_system_auth::kerberos::ad_createhostkeytab: null
+profile_system_auth::kerberos::ad_createhostuser: null
+profile_system_auth::kerberos::ad_domain: null
+
profile_system_auth::kerberos::cfg_file_settings:
/etc/krb5.conf: |
# This file is managed by Puppet.
diff --git a/data/os/RedHat.yaml b/data/os/RedHat.yaml
index 3919725..33a462c 100644
--- a/data/os/RedHat.yaml
+++ b/data/os/RedHat.yaml
@@ -10,6 +10,7 @@ profile_system_auth::config::use_authconfig: false
profile_system_auth::kerberos::files_remove_setuid:
"/usr/bin/ksu": {}
profile_system_auth::kerberos::required_pkgs:
+ - "adcli"
- "krb5-libs"
- "krb5-workstation"
profile_system_auth::ldap::ldap_conf: |
diff --git a/lib/facter/is_joined_ad_domain.rb b/lib/facter/is_joined_ad_domain.rb
new file mode 100644
index 0000000..3bdc395
--- /dev/null
+++ b/lib/facter/is_joined_ad_domain.rb
@@ -0,0 +1,8 @@
+Facter.add('kerberos_keytab_domains') do
+ setcode do
+ command = "klist -kte 2>&1 | grep $(hostname) | awk -F\\@ '{ print $2 }' | awk '{ print $1 }' | uniq"
+ result = Facter::Core::Execution.execute(command)
+ domains = result.split("\n").uniq
+ domains.join(',')
+ end
+end
diff --git a/manifests/kerberos.pp b/manifests/kerberos.pp
index a15a86f..8d190ed 100644
--- a/manifests/kerberos.pp
+++ b/manifests/kerberos.pp
@@ -2,6 +2,18 @@
#
# @summary Basic kerberos client setup, with optional host principal management
#
+# @param ad_computers_ou
+# Optional String of AD OU where computer objects should be created
+#
+# @param ad_createhostkeytab
+# Optional String of base64 encoding of AD krb5 createhost keytab file
+#
+# @param ad_createhostuser
+# Optional String of user with permissions to create host in AD
+#
+# @param ad_domain
+# Optional String of the Active Directory domain that the computer should join
+#
# @param cfg_file_settings
# Hash of file resource parameters for various config files
#
@@ -30,12 +42,16 @@
# include profile_system_auth::kerberos
#
class profile_system_auth::kerberos (
- Hash $cfg_file_settings, # cfg files and their contents
+ Optional[String] $ad_computers_ou, # AD OU FOR COMPUTER OBJECTS
+ Optional[String] $ad_createhostkeytab, # BASE64 ENCODING OF KRB5 CREATEHOST KEYTAB FILE
+ Optional[String] $ad_createhostuser, # AD CREATEHOST USER
+ Optional[String] $ad_domain, # AD DOMAIN
+ Hash $cfg_file_settings, # cfg files and their contents
Optional[String] $createhostkeytab, # BASE64 ENCODING OF KRB5 CREATEHOST KEYTAB FILE
Optional[String] $createhostuser, # CREATEHOST USER
- Hash $crons,
- Boolean $enable,
- Hash $files_remove_setuid,
+ Hash $crons,
+ Boolean $enable,
+ Hash $files_remove_setuid,
Array[String[1]] $required_pkgs, # DEFAULT SET VIA MODULE DATA
Optional[Array[String[1]]] $root_k5login_principals, # PRINCIPALS WITH ROOT PRIVILEGES
) {
@@ -80,11 +96,12 @@
}
}
+ # KERBEROS HOST PRINCIPAL CREATION
if ( $createhostkeytab and $createhostuser ) {
# CREATE KEYS AND SETUP RENEWAL
file { '/root/createhostkeytab.sh':
ensure => file,
- mode => '0700',
+ mode => '0500',
source => "puppet:///modules/${module_name}/root/createhostkeytab.sh",
}
## THIS MIGHT NEED TO BE SMARTER TO ALLOW FOR MULTIPLE HOSTNAMES ON ONE SERVER
@@ -115,5 +132,36 @@
cron { $k: ensure => absent, }
}
}
+
+ # AD JOIN AND KEYTAB CREATION
+ if ( $ad_createhostkeytab and $ad_createhostuser and $ad_computers_ou and $ad_domain ) {
+ $kerberos_domains = split($facts['kerberos_keytab_domains'], ',')
+ if ( $ad_domain in $kerberos_domains ) {
+ $ensure_parm = 'absent'
+ } else {
+ $ensure_parm = 'present'
+
+ exec { 'run_ad_create_host_keytab_script':
+ path => ['/usr/bin', '/usr/sbin', '/usr/lib/mit/bin'],
+ command => Sensitive(
+ "/root/ad_createhostkeytab.sh '${ad_domain}' '${ad_computers_ou}' '${ad_createhostuser}' '${ad_createhostkeytab}' "
+ ),
+ #refreshonly => true,
+ require => File['/root/ad_createhostkeytab.sh'],
+ }
+
+ # FOLLOWING IS JUST IN CASE THE run_ad_create_host_keytab_script TIMES OUT, WHICH IT HAS
+ file { '/root/createhost.keytab':
+ ensure => absent,
+ require => Exec['run_ad_create_host_keytab_script'],
+ }
+ }
+
+ file { '/root/ad_createhostkeytab.sh':
+ ensure => $ensure_parm,
+ mode => '0500',
+ content => template("${module_name}/ad_createhostkeytab.sh.erb"),
+ }
+ }
}
}
diff --git a/templates/ad_createhostkeytab.sh.erb b/templates/ad_createhostkeytab.sh.erb
new file mode 100644
index 0000000..294c1fb
--- /dev/null
+++ b/templates/ad_createhostkeytab.sh.erb
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Enable debugging mode
+set -x
+
+# ASSIGN ARGUMENTS FROM COMMAND LINE ARGUMENTS
+AD_DOMAIN=$1 # Active Directory domain
+AD_OU_COMPUTERS=$2 # Organizational Unit for computers in AD
+AD_USER=$3 # User with permissions to create host in AD
+KEYTAB_BASE64=$4 # Base64 encoded keytab for creating host
+
+# ASSIGN STATIC VARIABLES
+HOST_FQDN="<%= @fqdn %>" # Fully Qualified Domain Name of the host
+KEYTAB_FILE="/root/createhost.keytab" # Path to store the decoded keytab file
+OS_NAME="<%= @os['name'] %>" # Operating System name
+
+# Decode the base64 encoded keytab and save it to a file
+echo "${KEYTAB_BASE64}" | base64 --decode > $KEYTAB_FILE
+
+# Authenticate using the keytab file
+kinit -k -t $KEYTAB_FILE $AD_USER
+
+# Pre-create the computer account in the specified OU
+adcli preset-computer --domain="${AD_DOMAIN}" --domain-ou="${AD_OU_COMPUTERS}" -U "${AD_USER}" --login-ccache --os-name="${OS_NAME}" $HOST_FQDN
+
+# Join the computer to the AD domain
+adcli join --domain="${AD_DOMAIN}" -U "${AD_USER}" --login-ccache
+
+# Destroy the Kerberos ticket cache for the user
+kdestroy -p $AD_USER
+
+# Optionally, list the contents of the keytab file (uncomment for debugging)
+# klist -kte
+
+# Remove the keytab file for security reasons
+rm -f $KEYTAB_FILE