491 lines
20 KiB
Plaintext
491 lines
20 KiB
Plaintext
version: 0.7
|
|
id: addsftp
|
|
type: update
|
|
description: An addon to add new SFTP users for Jelastic Virtuozzo LLSMP environments. It manages user accounts with secure SFTP access and optional SSH access with proper chroot jailing.
|
|
name: Add SFTP User for MB Panel
|
|
|
|
targetNodes:
|
|
nodeGroup: cp
|
|
|
|
settings:
|
|
sfpform:
|
|
submitUnchanged: true
|
|
fields:
|
|
- type: displayfield
|
|
name: infoField
|
|
caption: Root Directory /var/www/webroot/ROOT/
|
|
description: "Files will be accessible in a data/ROOT directory within the user's home"
|
|
required: false
|
|
- type: string
|
|
name: custom_username
|
|
caption: Custom Username
|
|
description: "Enter a custom username (3-32 characters, alphanumeric + underscore only)"
|
|
required: true
|
|
regex: ^[a-zA-Z0-9_]{3,32}$
|
|
regexText: "Username must be 3-32 characters long and contain only letters, numbers, and underscores"
|
|
- type: checkbox
|
|
name: allow
|
|
caption: Accept User Creation
|
|
default: false
|
|
required: false
|
|
- type: checkbox
|
|
name: enable_ssh
|
|
caption: Also enable SSH access
|
|
default: false
|
|
required: false
|
|
tip: "If enabled, the user will have both SFTP and SSH access. Otherwise, only SFTP access will be granted."
|
|
manageUserForm:
|
|
fields:
|
|
- type: string
|
|
name: manage_username
|
|
caption: Username to Manage
|
|
description: "Enter the username you want to manage."
|
|
required: true
|
|
regex: ^[a-zA-Z0-9_]{3,32}$
|
|
regexText: "Username must be 3-32 characters long and contain only letters, numbers, and underscores"
|
|
- type: string
|
|
name: custom_password
|
|
caption: New Password
|
|
description: "Enter a new password for the user (leave empty to generate random password)"
|
|
required: false
|
|
deleteUserForm:
|
|
fields:
|
|
- type: string
|
|
name: manage_username
|
|
caption: Username to Delete
|
|
description: "Enter the username you want to delete."
|
|
required: true
|
|
regex: ^[a-zA-Z0-9_]{3,32}$
|
|
regexText: "Username must be 3-32 characters long and contain only letters, numbers, and underscores"
|
|
|
|
globals:
|
|
username: ${settings.custom_username}
|
|
password: ${fn.password(min)}
|
|
sftpHost: ${env.domain}
|
|
sftpPort: 22
|
|
|
|
onInstall:
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create required directories and files in persistent location
|
|
mkdir -p /opt/add-sftp-user-addon/logs/{operations,errors,debug}
|
|
mkdir -p /opt/add-sftp-user-addon/scripts
|
|
chmod -R 755 /opt/add-sftp-user-addon/logs
|
|
touch /opt/add-sftp-user-addon/logs/script_output.log
|
|
chmod 644 /opt/add-sftp-user-addon/logs/script_output.log
|
|
|
|
# Download scripts with proper error handling
|
|
set -e
|
|
|
|
echo "Downloading add-sftp.sh..." >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
if ! wget --no-check-certificate -O /opt/add-sftp-user-addon/add-sftp.sh "https://deploy-proxy.mightybox.io/addons/add-sftp-user/raw/branch/main/add-sftp.sh" 2>&1 | tee -a /opt/add-sftp-user-addon/logs/script_output.log; then
|
|
echo "ERROR: Failed to download add-sftp.sh" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
|
|
echo "Downloading logging.sh..." >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
if ! wget --no-check-certificate -O /opt/add-sftp-user-addon/scripts/logging.sh "https://deploy-proxy.mightybox.io/addons/add-sftp-user/raw/branch/main/scripts/logging.sh" 2>&1 | tee -a /opt/add-sftp-user-addon/logs/script_output.log; then
|
|
echo "ERROR: Failed to download logging.sh" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
|
|
echo "Downloading system_prep.sh..." >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
if ! wget --no-check-certificate -O /opt/add-sftp-user-addon/scripts/system_prep.sh "https://deploy-proxy.mightybox.io/addons/add-sftp-user/raw/branch/main/scripts/system_prep.sh" 2>&1 | tee -a /opt/add-sftp-user-addon/logs/script_output.log; then
|
|
echo "ERROR: Failed to download system_prep.sh" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
|
|
# Verify files were downloaded and are not empty
|
|
for file in /opt/add-sftp-user-addon/add-sftp.sh /opt/add-sftp-user-addon/scripts/logging.sh /opt/add-sftp-user-addon/scripts/system_prep.sh; do
|
|
if [ ! -f "$file" ]; then
|
|
echo "ERROR: File not found: $file" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
if [ ! -s "$file" ]; then
|
|
echo "ERROR: File is empty: $file" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
# Check if file is actually a bash script and not an HTML error page
|
|
if head -n 1 "$file" | grep -q "<!DOCTYPE\|<html\|<HTML"; then
|
|
echo "ERROR: Downloaded file appears to be HTML (404/error page): $file" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
cat "$file" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 1
|
|
fi
|
|
echo "Verified: $file exists and is not empty" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
done
|
|
|
|
chmod +x /opt/add-sftp-user-addon/add-sftp.sh
|
|
chmod +x /opt/add-sftp-user-addon/scripts/*.sh
|
|
|
|
# Source libraries and run the system preparation function
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
source /opt/add-sftp-user-addon/scripts/system_prep.sh
|
|
|
|
log "======== STARTING ADDON INSTALLATION ========"
|
|
|
|
# Create sftpusers group and directory before running full prep
|
|
groupadd -f sftpusers
|
|
mkdir -p /home/sftpusers
|
|
|
|
prepare_sftp_system
|
|
|
|
log "======== ADDON INSTALLATION COMPLETE ========"
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create backup of original sshd_config
|
|
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d%H%M%S)
|
|
echo "Created backup of original sshd_config" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
|
|
# Fix SFTP subsystem configuration
|
|
if grep -q "Subsystemsftp" /etc/ssh/sshd_config; then
|
|
sed -i 's|Subsystemsftp/usr/libexec/openssh/sftp-server|Subsystem sftp /usr/libexec/openssh/sftp-server|g' /etc/ssh/sshd_config
|
|
echo "Fixed malformed SFTP subsystem configuration" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
fi
|
|
|
|
# Enable password authentication globally if it's set to no
|
|
if grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config; then
|
|
sed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
|
|
echo "Enabled global password authentication" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
fi
|
|
|
|
# Configure SFTP chroot jail
|
|
if ! grep -q "^Match Group sftpusers" /etc/ssh/sshd_config; then
|
|
echo -e "\n# SFTP chroot configuration for Jelastic Virtuozzo\nMatch Group sftpusers\n ChrootDirectory /home/sftpusers/%u\n ForceCommand internal-sftp\n PasswordAuthentication yes\n AllowTcpForwarding no\n X11Forwarding no" >> /etc/ssh/sshd_config
|
|
echo "Added SFTP chroot configuration" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
fi
|
|
|
|
# Create sftpusers group and directory
|
|
groupadd -f sftpusers
|
|
mkdir -p /home/sftpusers
|
|
chown root:root /home/sftpusers
|
|
chmod 755 /home/sftpusers
|
|
echo "Created sftpusers group and directory with proper permissions" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
|
|
# Clean up configuration - remove duplicate lines
|
|
awk '!seen[$0]++' /etc/ssh/sshd_config > /etc/ssh/sshd_config.tmp && mv /etc/ssh/sshd_config.tmp /etc/ssh/sshd_config
|
|
echo "Cleaned up sshd_config file" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
|
|
# Verify configuration
|
|
if sshd -t; then
|
|
echo "SSH configuration is valid, applying changes" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
systemctl restart sshd
|
|
else
|
|
echo "ERROR: SSH configuration is INVALID, reverting to backup" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
cp /etc/ssh/sshd_config.bak.$(ls -t /etc/ssh/sshd_config.bak.* | head -1 | awk -F/ '{print $NF}') /etc/ssh/sshd_config
|
|
systemctl restart sshd
|
|
fi
|
|
- cmd[cp]:
|
|
user: root
|
|
commands:
|
|
- systemctl restart sshd
|
|
- api: environment.control.RestartContainer
|
|
nodeGroup: cp
|
|
nodeid: ${nodes.cp.id}
|
|
- return: installSuccess
|
|
|
|
menu:
|
|
confirmText: "Do you want to list all users?"
|
|
loadingText: "Loading users..."
|
|
action: "list_users"
|
|
caption: "List Users"
|
|
successText: "Users listed successfully!"
|
|
logsNodeGroup: cp
|
|
|
|
actions:
|
|
add_sftp_user:
|
|
- setGlobals:
|
|
ssh_enabled: "false"
|
|
- if ('${settings.enable_ssh}' == 'true'):
|
|
setGlobals:
|
|
ssh_enabled: "true"
|
|
- setGlobals:
|
|
password: ${fn.password(12)}
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create unique log file for this operation
|
|
OUTPUT_LOG="/opt/add-sftp-user-addon/logs/user_creation-$(date +%Y%m%d%H%M%S).log"
|
|
touch "$OUTPUT_LOG"
|
|
|
|
# Execute the script and capture exit status
|
|
/opt/add-sftp-user-addon/add-sftp.sh "${globals.username}" "${globals.password}" "${globals.ssh_enabled}" >> "$OUTPUT_LOG" 2>&1
|
|
SCRIPT_EXIT_STATUS=$?
|
|
|
|
# Log the exit status
|
|
echo "Script exit status: $SCRIPT_EXIT_STATUS" >> "$OUTPUT_LOG"
|
|
|
|
# Check if script succeeded
|
|
if [ $SCRIPT_EXIT_STATUS -eq 0 ]; then
|
|
echo "SUCCESS: User ${globals.username} created successfully"
|
|
exit 0
|
|
else
|
|
echo "ERROR: Script failed with exit status $SCRIPT_EXIT_STATUS"
|
|
# Output last 10 lines of log for debugging
|
|
echo "Last 10 lines of log:"
|
|
tail -10 "$OUTPUT_LOG"
|
|
exit $SCRIPT_EXIT_STATUS
|
|
fi
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return:
|
|
type: error
|
|
message: "Failed to create SFTP user ${globals.username}. Error details: ${response.out}"
|
|
- setGlobals:
|
|
username: ${globals.username}
|
|
password: ${globals.password}
|
|
- return:
|
|
type: info
|
|
message: "Connection Details\n\nSFTP Host: ${globals.sftpHost}\n\nPort: ${globals.sftpPort}\n\nLogin Credentials\n\nUsername: ${globals.username}\n\nPassword: ${globals.password}\n\nNotes:\n- Files are accessible at /data/ROOT inside your SFTP session\n- If you enabled SSH access, you can also log in via SSH"
|
|
change_password:
|
|
# Verify user exists
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create log file for this run
|
|
LOG_FILE="/opt/add-sftp-user-addon/logs/password_change.log"
|
|
touch "$LOG_FILE"
|
|
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
# Log start of process
|
|
log "======== STARTING PASSWORD CHANGE ========"
|
|
log "Verifying user exists: ${settings.manage_username}"
|
|
|
|
# Check if user exists
|
|
if id ${settings.manage_username} &>/dev/null; then
|
|
log "User ${settings.manage_username} exists"
|
|
exit 0
|
|
else
|
|
log_error "User ${settings.manage_username} does not exist"
|
|
echo "User does not exist"
|
|
exit 1
|
|
fi
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return:
|
|
type: error
|
|
message: "User ${settings.manage_username} does not exist."
|
|
|
|
# Use custom password if provided, otherwise generate one
|
|
- if ('${settings.custom_password}' != ''):
|
|
setGlobals:
|
|
password: ${settings.custom_password}
|
|
- if ('${settings.custom_password}' == ''):
|
|
setGlobals:
|
|
password: ${fn.password(12)}
|
|
|
|
# Update password
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
log "Changing password for user: ${settings.manage_username}"
|
|
|
|
# Change password using echo and chpasswd
|
|
if echo "${settings.manage_username}:${globals.password}" | /usr/sbin/chpasswd; then
|
|
log_success "Password changed successfully for ${settings.manage_username}"
|
|
echo "Password changed for ${settings.manage_username} at $(date)" >> /opt/add-sftp-user-addon/logs/script_output.log
|
|
exit 0
|
|
else
|
|
log_error "Failed to change password for ${settings.manage_username}"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "======== PASSWORD CHANGE COMPLETED ========"
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return: passwordChangeError
|
|
- return: passwordChangeSuccess
|
|
delete_user:
|
|
# Verify user exists first
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create log file for this run
|
|
LOG_FILE="/opt/add-sftp-user-addon/logs/user_deletion.log"
|
|
touch "$LOG_FILE"
|
|
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
# Log start of process
|
|
log "======== STARTING USER DELETION ========"
|
|
log "Verifying user exists: ${settings.manage_username}"
|
|
|
|
# Check if user exists
|
|
if id ${settings.manage_username} &>/dev/null; then
|
|
log "User ${settings.manage_username} exists"
|
|
exit 0
|
|
else
|
|
log_error "User ${settings.manage_username} does not exist"
|
|
echo "User does not exist"
|
|
exit 1
|
|
fi
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return:
|
|
type: error
|
|
message: "User ${settings.manage_username} does not exist."
|
|
|
|
# Check if user is in sftpusers directory
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
log "Checking home directory for: ${settings.manage_username}"
|
|
|
|
if test -d /home/sftpusers/${settings.manage_username}; then
|
|
log "Home directory found: /home/sftpusers/${settings.manage_username}"
|
|
exit 0
|
|
else
|
|
log_error "Home directory not found for user: ${settings.manage_username}"
|
|
echo "User home directory not found"
|
|
exit 1
|
|
fi
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return:
|
|
type: error
|
|
message: "User ${settings.manage_username} exists but their home directory was not found."
|
|
|
|
# Perform deletion
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
log "Starting deletion of user: ${settings.manage_username}"
|
|
|
|
# First unmount any bind mounts
|
|
if mount | grep -q "/home/sftpusers/${settings.manage_username}/data/ROOT"; then
|
|
log "Unmounting bind mount for user: ${settings.manage_username}"
|
|
umount /home/sftpusers/${settings.manage_username}/data/ROOT
|
|
fi
|
|
|
|
# Remove from fstab
|
|
if grep -q "/home/sftpusers/${settings.manage_username}/data/ROOT" /etc/fstab; then
|
|
log "Removing bind mount from fstab for user: ${settings.manage_username}"
|
|
sed -i "\|/home/sftpusers/${settings.manage_username}/data/ROOT|d" /etc/fstab
|
|
fi
|
|
|
|
# Unmount shell template if mounted
|
|
if mount | grep -q "/home/sftpusers/${settings.manage_username}/shell"; then
|
|
log "Unmounting shell bind mount for user: ${settings.manage_username}"
|
|
umount /home/sftpusers/${settings.manage_username}/shell
|
|
fi
|
|
|
|
# Remove shell mount from fstab
|
|
if grep -q "/home/sftpusers/${settings.manage_username}/shell" /etc/fstab; then
|
|
log "Removing shell bind mount from fstab for user: ${settings.manage_username}"
|
|
sed -i "\|/home/sftpusers/${settings.manage_username}/shell|d" /etc/fstab
|
|
fi
|
|
|
|
# Delete user account
|
|
if userdel ${settings.manage_username}; then
|
|
log_success "User account deleted: ${settings.manage_username}"
|
|
else
|
|
log_error "Failed to delete user account: ${settings.manage_username}"
|
|
exit 1
|
|
fi
|
|
|
|
# Remove home directory
|
|
if rm -rf /home/sftpusers/${settings.manage_username}; then
|
|
log_success "Home directory removed: /home/sftpusers/${settings.manage_username}"
|
|
else
|
|
log_warning "Failed to remove home directory for: ${settings.manage_username}"
|
|
fi
|
|
|
|
log_success "======== USER DELETION COMPLETED ========"
|
|
exit 0
|
|
- if ("${response.exitStatus}" != "0"):
|
|
return: deleteUserError
|
|
- return: deleteUserSuccess
|
|
list_users:
|
|
- cmd[cp]:
|
|
user: root
|
|
commands: |-
|
|
# Create log file for this run
|
|
LOG_FILE="/opt/add-sftp-user-addon/logs/list_users.log"
|
|
touch "$LOG_FILE"
|
|
|
|
# Source the logging helper
|
|
source /opt/add-sftp-user-addon/scripts/logging.sh
|
|
|
|
# Log start of process
|
|
log "======== LISTING SFTP USERS ========"
|
|
log "Retrieving list of SFTP users"
|
|
|
|
# List users without logging to stdout - only return the clean list
|
|
USERS_LIST=$(ls -ld /home/sftpusers/* 2>/dev/null | grep -v "total" | awk '{printf "Username: %s - Created: %s %s %s\n", substr($9, 17), $6, $7, $8}')
|
|
|
|
# Check if any users were found
|
|
if [ -z "$USERS_LIST" ]; then
|
|
log_warning "No SFTP users found"
|
|
log "======== USER LISTING COMPLETED ========"
|
|
echo ""
|
|
else
|
|
log_success "Retrieved list of SFTP users"
|
|
log_debug "Found users: $(echo "$USERS_LIST" | wc -l)"
|
|
log "======== USER LISTING COMPLETED ========"
|
|
echo "$USERS_LIST"
|
|
fi
|
|
- if ("${response.exitStatus}" != "0" || "${response.out}" == ""):
|
|
return:
|
|
type: warning
|
|
message: "No SFTP users found. Use the Add SFTP/SSH User button to create one."
|
|
- return: listUsers
|
|
|
|
responses:
|
|
installSuccess:
|
|
type: success
|
|
message: "Add SFTP User addon installed successfully for Jelastic Virtuozzo LLSMP"
|
|
sftpError:
|
|
type: error
|
|
message: "Failed to add SFTP user. Please check the server logs for more details."
|
|
sftpSuccess:
|
|
type: success
|
|
message: "Connection Details\n\nSFTP Host: ${globals.sftpHost}\n\nPort: ${globals.sftpPort}\n\nLogin Credentials\n\nUsername: ${globals.username}\n\nPassword: ${globals.password}"
|
|
passwordChangeError:
|
|
type: error
|
|
message: "Failed to change password for ${settings.manage_username}. Check logs for details."
|
|
passwordChangeSuccess:
|
|
type: success
|
|
message: "Password changed successfully for ${settings.manage_username}.\n\n New password: ${globals.password}"
|
|
deleteUserError:
|
|
type: error
|
|
message: "Failed to delete user ${settings.manage_username}. Check logs for details."
|
|
deleteUserSuccess:
|
|
type: success
|
|
message: "User ${settings.manage_username} deleted successfully."
|
|
noUsersFound:
|
|
type: error
|
|
message: "No SFTP users have been created yet."
|
|
listUsers:
|
|
type: info
|
|
message: "${response.out}"
|
|
|
|
buttons:
|
|
- settings: sfpform
|
|
action: add_sftp_user
|
|
caption: Add SFTP/SSH User
|
|
confirmText: "Are you sure you want to add this SFTP user?"
|
|
submitButtonText: Add User
|
|
- settings: manageUserForm
|
|
action: change_password
|
|
caption: Change Password
|
|
confirmText: "Are you sure you want to change the password for this user?"
|
|
submitButtonText: Change Password
|
|
- settings: deleteUserForm
|
|
action: delete_user
|
|
caption: Delete User
|
|
confirmText: "Are you sure you want to delete this user? This action cannot be undone."
|
|
submitButtonText: Delete User
|
|
|
|
onUninstall:
|
|
- cmd[cp]:
|
|
user: root
|
|
commands:
|
|
- rm -rf /opt/add-sftp-user-addon/ |