Switch user in Gitlab Runner?

Hello,

I am very new to GitLab and struggling with the CI script I’m writing. I’m using a shell executor and the main idea is to deploy the content of the Git repo to a specific location on the server by either git clone, or git pull. Since the script is being executed with the gitlab-runner user, but the files need to be placed into some other users’ home directory, the gitlab-runner user is in sudoers and I want to execute the following command:

sudo su newuser or sudo -i

And I am not getting an error, but when I do whoami, the current user is still gitlab-runner.

So, my question is how can I change the user dynamically in the CI script, as not all commands work well with sudo and that’s causing me other issues.

To clarify, I need it switched to a different user everytime, so changing the runner config is not an option. The easiest way would be to execute the CI script as root, but that doesn’t sound right.

I’m doing this on a self-hosted GitLab if that matters.

Thank you!

2 Likes

Hi @georgiharbinger

There are probably different ways of doing this. A simple one is to use visudo to allow gitlab-runner to execute specific commands. The commands will need full paths, but you might have something like:

gitlab-runner ALL=NOPASSWD: cp FILES /home/user/dir

or, better still, write a script, so that you have a version-controlled record of the commands that are run on the server:

gitlab-runner ALL=NOPASSWD: /tmp/move-files.sh

In the example above, the .gitlab-ci.yml file would do something like this:

job:
    script:
        - cp bin/move-files.sh /tmp/
        - sudo /tmp/move-files.sh

so that visudo can have a full path to move-files.sh, regardless of where the runner clones your repo.

You can find a bit more about visudo here.

2 Likes

Hi @snim2 and thank you for your reply!

Could you please share some of the other ways of doing this too? I’m thinking that some of the other ways might be a better fit to what I’m trying to do.

Do you know if changing the user in the CI script is forbidden due some protection in GitLab itself, or I’m doing something wrong? Because it kind of doesn’t make sense for it not to work.

Currently the line in my sudoers file is:

gitlab-runner ALL=(ALL) NOPASSWD:ALL

That line won’t work because you haven’t given visudo a command for gitlab-runner to run.

It is forbidden (or should be!) in your operating system for one user to “pretend” to be another, without root privileges. Otherwise, a user could log on and change all the files and so on that belong to another user. This isn’t something specific to gitlab-runner.

You may well be tempted to do this:

gitlab-runner ALL=(ALL) NOPASSWD:ALL su another-user

I would advise against it, because you are giving gitlab-runner permission to run /any/ command as another-user, and if somehow someone breached your security, and ran their own scripts on your machine, they would have a lot of scope to do damage.

Probably, you have a situation where you want to deploy a web app to a web server, your web server will (by design) have limited privileges, and it’s important not to change that, as any web server is a potential vector of attack.

What I would suggest, as good practice (I won’t say best practice, someone may well have better ideas) is:

  1. You run the smallest possible set of commands with special privileges
  2. Anything you run in gitlab-runner that needs visudo should be checked into version control. So, either you have commands in .gitlab-ci.yml or .gitlab-ci.yml calls a script that’s in your repo. That means that if you see a pipeline somewhere has messed something up, you can look at the timestamp and see what code was run, even if it’s been deleted from the server.
  3. Wherever possible, it makes sense to do as much of your deployment as possible as gitlab-runner with normal permissions, and then only use commands in visudo right at the end of the deployment. That way, if anything goes wrong in the middle, any problems will have caused you the least possible amount of damage, and you won’t need to roll back a live deployment.

I do realise this makes setting up a good deployment pipeline a bit trickier, and it’s a bit more work. Hopefully, in the long term more caution now will mean fewer bug fixes and maintenance jobs.

1 Like