From 6726ca78a676a95dbadc72f5afb3494c4444db73 Mon Sep 17 00:00:00 2001 From: Bill Glick Date: Tue, 3 Dec 2024 17:47:09 -0600 Subject: [PATCH] SVCPLAN-6686: Add support for AD createhost functionality --- README.md | 31 ++++-------- REFERENCE.md | 28 +++++++++++ data/os/RedHat.yaml | 1 + manifests/kerberos.pp | 75 ++++++++++++++++++++++++++-- templates/ad_createhostkeytab.sh.erb | 34 +++++++++++++ 5 files changed, 143 insertions(+), 26 deletions(-) create mode 100644 templates/ad_createhostkeytab.sh.erb 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/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/manifests/kerberos.pp b/manifests/kerberos.pp index a15a86f..e9a0524 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,6 +96,7 @@ } } + # KERBEROS HOST PRINCIPAL CREATION if ( $createhostkeytab and $createhostuser ) { # CREATE KEYS AND SETUP RENEWAL file { '/root/createhostkeytab.sh': @@ -115,5 +132,55 @@ cron { $k: ensure => absent, } } } + + # AD JOIN AND KEYTAB CREATION + if ( $ad_createhostkeytab and $ad_createhostuser and $ad_computers_ou and $ad_domain ) { + # Step 1: Ensure a temporary script file is in place only if a command fails + exec { 'check_keytab_command': + path => ['/usr/bin', '/usr/sbin', '/usr/lib/mit/bin'], + command => "echo 'host is missing from keytab'", + unless => "klist -kte 2>&1 | grep 'host/${facts['networking']['fqdn']}' | grep -i '${ad_domain}'", + logoutput => true, + notify => Exec['run_ad_create_host_keytab_script'], + } + + file { '/root/ad_createhostkeytab.sh': + ensure => file, + mode => '0700', + content => Sensitive(template("${module_name}/ad_createhostkeytab.sh.erb")), + require => [ + Exec['check_keytab_command'], + ], + } + + # Step 2: Run the script if the command fails + exec { 'run_ad_create_host_keytab_script': + path => ['/usr/bin', '/usr/sbin', '/usr/lib/mit/bin'], + command => '/root/ad_createhostkeytab.sh', + refreshonly => true, + require => [ + Exec['check_keytab_command'], + File['/root/ad_createhostkeytab.sh'], + ], + notify => Exec['delete_ad_create_host_keytab_script'], + } + + # Step 3: Ensure the temporary script file is deleted once it has been run + exec { 'delete_ad_create_host_keytab_script': + command => '/bin/rm /root/ad_createhostkeytab.sh', + onlyif => 'test -f /root/ad_createhostkeytab.sh', + path => ['/bin', '/usr/bin'], + require => [ + Exec['check_keytab_command'], + Exec['run_ad_create_host_keytab_script'], + File['/root/ad_createhostkeytab.sh'], + ], + } + + # THE kerberos $crons FOR UPGRADING/REFRESHING HOST KEYTAB DO NOT SEEM TO WORK WITH AD. + # BUT IF YOU NEED TO UPDATE A HOST KEYTAB: + # YOU CAN MANUALLY REMOVE THOSE FROM THE LOCAL KEYTAB AND LET PUPPET CREATE A NEW ONE. + # THE VERSION NUMBERS SEEM TO ITERATE AUTOMATICALLY WHEN USING adcli TO RECREATE THEM. + } } } diff --git a/templates/ad_createhostkeytab.sh.erb b/templates/ad_createhostkeytab.sh.erb new file mode 100644 index 0000000..47bfef4 --- /dev/null +++ b/templates/ad_createhostkeytab.sh.erb @@ -0,0 +1,34 @@ +#!/bin/bash + +# Enable debugging mode +set -x + +# ASSIGN VARIABLES +AD_DOMAIN="<%= @ad_domain %>" # Active Directory domain +AD_OU_COMPUTERS="<%= @ad_computers_ou %>" # Organizational Unit for computers in AD +AD_USER="<%= @ad_createhostuser %>" # User with permissions to create host in AD +HOST_FQDN="<%= @fqdn %>" # Fully Qualified Domain Name of the host +KEYTAB_BASE64="<%= @ad_createhostkeytab %>" # Base64 encoded keytab for creating 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