12

Using GitLab CI, I want to push production code to a remote webhost.

To connect with SSH, I am storing the key pair's private key in the variables of my GitLab repository. I've also copied the public key to the authorized keys of the server. This is (part of) my .gitlab-ci.yml.

image: ubuntu

before_script:
  # Setup SSH credentials and known host
  - which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )
  - mkdir -p ~/.ssh
  - echo "$SSH_PRIVATE" | tr -d '\r' > ~/.ssh/id_rsa
  - chmod 700 ~/.ssh/id_rsa
  - eval "$(ssh-agent -s)"
  - ssh-add ~/.ssh/id_rsa
  - echo "$SSH_KNOWN_HOSTS"
  - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts

This method works, but I'm questioning the security of it. Is my private key safe this way? How else can I achieve the result that I'm looking for?

EDIT: I'm particularly questioning the security of this method in a production environment.

Justin Praas
  • 183
  • 1
  • 1
  • 7

2 Answers2

1

The official example is in gitlab-examples/ssh-private-key

Its .gitlab-ci.yml uses a custom environment variable SSH_PRIVATE_KEY, as described in "How to simplify your smart home configuration with GitLab CI/CD / Preparing the server (and GitLab) for SSH access".

As long as that variable is masked, this should be secure enough.


sneaky suggests in the comments to create a pre-processing file:

cat id_rsa | base64 -w0 insert into script-part of your job in .gitlab-ci.yml:

mkdir -p ~/.ssh && echo "$SSH_PRIVATE_KEY" | \
  base64 -d > ${SSH_KEY_FILE} && chmod 0600 ${SSH_KEY_FILE}
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 4
    You can't mask a variable containing a private key if it contains line breaks though. – Clockwork Feb 02 '22 at 14:05
  • 2
    @Clockwork Indeed. Not without pre and post-processing, as in https://stackoverflow.com/a/54675024/6309. – VonC Feb 02 '22 at 15:08
  • 1
    Create pre-processing file: `cat id_rsa | base64 -w0` insert into script-part of your job in `.gitlab-ci.yml`: `mkdir -p ~/.ssh && echo "$SSH_PRIVATE_KEY" | base64 -d > ${SSH_KEY_FILE} && chmod 0600 ${SSH_KEY_FILE}` – sneaky Jul 26 '22 at 12:35
  • 1
    @sneaky Thank you for this suggestion. I have included your comment in the answer for more visibility. – VonC Jul 26 '22 at 12:46
0

I have been able to bypass this issue by encoding on origin the value and then decoding it on the fly.

On my Makefile:

KEY=$(shell base64 -w 0 private-key-file)

On .gitlab-ci.yml file:

- echo $SSH_PRIVATE_KEY | base64 -d |tr -d '\r' | ssh-add -

and then i call gitlab-runner

gitlab-runner exec docker ${build_target} --env 'SSH_PRIVATE_KEY=${KEY}'