How to give celery enough permission to run a root file without compromising security?

Viewed 175

I'm running the code below as part of a Celery task.

class HealthCheckIKEV2:
    async def report(self):
        try:
            client = RedisClient()
            proc1 = subprocess.Popen(
                ["sudo", "/usr/sbin/swanctl", "--list-sas"], stdout=subprocess.PIPE
            )
            proc2 = subprocess.Popen(
                ["grep", "INSTALLED"],
                stdin=proc1.stdout,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
            )
            proc3 = subprocess.Popen(
                ["wc", "-l"],
                stdin=proc2.stdout,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True,
            )
            proc1.stdout.close()  # Allow proc1 to receive a SIGPIPE if proc2 exits.
            proc2.stdout.close()  # Allow proc2 to receive a SIGPIPE if proc3 exits.
            out, err = proc3.communicate()
            info = {
                "users": out.rstrip(),
                "timestamp": datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
            }
            client.conn.hset(settings.REDIS_VPN_SUBDOMAIN, mapping=info)

However Celery fails with the following error message:

Jun 13 08:46:42 de-vpn-1 sudo[2038]:   celery : user NOT in sudoers ; TTY=unknown ; PWD=/home/admin/app ; USER=root ; COMMAND=/usr/sbin/swanctl --list-sas
Jun 13 08:47:42 de-vpn-1 sudo[2045]: pam_unix(sudo:auth): conversation failed

This is because of this line where the subprocess has to run as sudo to be able to execute /usr/sbin/swanctl.

proc1 = subprocess.Popen(
                ["sudo", "/usr/sbin/swanctl", "--list-sas"], stdout=subprocess.PIPE
            )

What are my options here? Celery documentation says to not give the celery user root access. What can I do to adhere to best practices and yet get this task executed successfully?

One idea I had was to create a new group and add both root and celery users to that group. And change the permission of that file to that group. Sounds a bit hacky though. Thanks.

2 Answers

I would add the celery user to the sudoers file with the only command allowed being the one needed. Use visudo and add these lines

celery all = (root) NOPASSWD: /usr/sbin/swanctl --list-sas

The NOPASSWD: directive insures linux will not ask for a password.

Note: this gives anyone who can control this user this level of access

I would simply set the setuid flag on /usr/sbin/swanctl and then run it from Celery without the need for sudo.

Related