3
\$\begingroup\$

My first client-server application. It's a simple Python script that gets a list of running processes from Server_1 and writes it to a datetime-named file on Server_2, every 5 seconds.

I am planning on refactoring this code into one or two functions, maybe one for securing the connection and one for implementing the logic.

I also know nothing about security best-practices, and I'm looking for some pointers. Any feedback on any aspect of the code is welcome.


import os
import paramiko
from time import sleep
from datetime import datetime

SERVER_1 = os.getenv('HOST_1') or ""
SERVER_1_PASS = os.getenv('PASS_1') or ""
SERVER_2 = os.getenv('HOST_2') or ""
SERVER_2_PASS = os.getenv('PASS_2') or ""

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(SERVER_1, username='root', password=SERVER_1_PASS)

ssh2 = paramiko.SSHClient()
ssh2.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh2.connect(SERVER_2, username='root', password=SERVER_2_PASS)

while True:

    now = datetime.now()
    dt_string = now.strftime("%d-%m-%YT%H:%M:%S")

    stdin, stdout, stderr = ssh.exec_command("ps -aux")

    processes = stdout.readlines()
    output = [line.strip() for line in processes]

    ftp = ssh2.open_sftp()
    try:
        file = ftp.file(dt_string, "a", -1)
        file.write('\n'.join(output))
        file.flush()
        ftp.close()
    except IOError as e:
        print("Could not write to file")
        print(e)

    sleep(5)
```
\$\endgroup\$
2
  • \$\begingroup\$ Don't use root. Create another account that just has permissions to do these commands. Also, the loop will be 5 seconds plus the time to execute all the code. Maybe it doesn't matter. \$\endgroup\$
    – RootTwo
    Feb 25, 2021 at 8:05
  • \$\begingroup\$ @RootTwo does that mean create a new user and put them in a specific group, then modify the group privileges of the directory they operate in? Or what do you mean? Thanks \$\endgroup\$
    – Bn.F76
    Feb 27, 2021 at 23:51

1 Answer 1

1
\$\begingroup\$
SERVER_1_PASS = os.getenv('PASS_1') or ""
SERVER_2_PASS = os.getenv('PASS_2') or ""

I don't think it's a good idea to pass secrets in the environment - that's too easily read by other processes. Instead, prefer to hold them in a file that's accessible only by the user. Since we're using SSH, we even already have such a file ($HOME/.ssh/config), though a better choice would be to use public-key authentication.

ssh.connect(SERVER_1, username='root', password=SERVER_1_PASS)

Ouch - why to we need to connect as root? We should have a dedicated user for this, with the minimum level of capability to perform the task.

What does connect() do when SERVER_1 is the empty string (our default if not passed in environment)? Is that what we want, or should we error out in that case?

\$\endgroup\$
2
  • \$\begingroup\$ can you expand on having a "dedicated user"? I'm confused: do I create a new user and put them in a group and then modify the group's priviledges? Or do I modify group privildges on the directory I want the new user to work in? \$\endgroup\$
    – Bn.F76
    Feb 27, 2021 at 22:39
  • \$\begingroup\$ That's quite a broad topic to expand on (and maybe worth looking over on Information Security (and perhaps Unix & Linux) for ideas on how best to set up a user to run a particular task). Something you could do with SSH is permit only a particular command to be run, thus denying a login shell even to someone with the correct private key. \$\endgroup\$ Feb 28, 2021 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.