add-sftp-user/scripts/system_prep.sh

153 lines
7.5 KiB
Bash
Raw Normal View History

2025-07-29 16:33:46 +00:00
#!/bin/bash
# ==============================================================================
# Canonical System Preparation Library for SFTP User Addon
#
# Provides a standardized function to prepare the Jelastic environment for
# secure SFTP/SSH user chroot jailing.
# ==============================================================================
# This script expects that 'scripts/logging.sh' has already been sourced
# by the calling script, so functions like log() and log_cmd() are available.
prepare_sftp_system() {
log "Phase: Preparing and Verifying System for SFTP/SSH"
# --------------------------------------------------------------------------
# Step 1: Fix critical directory permissions for chroot
# --------------------------------------------------------------------------
log "Checking and fixing critical directory permissions for chroot jail..."
if [ -d "/home" ] && [[ "$(stat -c '%U:%G' /home)" != "root:root" ]]; then
log "Fixing /home ownership. Current: $(stat -c '%U:%G' /home)"
log_cmd "chown root:root /home" "Set /home owner to root:root"
fi
log_cmd "chmod 755 /home" "Set /home permissions to 755"
log_success "Directory permissions check complete."
# --------------------------------------------------------------------------
# Step 2: Ensure PasswordAuthentication is enabled globally
# --------------------------------------------------------------------------
local sshd_config="/etc/ssh/sshd_config"
log "Ensuring global PasswordAuthentication is enabled in $sshd_config..."
# Use grep to check the current state and sed to change it if needed.
# This is more robust than blindly adding a line.
if grep -qE "^[#\s]*PasswordAuthentication\s+no" "$sshd_config"; then
log "PasswordAuthentication is disabled, enabling it now."
# Comment out the old line and add the new one to be explicit.
log_cmd "sed -i 's/^[#\s]*PasswordAuthentication\s+no/#&/' $sshd_config" "Commenting out old PasswordAuthentication line"
log_cmd "echo 'PasswordAuthentication yes' >> $sshd_config" "Adding 'PasswordAuthentication yes' to sshd_config"
elif ! grep -qE "^[#\s]*PasswordAuthentication\s+yes" "$sshd_config"; then
log "PasswordAuthentication setting not found, adding it."
log_cmd "echo 'PasswordAuthentication yes' >> $sshd_config" "Adding 'PasswordAuthentication yes' to sshd_config"
else
log_debug "PasswordAuthentication is already enabled."
fi
2025-07-29 16:59:23 +00:00
# Ensure we disable any Subsystem lines pointing to external sftp-server
if grep -qE "^[#\s]*Subsystem\s+sftp\s+/" "$sshd_config"; then
log "Commenting out existing Subsystem sftp external binary line"
log_cmd "sed -i 's/^\s*Subsystem\s\+sftp\s\+/#&/' $sshd_config" "Comment out old Subsystem"
fi
2025-07-29 16:33:46 +00:00
# --------------------------------------------------------------------------
# Step 3: Create a dedicated addon config for modern SSH servers
# --------------------------------------------------------------------------
local addon_config_file="/etc/ssh/sshd_config.d/99-sftp-addon.conf"
log "Creating dedicated SSH configuration at $addon_config_file..."
2025-07-29 16:59:23 +00:00
echo "Subsystem sftp internal-sftp" > "$addon_config_file"
2025-07-29 17:14:57 +00:00
# Group-based policy:
# - sftpusers : SFTP-only, jailed
# - sshusers : full SSH + SFTP, NOT chrooted (still jailed by Linux user perms)
2025-07-29 16:59:23 +00:00
cat >> "$addon_config_file" << EOF
2025-07-29 16:33:46 +00:00
# Configuration managed by SFTP-Addon - DO NOT EDIT MANUALLY
# --- SFTP-ONLY USERS ---
# Users in this group are forced into the SFTP server and cannot get a shell.
Match Group sftpusers
ChrootDirectory /home/sftpusers/%u
ForceCommand internal-sftp
PasswordAuthentication yes
AllowTcpForwarding no
X11Forwarding no
2025-07-29 17:14:57 +00:00
# --- SSH & SFTP USERS (no chroot) ---
2025-07-29 16:33:46 +00:00
Match Group sshusers
PasswordAuthentication yes
AllowTcpForwarding no
X11Forwarding no
EOF
log_success "Created dedicated SSH configuration for addon."
# --------------------------------------------------------------------------
# Step 4: Validate configuration and restart SSH service
# --------------------------------------------------------------------------
log "Validating new SSH configuration..."
if log_cmd "sshd -t" "Validating sshd configuration syntax"; then
log_success "SSH configuration is valid. Restarting SSH service..."
if ! log_cmd "systemctl restart sshd" "Restarting sshd service"; then
log_error "Failed to restart sshd, but configuration was valid. Manual check may be required."
return 1
fi
log_success "SSHD service restarted successfully."
else
log_error "SSH configuration is INVALID. The new config file at $addon_config_file may contain an error."
# We don't revert here because the base config was likely valid.
# The new file simply won't be loaded by sshd.
return 1
fi
# Ensure /home/sftpusers exists with correct ownership and permissions
if [ ! -d "/home/sftpusers" ]; then
log_cmd "mkdir -p /home/sftpusers" "Creating /home/sftpusers directory"
fi
log_cmd "chown root:root /home/sftpusers" "Setting /home/sftpusers ownership to root:root"
log_cmd "chmod 755 /home/sftpusers" "Setting /home/sftpusers permissions to 755"
# --------------------------------------------------------------------------
# Step 5: Ensure webroot has correct group ownership and permissions
# --------------------------------------------------------------------------
local webroot_dir="/var/www/webroot/ROOT"
if [ -d "$webroot_dir" ]; then
log "Ensuring webroot directory has correct group ownership and permissions..."
# Check if litespeed group exists, create if not
if ! getent group litespeed > /dev/null; then
log "Creating litespeed group"
log_cmd "groupadd litespeed" "Creating litespeed group"
fi
# Check current group ownership
local current_group=$(stat -c '%G' "$webroot_dir" 2>/dev/null)
if [ "$current_group" != "litespeed" ]; then
log "Setting webroot group ownership to litespeed (was: $current_group)"
log_cmd "chgrp -R litespeed $webroot_dir" "Setting webroot group to litespeed"
else
log_debug "Webroot already owned by litespeed group"
fi
# Check if group write permission exists
# Group write exists if second digit is 7(rwx), 6(rw-), 3(-wx), or 2(-w-)
local current_perms=$(stat -c '%a' "$webroot_dir" 2>/dev/null)
if [ -n "$current_perms" ]; then
# Extract group write bit (second digit)
local group_write_bit=$(echo "$current_perms" | cut -c2)
# Check if write bit is NOT set (4=r--, 5=r-x, 1=--x, 0=---)
if [ "$group_write_bit" = "4" ] || [ "$group_write_bit" = "5" ] || [ "$group_write_bit" = "1" ] || [ "$group_write_bit" = "0" ]; then
log "Adding group write permissions to webroot (current: $current_perms)"
log_cmd "chmod -R g+w $webroot_dir" "Adding group write permissions to webroot"
else
log_debug "Webroot already has group write permissions (current: $current_perms)"
fi
fi
log_success "Webroot permissions configured for group access"
else
log_warning "Webroot directory $webroot_dir does not exist, skipping permission setup"
fi
2025-07-29 16:33:46 +00:00
log_success "System preparation complete."
return 0
}