Ok, so another update to my last update. I just started out a deployment on a new authentication infrastructure with saml in which I am not using the user_map script and this seems like it could be a sensible solution that would work independently any choices you have had to make regarding authentication mechanisms.
Everything I needed was built in to ood. I was not doing myself any favors by reinventing the wheel (see Fix "no home directory" issue when first time logging in):
Use the pun pre_hook config in your ood_portal.yml file:
pun_pre_hook_root_cmd: ‘/usr/local/bin/create_home_dir.sh’
pun_pre_hook_exports: ‘MELLON_REMOTE_USER,REMOTE_USER’
You’d think the script would be obvious but there is a gotcha here. This is why I am logging the output to /var/log/home_dir.
Using environment variables did not seem like an option because the context of the user changes a couple of times
1. Our researcher logs into Apache
2. The “apache” account executes the pre-pun hook - but with sudo
3. The script is executed as root.
Instead, the script parses out the username from the command line arguments passed to it.
name: Create user home directory script
ansible.builtin.copy:
dest: /usr/local/bin/create_home_dir.sh
content: |
#!/bin/bash# Setup logging LOG_DIR="/var/log/home_dir" LOG_FILE="$LOG_DIR/homedir.log" # Create log directory if it doesn't exist mkdir -p $LOG_DIR chmod 755 $LOG_DIR # Log function log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE } # Start logging log "Script started" log "Environment variables:" env | sort >> $LOG_FILE log "Command line arguments: $@" # Get username from command line arguments USERNAME="" while [[ $# -gt 0 ]]; do case $1 in -u|--user) USERNAME="$2" shift 2 ;; -P|--pre-hook) # Skip the pre-hook argument and its value shift 2 ;; *) shift ;; esac done if [ -z "$USERNAME" ]; then log "ERROR: Username not provided in command line arguments" exit 1 fi log "Username from command line: $USERNAME" # Remove @uchicago.edu if present USERNAME=${USERNAME%@uchicago.edu} log "Final username after processing: $USERNAME" if [ -z "$USERNAME" ]; then log "ERROR: Username is empty after processing" exit 1 fi # Check if user exists if ! id "$USERNAME" &>/dev/null; then log "ERROR: User $USERNAME does not exist" exit 1 fi # Create the home directory with .ssh directory and set permissions and selinux labels log "Creating home directory for $USERNAME" if [ ! -d "/home/$USERNAME" ]; then mkdir -p /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to create home directory" exit 1 fi log "Created new home directory" else log "Home directory already exists, ensuring proper setup" fi # Create .bashrc with proper content log "Creating .bashrc" cat > /home/$USERNAME/.bashrc << 'EOL' # .bashrc created by create_home_dir.sh # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific environment if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]] then PATH="$HOME/.local/bin:$HOME/bin:$PATH" fi export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions if [ -d ~/.bashrc.d ]; then for rc in ~/.bashrc.d/*; do if [ -f "$rc" ]; then . "$rc" fi done fi unset rc EOL # Create .bash_profile with proper content log "Creating .bash_profile" cat > /home/$USERNAME/.bash_profile << 'EOL' # .bash_profile created by create_home_dir.sh # Source .bashrc . ~/.bashrc EOL # Create and set .ssh directory permissions mkdir -p /home/$USERNAME/.ssh chown $USERNAME:$USERNAME /home/$USERNAME/.ssh chmod 700 /home/$USERNAME/.ssh # Ensure all files and directories have correct ownership and permissions log "Ensuring correct ownership and permissions" chown -R $USERNAME:$USERNAME /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to set ownership" exit 1 fi chmod 700 /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to set home directory permissions" exit 1 fi # Set file permissions chmod 644 /home/$USERNAME/.bashrc chmod 644 /home/$USERNAME/.bash_profile chmod 644 /home/$USERNAME/.bash_logout # Log SELinux operations log "Setting SELinux contexts" # Set context for home directory semanage fcontext -a -t user_home_dir_t "/home/$USERNAME(/.*)?" 2>> $LOG_FILE restorecon -Rv /home/$USERNAME 2>> $LOG_FILE # Set specific contexts for files chcon -t user_home_t /home/$USERNAME/.bashrc 2>> $LOG_FILE chcon -t user_home_t /home/$USERNAME/.bash_profile 2>> $LOG_FILE chcon -t user_home_t /home/$USERNAME/.bash_logout 2>> $LOG_FILE # Set context for .ssh directory semanage fcontext -a -t ssh_home_t "/home/$USERNAME/.ssh" 2>> $LOG_FILE restorecon -Rv /home/$USERNAME/.ssh 2>> $LOG_FILE log "Script completed successfully"
mode: ‘0755’
owner: root
group: root
setype: bin_tname: Set SELinux context for log directory
ansible.builtin.file:
path: /var/log/home_dir
state: directory
mode: ‘0755’
owner: root
group: root
setype: var_log_t
Or if you are not using selinux:
name: Create user home directory script
ansible.builtin.copy:
dest: /usr/local/bin/create_home_dir.sh
content: |
#!/bin/bash# Setup logging LOG_DIR="/var/log/home_dir" LOG_FILE="$LOG_DIR/homedir.log" # Create log directory if it doesn't exist mkdir -p $LOG_DIR chmod 755 $LOG_DIR # Log function log() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE } # Start logging log "Script started" log "Environment variables:" env | sort >> $LOG_FILE log "Command line arguments: $@" # Get username from command line arguments USERNAME="" while [[ $# -gt 0 ]]; do case $1 in -u|--user) USERNAME="$2" shift 2 ;; -P|--pre-hook) # Skip the pre-hook argument and its value shift 2 ;; *) shift ;; esac done if [ -z "$USERNAME" ]; then log "ERROR: Username not provided in command line arguments" exit 1 fi log "Username from command line: $USERNAME" # Remove @uchicago.edu if present USERNAME=${USERNAME%@uchicago.edu} log "Final username after processing: $USERNAME" if [ -z "$USERNAME" ]; then log "ERROR: Username is empty after processing" exit 1 fi # Check if user exists if ! id "$USERNAME" &>/dev/null; then log "ERROR: User $USERNAME does not exist" exit 1 fi # Create the home directory with .ssh directory and set permissions log "Creating home directory for $USERNAME" if [ ! -d "/home/$USERNAME" ]; then mkdir -p /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to create home directory" exit 1 fi log "Created new home directory" else log "Home directory already exists, ensuring proper setup" fi # Create .bashrc with proper content log "Creating .bashrc" cat > /home/$USERNAME/.bashrc << 'EOL' # .bashrc created by create_home_dir.sh # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # User specific environment if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]] then PATH="$HOME/.local/bin:$HOME/bin:$PATH" fi export PATH # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions if [ -d ~/.bashrc.d ]; then for rc in ~/.bashrc.d/*; do if [ -f "$rc" ]; then . "$rc" fi done fi unset rc EOL # Create .bash_profile with proper content log "Creating .bash_profile" cat > /home/$USERNAME/.bash_profile << 'EOL' # .bash_profile created by create_home_dir.sh # Source .bashrc . ~/.bashrc EOL # Create and set .ssh directory permissions mkdir -p /home/$USERNAME/.ssh chown $USERNAME:$USERNAME /home/$USERNAME/.ssh chmod 700 /home/$USERNAME/.ssh # Ensure all files and directories have correct ownership and permissions log "Ensuring correct ownership and permissions" chown -R $USERNAME:$USERNAME /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to set ownership" exit 1 fi chmod 700 /home/$USERNAME if [ $? -ne 0 ]; then log "ERROR: Failed to set home directory permissions" exit 1 fi # Set file permissions chmod 644 /home/$USERNAME/.bashrc chmod 644 /home/$USERNAME/.bash_profile chmod 644 /home/$USERNAME/.bash_logout log "Script completed successfully"
mode: ‘0755’
owner: root
group: root