Baeldung Pro – Linux – NPI EA (cat = Baeldung on Linux)
announcement - icon

Learn through the super-clean Baeldung Pro experience:

>> Membership and Baeldung Pro.

No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.

Partner – Orkes – NPI EA (tag=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

1. Overview

Secure Shell (SSH) and Secure Copy Protocol (SCP) are commonly used tools for secure remote access and file transfer in Linux environments. Automating these tasks using Python’s subprocess.Popen can be helpful in scenarios where password authentication is required.

In this tutorial, we’ll learn how to securely send a password using subprocess.Popen while avoiding common security pitfalls.

2. Understanding subprocess.Popen

The subprocess module in Python enables us to spawn new processes, connect to their input, output, and error pipes, and obtain their return codes. The Popen class is particularly useful for interacting with processes programmatically.

Here’s a basic example to run an SSH command using subprocess.Popen:

import subprocess

process = subprocess.Popen([
    'ssh', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout, stderr = process.communicate()
print(stdout.decode())

This approach works well when using SSH keys for authentication. If password authentication is needed, subprocess.Popen doesn’t support sending it securely by default.

3. Why Sending Passwords Directly Is Risky

Passing passwords via standard input or command-line arguments introduces several risks:

  • Passwords may appear in the shell history
  • Passwords could be exposed through process listing (e.g., ps aux)
  • Automation scripts might inadvertently log them

Tools such as sshpass or pexpect help reduce these risks effectively.

4. Using sshpass With subprocess.Popen

sshpass is a utility that allows non-interactive SSH authentication by passing a password via a command-line argument or standard input.

4.1. Installing sshpass

Let’s install sshpass using the system’s package manager:

$ sudo apt install sshpass         # Debian-based systems
$ sudo yum install sshpass         # RHEL-based systems

Once installed, we can use it to invoke SSH commands.

4.2. Using sshpass With subprocess.Popen

Let’s use sshpass to run an SSH command from Python:

import subprocess

password = "your_password"
command = [
    'sshpass', '-p', password, 'ssh', 'user@remote_host', 'ls'
]

process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode())

Although the code works, there are security concerns to be aware of.

4.3. Security Considerations

While sshpass helps with automation, there are notable concerns:

  • sshpass exposes the password in the process list
  • Logs and history may retain the password
  • Employing sshpass isn’t recommended for production use

These concerns make sshpass less ideal for secure environments. Let’s look at a more secure alternative.

5. Using pexpect for Secure Password Handling

pexpect simulates user interaction, allowing secure password entry and improved automation handling.

5.1. Installing pexpect

Let’s install pexpect using pip:

$ pip install pexpect

With pexpect ready, let’s automate SSH connections more securely.

5.2. Using pexpect for SSH

The following example demonstrates how to automate SSH login using pexpect:

import pexpect

user = "user"
host = "remote_host"
password = "your_password"
command = "ls"

ssh_command = f"ssh {user}@{host} {command}"
child = pexpect.spawn(ssh_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())

Let’s extend the same approach to handle file transfers.

5.3. Using pexpect for SCP

We can automate SCP transfers securely using pexpect:

import pexpect

user = "user"
host = "remote_host"
password = "your_password"
local_file = "file.txt"
remote_path = "/home/user/file.txt"

scp_command = f"scp {local_file} {user}@{host}:{remote_path}"
child = pexpect.spawn(scp_command)
child.expect("password:")
child.sendline(password)
child.expect(pexpect.EOF)
print(child.before.decode())

Aside from convenience, pexpect improves the overall security posture.

5.4. Security Benefits

Using pexpect offers several security benefits:

  • The password doesn’t appear in the command history or process list
  • Better interaction control for automation
  • More secure than sshpass

These advantages make pexpect a preferable option for password-based automation.

6. Best Practices for Secure SSH Automation

Although password authentication can be automated, it’s usually better to use SSH keys for stronger security. Let’s walk through setting up SSH key authentication.

6.1. Generating SSH Keys

To create a new key pair, let’s use the ssh-keygen command:

$ ssh-keygen -t rsa -b 4096

Once the keys are generated, we place the public key on the remote system.

6.2. Copying the Public Key to the Remote Host

Let’s copy the public key to the remote host:

$ ssh-copy-id user@remote_host

Now, we can use key-based authentication in our Python script.

6.3. Using SSH Keys in Python

Once the SSH key is in place, let’s use it in Python:

import subprocess

process = subprocess.Popen([
    'ssh', '-i', '/path/to/private_key', 'user@remote_host', 'ls'
], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout, stderr = process.communicate()
print(stdout.decode())

SSH keys provide a more secure and efficient way to automate authentication in Python.

7. Conclusion

In this article, we saw how automating SSH and SCP operations using subprocess.Popen is possible but involves security challenges when passwords are required. Tools like pexpect offer a safer alternative to sshpass. However, using SSH keys remains the most secure and efficient method. By following these best practices, we can build robust and secure automation workflows.