Password Self-Service¶
On the login node.
SLURM users can't use the standard passwd command, since their accounts exist only in LDAP, not the local system password database. spasswd is a custom self-service tool that lets slurm_-prefixed accounts update their own LDAP password securely — it uses ldappasswd with current-password verification and a confirmation prompt.
Not yet in Scripts/
Every other admin tool in this guide lives in User Management/Scripts/ and is linked from its doc page. spasswd is the one exception — it currently only exists as the inline script below. Recommend moving it into Scripts/spasswd for consistency (an inline ~85-line script in a markdown page is exactly the kind of content that silently drifts from what's actually deployed). This is a repo change beyond a docs edit — happy to do it as a quick follow-up if you'd like.
Path: /usr/local/bin/spasswd
#!/usr/bin/env python3
import getpass
import sys
import os
def main():
# Get the actual username (not the stripped version)
actual_username = os.getenv('USER', '')
# Check if username starts with slurm_
if not actual_username.startswith('slurm_'):
print("Error: This tool is only available for SLURM users (slurm_ accounts)")
print(f"Your username '{actual_username}' is not authorized to use this tool")
sys.exit(1)
# Remove slurm_ prefix for LDAP operations
ldap_username = actual_username.replace('slurm_', '', 1)
print("=== SLURM Password Change ===")
print(f"Changing password for: {ldap_username}")
print()
try:
# Get passwords with custom prompts
new_pass = getpass.getpass("Enter new password: ")
confirm_pass = getpass.getpass("Confirm new password: ")
if new_pass != confirm_pass:
print("✗ Passwords don't match!")
sys.exit(1)
current_pass = getpass.getpass("Enter current password: ")
# Build ldappasswd command
import subprocess
import shlex
# Build the ldappasswd command with proper escaping
ldap_cmd = [
'ldappasswd',
'-x',
'-D', f'cn={ldap_username},ou=People,dc=jrcai,dc=lan',
'-w', current_pass,
'-s', new_pass,
'-H', 'ldap://server02.jrcai.lan',
'-ZZ'
]
# Join the command with proper shell escaping
ldap_cmd_str = ' '.join(shlex.quote(arg) for arg in ldap_cmd)
# Properly initialize conda and deactivate before running ldappasswd
full_cmd = f'''
if [ -n "$CONDA_EXE" ]; then
eval "$($CONDA_EXE shell.bash hook 2>/dev/null)" || true
conda deactivate 2>/dev/null || true
fi
{ldap_cmd_str}
'''
# Execute command
result = subprocess.run(['bash', '-c', full_cmd], capture_output=True, text=True)
if result.returncode == 0:
print("✓ Password changed successfully!")
else:
print("✗ Password change failed!")
print(f" Return code: {result.returncode}")
print(f" STDERR: {result.stderr}")
if "Invalid credentials" in result.stderr:
print(" Please check your current password.")
except KeyboardInterrupt:
print("\nOperation cancelled.")
sys.exit(1)
except Exception as e:
print(f"✗ Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Allow execution: