DEV Community

Janak Shrestha
Janak Shrestha

Posted on

Linux SSH Authentication

The system admins team of xFusionCorp Industries has set up some scripts on jump host that run on regular intervals and perform operations on all app servers in Stratos Datacenter. To make these scripts work properly we need to make sure the thor user on jump host has password-less SSH access to all app servers through their respective sudo users (i.e tony for app server 1). Based on the requirements, perform the following:

Set up a password-less authentication from user thor on jump host to all app servers through their respective sudo users.


1. Understanding SSH Authentication

What is SSH?

SSH (Secure Shell) is a cryptographic network protocol used for secure remote access to servers. It provides encrypted communication between two systems.

SSH Authentication Methods

Method Description Security Level
Password User enters password each time Medium
Public Key Cryptographic key pair for authentication High
Host-based Trust based on host identity Low
Keyboard-interactive Challenge-response authentication Medium

Why Password-less SSH?

Benefit Description
Automation Enables scripts to run without human intervention
Convenience No need to remember or type passwords
Security Uses strong cryptographic keys instead of passwords
Efficiency Faster access to multiple servers
Integration Works with automation tools (Ansible, Puppet, etc.)

How SSH Key Authentication Works

┌─────────────────┐     ┌─────────────────┐
│   Client (Jump  │     │   Server (App   │
│      Host)      │     │     Server)     │
│                 │     │                 │
│  Private Key    │────▶│  Public Key     │
│  (id_rsa)       │     │  (authorized)   │
│                 │     │                 │
└─────────────────┘     └─────────────────┘
Enter fullscreen mode Exit fullscreen mode
  1. Client sends a request to the server
  2. Server sends a challenge encrypted with the public key
  3. Client decrypts the challenge with the private key
  4. Server verifies the decryption
  5. Connection is established without a password

2. Understanding Sudo Access

What is Sudo?

Sudo (Superuser DO) allows authorized users to execute commands with elevated privileges (as root or another user).

Sudo Authentication

By default, sudo prompts for the user's password before executing privileged commands. This can be bypassed by configuring NOPASSWD in the sudoers file.

Why Password-less Sudo?

Benefit Description
Automation Scripts can run privileged commands without prompting
Headless Operation No terminal needed for password input
Consistency Prevents failed commands due to password prompts
CI/CD Integration Essential for deployment pipelines

Sudoers File Locations

Location Purpose
/etc/sudoers Main sudo configuration file
/etc/sudoers.d/ Directory for individual configuration files
/etc/sudoers.d/username User-specific sudo rules

3. Prerequisites

Before You Begin

  • SSH access to the jump host and all target servers
  • Passwords for all server user accounts
  • Sudo privileges on target servers
  • OpenSSH client installed

Server Details for This Tutorial

Server User Password Purpose
jump-host thor mjolnir123 Jump/Bastion host
stapp01 tony Ir0nM@n Application Server 1
stapp02 steve Am3ric@ Application Server 2
stapp03 banner BigGr33n Application Server 3

4. Step 1: Generate SSH Key Pair

Connect to Jump Host

# Connect to the jump host
ssh thor@jump-host
# Password: mjolnir123
Enter fullscreen mode Exit fullscreen mode

Check for Existing SSH Keys

# Check if SSH keys already exist
ls -la ~/.ssh/id_rsa*

# If files exist, you can either use them or generate new ones
Enter fullscreen mode Exit fullscreen mode

Generate a New SSH Key Pair

# Generate RSA key pair (4096-bit for security)
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
Enter fullscreen mode Exit fullscreen mode

Command Breakdown:

Option Description
-t rsa Use RSA encryption algorithm
-b 4096 Use 4096-bit key length (more secure than 2048)
-N "" No passphrase (for automation)
-f ~/.ssh/id_rsa Save to default location

Expected Output:

Generating public/private rsa key pair.
Your identification has been saved in /home/thor/.ssh/id_rsa
Your public key has been saved in /home/thor/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:TijFO2sEaH98fh4JD2JIT+M1+4IJYOtzky5TSJn9heI thor@jump-host
The key's randomart image is:
+---[RSA 4096]----+
|                 |
|   . .           |
|  =+o =.o        |
| o+=oO.=.o       |
| ..o=o%.S        |
| .. EB.@ = .     |
|  o.+ = + *      |
|  o+ o   + .     |
|   o.     .      |
+----[SHA256]-----+
Enter fullscreen mode Exit fullscreen mode

Verify the Keys

# View the private key
ls -la ~/.ssh/id_rsa
# -rw------- 1 thor thor 3381 Sep 3 10:00 /home/thor/.ssh/id_rsa

# View the public key
cat ~/.ssh/id_rsa.pub
# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC... thor@jump-host
Enter fullscreen mode Exit fullscreen mode

5. Step 2: Copy SSH Public Key to Servers

Method 1: Using ssh-copy-id (Recommended)

# Copy key to App Server 1 (tony)
ssh-copy-id tony@stapp01
# Password: Ir0nM@n

# Copy key to App Server 2 (steve)
ssh-copy-id steve@stapp02
# Password: Am3ric@

# Copy key to App Server 3 (banner)
ssh-copy-id banner@stapp03
# Password: BigGr33n
Enter fullscreen mode Exit fullscreen mode

Expected Output:

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/thor/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
tony@stapp01's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'tony@stapp01'"
and check to make sure that only the key(s) you wanted were added.
Enter fullscreen mode Exit fullscreen mode

Method 2: Manual Key Copy

# If ssh-copy-id is not available
cat ~/.ssh/id_rsa.pub | ssh tony@stapp01 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Enter fullscreen mode Exit fullscreen mode

Method 3: Using SCP

# Copy the public key to the server
scp ~/.ssh/id_rsa.pub tony@stapp01:/tmp/

# Add the key to authorized_keys
ssh tony@stapp01 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat /tmp/id_rsa.pub >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && rm /tmp/id_rsa.pub"
Enter fullscreen mode Exit fullscreen mode

Verify Password-less SSH Access

# Test each server (should not prompt for password)
ssh tony@stapp01 "hostname"
ssh steve@stapp02 "hostname"
ssh banner@stapp03 "hostname"
Enter fullscreen mode Exit fullscreen mode

Expected Output:

stapp01
stapp02
stapp03
Enter fullscreen mode Exit fullscreen mode

6. Step 3: Configure Password-less Sudo

Even with password-less SSH, sudo still prompts for a password by default. We need to configure NOPASSWD in the sudoers file.

Method 1: Using sudoers.d Directory (Recommended)

App Server 1 (stapp01):

ssh tony@stapp01 << 'EOF'
echo 'Ir0nM@n' | sudo -S bash -c '
echo "tony ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/tony
chmod 440 /etc/sudoers.d/tony
echo "✓ sudo NOPASSWD configured for tony"
'
EOF
Enter fullscreen mode Exit fullscreen mode

App Server 2 (stapp02):

ssh steve@stapp02 << 'EOF'
echo 'Am3ric@' | sudo -S bash -c '
echo "steve ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/steve
chmod 440 /etc/sudoers.d/steve
echo "✓ sudo NOPASSWD configured for steve"
'
EOF
Enter fullscreen mode Exit fullscreen mode

App Server 3 (stapp03):

ssh banner@stapp03 << 'EOF'
echo 'BigGr33n' | sudo -S bash -c '
echo "banner ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/banner
chmod 440 /etc/sudoers.d/banner
echo "✓ sudo NOPASSWD configured for banner"
'
EOF
Enter fullscreen mode Exit fullscreen mode

Method 2: Using visudo (Interactive)

# Connect to each server
ssh tony@stapp01

# Edit sudoers file
sudo visudo

# Add this line at the end:
tony ALL=(ALL) NOPASSWD: ALL

# Save and exit
# Repeat for steve@stapp02 and banner@stapp03
Enter fullscreen mode Exit fullscreen mode

Method 3: Using visudo with a Separate File

# Create a separate file and include it
ssh tony@stapp01 "sudo bash -c 'echo \"tony ALL=(ALL) NOPASSWD: ALL\" > /etc/sudoers.d/tony'"
Enter fullscreen mode Exit fullscreen mode

Verify Sudo Access

# Test sudo (should not prompt for password)
ssh tony@stapp01 "sudo whoami"
ssh steve@stapp02 "sudo whoami"
ssh banner@stapp03 "sudo whoami"
Enter fullscreen mode Exit fullscreen mode

Expected Output:

root
root
root
Enter fullscreen mode Exit fullscreen mode

7. Step 4: Verification and Testing

Complete Verification Script

#!/bin/bash

echo "========================================="
echo "Verifying SSH and Sudo Configuration"
echo "========================================="

# Define servers
SERVERS=("stapp01:tony" "stapp02:steve" "stapp03:banner")

for server_info in "${SERVERS[@]}"; do
    IFS=':' read -r server user <<< "$server_info"
    echo ""
    echo "=== Testing $server (User: $user) ==="

    # Test SSH connection
    echo "SSH connection:"
    ssh -o ConnectTimeout=5 "$user@$server" "echo ✓ Connected to $server" 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "  ✓ SSH password-less working"
    else
        echo "  ✗ SSH password-less failed"
    fi

    # Test sudo access
    echo "Sudo access:"
    ssh "$user@$server" "sudo whoami" 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "  ✓ Sudo NOPASSWD working"
    else
        echo "  ✗ Sudo NOPASSWD failed"
    fi

    # Check sudoers file
    echo "Sudoers file:"
    ssh "$user@$server" "cat /etc/sudoers.d/$user 2>/dev/null || echo '  Not found'"
done

echo ""
echo "========================================="
echo "✅ Verification complete!"
echo "========================================="
Enter fullscreen mode Exit fullscreen mode

Quick Verification Commands

# Test all servers
for server in stapp01 stapp02 stapp03; do
    echo "=== $server ==="
    ssh tony@$server "hostname && sudo whoami"
done
Enter fullscreen mode Exit fullscreen mode

Detailed Verification

# 1. Check SSH key
ssh tony@stapp01 "ls -la ~/.ssh/authorized_keys"

# 2. Check sudoers file
ssh tony@stapp01 "cat /etc/sudoers.d/tony 2>/dev/null"

# 3. Check sudo configuration
ssh tony@stapp01 "sudo -l"

# 4. Test command execution
ssh tony@stapp01 "sudo yum update -y --assumeno" 2>/dev/null
Enter fullscreen mode Exit fullscreen mode

8. Automated Deployment Scripts

Complete Bash Script

#!/bin/bash

echo "========================================="
echo "Setting Up Password-less SSH and Sudo"
echo "========================================="

# Server configuration
declare -A SERVERS=(
    ["stapp01"]="tony:Ir0nM@n"
    ["stapp02"]="steve:Am3ric@"
    ["stapp03"]="banner:BigGr33n"
)

# Generate SSH key if not exists
echo ""
echo "=== SSH Key Generation ==="
if [ ! -f ~/.ssh/id_rsa ]; then
    ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
    echo "✓ SSH key generated"
else
    echo "✓ SSH key already exists"
fi

echo ""
echo "Public Key:"
cat ~/.ssh/id_rsa.pub
echo ""

# Copy SSH keys and configure sudo
for server in "${!SERVERS[@]}"; do
    IFS=':' read -r user pass <<< "${SERVERS[$server]}"
    echo "========================================="
    echo "Configuring $server (User: $user)"
    echo "========================================="

    # Step 1: Copy SSH key
    echo "Copying SSH key..."
    sshpass -p "$pass" ssh-copy-id -o StrictHostKeyChecking=no "$user@$server" 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✓ SSH key copied"
    else
        echo "❌ Failed to copy SSH key"
        continue
    fi

    # Step 2: Verify SSH access
    echo "Verifying SSH access..."
    ssh -o StrictHostKeyChecking=no "$user@$server" "hostname" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "✓ SSH password-less working"
    else
        echo "❌ SSH password-less failed"
        continue
    fi

    # Step 3: Configure sudo NOPASSWD
    echo "Configuring sudo NOPASSWD..."
    echo "$pass" | ssh -o StrictHostKeyChecking=no "$user@$server" "sudo -S bash -c 'echo \"$user ALL=(ALL) NOPASSWD: ALL\" > /etc/sudoers.d/$user && chmod 440 /etc/sudoers.d/$user'"

    # Step 4: Verify sudo
    echo "Verifying sudo access..."
    ssh "$user@$server" "sudo whoami" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "✓ Sudo NOPASSWD working"
    else
        echo "❌ Sudo NOPASSWD failed"
    fi

    echo ""
done

echo "========================================="
echo "✅ Configuration complete!"
echo "========================================="
echo ""
echo "Verification:"
for server in "${!SERVERS[@]}"; do
    IFS=':' read -r user _ <<< "${SERVERS[$server]}"
    echo "  ssh $user@$server 'sudo whoami'"
done
Enter fullscreen mode Exit fullscreen mode

Using the Script

# Save the script
nano setup_ssh_sudo.sh

# Make it executable
chmod +x setup_ssh_sudo.sh

# Run the script
./setup_ssh_sudo.sh
Enter fullscreen mode Exit fullscreen mode

9. Troubleshooting Common Issues

Issue 1: "Permission denied (publickey,password)"

Problem: SSH key authentication fails.

Solutions:

# Check if key is added to authorized_keys
ssh tony@stapp01 "cat ~/.ssh/authorized_keys"

# Manually add the key
cat ~/.ssh/id_rsa.pub | ssh tony@stapp01 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Check SSH daemon configuration
ssh tony@stapp01 "grep PubkeyAuthentication /etc/ssh/sshd_config"
# Should be: PubkeyAuthentication yes

# Restart SSH daemon
ssh tony@stapp01 "sudo systemctl restart sshd"
Enter fullscreen mode Exit fullscreen mode

Issue 2: "sudo: a password is required"

Problem: Sudo still asks for password.

Solutions:

# Check if sudoers file exists
ssh tony@stapp01 "ls -la /etc/sudoers.d/"

# Check contents
ssh tony@stapp01 "cat /etc/sudoers.d/tony"

# Create with correct syntax
ssh tony@stapp01 "echo 'tony ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/tony"

# Check sudoers syntax
ssh tony@stapp01 "visudo -c"
Enter fullscreen mode Exit fullscreen mode

Issue 3: "Host key verification failed"

Problem: SSH doesn't recognize the host.

Solution:

# Remove the host key
ssh-keygen -R stapp01

# Reconnect (will prompt to accept the key)
ssh tony@stapp01
Enter fullscreen mode Exit fullscreen mode

Issue 4: "ssh-copy-id: command not found"

Problem: The ssh-copy-id command is not available.

Solution (Manual method):

# Manual key copy
cat ~/.ssh/id_rsa.pub | ssh tony@stapp01 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Enter fullscreen mode Exit fullscreen mode

Issue 5: "sudo: no tty present"

Problem: Sudo requires a terminal.

Solution:

# Use -S flag with sudo
ssh tony@stapp01 "echo 'password' | sudo -S whoami"

# Or disable requiretty in sudoers
ssh tony@stapp01 "echo 'Defaults:tony !requiretty' | sudo tee /etc/sudoers.d/requiretty"
Enter fullscreen mode Exit fullscreen mode

Issue 6: "sshpass: command not found"

Problem: sshpass is not installed.

Solution:

# Install sshpass
sudo yum install -y sshpass
# or
sudo apt-get install -y sshpass

# Or use interactive method without sshpass
Enter fullscreen mode Exit fullscreen mode

10. Security Best Practices

1. Use Strong SSH Keys

# Use 4096-bit RSA keys (not 2048)
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa

# Or use Ed25519 (more secure and faster)
ssh-keygen -t ed25519 -N "" -f ~/.ssh/id_ed25519
Enter fullscreen mode Exit fullscreen mode

2. Restrict Key Access

# Add restrictions to authorized_keys
echo "from="192.168.1.*",command=\"/usr/bin/some-command\",no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keys
Enter fullscreen mode Exit fullscreen mode

3. Use Separate sudoers Files

# Create user-specific files in /etc/sudoers.d/
echo "username ALL=(ALL) NOPASSWD: /usr/bin/specific-command" > /etc/sudoers.d/username
chmod 440 /etc/sudoers.d/username
Enter fullscreen mode Exit fullscreen mode

4. Limit Sudo Commands

Instead of NOPASSWD: ALL, restrict to specific commands:

# Only allow specific commands
username ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/journalctl -u nginx

# Allow only specific users to sudo
username ALL=(username) NOPASSWD: ALL
Enter fullscreen mode Exit fullscreen mode

5. Regular Key Rotation

# Regularly rotate SSH keys (every 90 days)
# Generate new key
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa_new

# Copy to servers
ssh-copy-id -i ~/.ssh/id_rsa_new.pub tony@stapp01

# Remove old key from servers
Enter fullscreen mode Exit fullscreen mode

6. Monitor SSH Access

# Check SSH logs
tail -f /var/log/secure

# Monitor authorized_keys changes
auditctl -w /home/*/.ssh/authorized_keys -p wa -k authorized_keys
Enter fullscreen mode Exit fullscreen mode

7. Use a Jump Host (Bastion Host)

┌──────────┐    ┌──────────┐    ┌──────────┐
│  Client  │───▶│  Jump    │───▶│  App     │
│          │    │  Host    │    │  Server  │
└──────────┘    └──────────┘    └──────────┘
     │                │                │
     │   Only SSH     │   SSH + Sudo   │
     │   from client  │   from jump    │
     └────────────────┴────────────────┘
Enter fullscreen mode Exit fullscreen mode

11. Conclusion

What We've Accomplished

Task Command/Step Status
Generate SSH key pair ssh-keygen -t rsa -b 4096
Copy SSH key to servers ssh-copy-id user@server
Verify SSH access ssh user@server "hostname"
Configure sudo NOPASSWD echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/user
Verify sudo access ssh user@server "sudo whoami"
Create automation script setup_ssh_sudo.sh

Complete Solution Summary

# SSH Access (No Password)
ssh tony@stapp01    # Works without password prompt

# Sudo Access (No Password)
ssh tony@stapp01 "sudo whoami"    # Returns: root

# Run Commands on All Servers
for server in stapp01 stapp02 stapp03; do
    ssh tony@$server "sudo systemctl status nginx"
done

# Automation Scripts
# Scripts on jump host can now run on all app servers
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. SSH Keys provide secure, password-less authentication
  2. ssh-copy-id simplifies key distribution
  3. sudoers.d is the cleanest way to configure NOPASSWD
  4. Automation is now possible without password prompts
  5. Security should be maintained with key rotation and restrictions

Final Verification Commands

# Complete verification
echo "=== Testing All Servers ==="
for server in stapp01 stapp02 stapp03; do
    echo "=== $server ==="
    ssh tony@$server "hostname && sudo whoami"
done
Enter fullscreen mode Exit fullscreen mode

Expected Output:

=== Testing All Servers ===
=== stapp01 ===
stapp01
root
=== stapp02 ===
stapp02
root
=== stapp03 ===
stapp03
root
Enter fullscreen mode Exit fullscreen mode

Additional Resources

Manual Pages

man ssh-keygen    # SSH key generation
man ssh-copy-id   # Copy SSH keys
man sudoers       # Sudo configuration
man ssh           # SSH client
Enter fullscreen mode Exit fullscreen mode

Related Topics

  • SSH Agent: Forwarding keys for multi-hop connections
  • Ansible: Automation tool that uses password-less SSH
  • SSH Config: ~/.ssh/config for connection shortcuts
  • Firewall Rules: Allow SSH from specific IPs only

Automation Tools

Tool Purpose
Ansible Configuration management and automation
Puppet Infrastructure as code
Chef Automation platform
SaltStack Remote execution

Quick Reference Card

Commands Summary

Task Command
Generate SSH key ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa
Copy SSH key ssh-copy-id user@server
Test SSH ssh user@server "hostname"
Configure sudo NOPASSWD echo "user ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/user
Test sudo ssh user@server "sudo whoami"
Batch test for s in stapp01 stapp02 stapp03; do ssh tony@$s "hostname"; done

Top comments (0)