gitlab-ci SSH key invalid format

Viewed 43633

I would like run deploy script with gitlab-ci, but step ssh-add $SSH_PRIVATE_KEY return an error :

echo "$SSH_PRIVATE_KEY" | ssh-add -
Error loading key "(stdin)": invalid format

You can see my .gitlab-ci.yml :

deploy:
  image: node:9.11.1-alpine
  stage: deploy
  before_script:
    # Install ssh-agent if not already installed, it is required by Docker.
    # (change apt-get to yum if you use a CentOS-based image)
    - 'which ssh-agent || ( apk add --update openssh )'

    # Add bash
    - apk add --update bash

    # Add git
    - apk add --update git

    # Run ssh-agent (inside the build environment)
    - eval $(ssh-agent -s)

    # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
    - echo "$SSH_PRIVATE_KEY"
    - echo "$SSH_PRIVATE_KEY" | ssh-add -

    # For Docker builds disable host key checking. Be aware that by adding that
    # you are suspectible to man-in-the-middle attacks.
    # WARNING: Use this only with the Docker executor, if you use it with shell
    # you will overwrite your user's SSH config.
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    # In order to properly check the server's host key, assuming you created the
    # SSH_SERVER_HOSTKEYS variable previously, uncomment the following two lines
    # instead.
    # - mkdir -p ~/.ssh
    # - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'
  script:
    - npm i -g pm2
    - pm2 deploy ecosystem.config.js production
  # only:
  # - master

On my project setting, i've been add SSH_PRIVATE_KEY variable, with the id_rsa from my production server cat ~/.ssh/id_rsa.pub.

Anyone can help me ?

15 Answers

In my case, it was because I had made my SSH_PRIVATE_KEY variable protected. When I disabled the Protected state, it worked without any error.

enter image description here

In my case I had to put a new line at the end of the SSH_PRIVATE_KEY variable

I made a stupid mistake and added the key without -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- clauses.

Summing up, you should add:

-----BEGIN RSA PRIVATE KEY-----
<< the key itself goes here >>
-----END RSA PRIVATE KEY-----

Also, ensure the newline after the closing is present.

It works with variable expansion (curly brackets in double string quotation):

  - echo "${SSH_PRIVATE_KEY}" | ssh-add -

While keeping the SSH_PRIVATE_KEY variable protected!

This approach is simply a less ambiguous method for printing variables; in this case it prevents trimming of the last line break.

Make sure that the newline after the end of the file variable is present. If not, the following error would have appeared:

Load key "/home/.../....tmp/ID_RSA": invalid format
 [MASKED]@...: Permission denied (publickey).

The ID_RSA was my file variable in this example.

for all people reaching this post not finding a solution yet.

Try to make the branch protected, because its a must for protected variables.

Protected: Only exposed to protected branches or protected tags.

Add a CI/CD variable to a project

It is the SSH public key in ~/.ssh/id_rsa.pub by default.

The private key is contained in ~/.ssh/id_rsa

If you export key from PuTTYgen, to get key content use its command Conversations - Export OpenSSH key (force new file format)

And trim last spaces and add new line.

You must copy the entire contents of the file(id_rsa), including the final blank line. I solve the problem this way.

I got it working with a protected variable.

If the variable is file, echo won't work anymore:

cat "$SSH_PRIVATE_KEY" | ssh-add -

Otherwise; if variable is NOT file, use the following:

echo "$SSH_PRIVATE_KEY" | ssh-add -

In my case, it was because I had made my SSH_PRIVATE_KEY variable available in a specific enviroment. I changed it to the one I was using (or you can change it to All, depending on your setup).

I had this issue on gitlab and bitbucket, both were solved adding a \n by the end of the key file.

echo $'' >> ~/.ssh/id_rsa

it possible you didn't copy the content of the public key to the authorized_keys

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

I had the same problem and after spending some hours trying to understand what was wrong I found that my private key was encrypted (and my computer had the password in cache for so long that I had forgotten that it was encrypted). It's not so easy to understand if it's encrypted or not by just looking at the key. You should decrypt the key (set an empty password) and then paste it on a GitLab variable. Then in your .gitlab-ci.yml you can have a similar configuration:

before_script:
    - 'which ssh-agent || ( apt-get install -qq openssh-client )'
    - mkdir -p ~/.ssh
    - touch ~/.ssh/id_rsa
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host *\nStrictHostKeyChecking no\n" > ~/.ssh/config
    - eval "$(ssh-agent -s)"
    - ssh-add ~/.ssh/id_rsa

*** Note that if you don't want to write the key in a file, you can just put it inside the ssh agent with:

- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null 

*** Note 2: In the Gitlab panel, make sure you have created a variable (and not a file); normally, it should be protected if you want to make it visible in the main branch.

*** Important: For security reasons change the following line:

- echo -e "Host *\nStrictHostKeyChecking no\n" > ~/.ssh/config

putting only your host/s (and don't permit all connections like this). If you put:

StrictHostKeyChecking no

when connecting to any host, the ssh-agent will not check the signature and this can be a big vulnerability!

Use

  SSH_PRIVATE_KEY: |
    -----BEGIN OPENSSH PRIVATE KEY-----

instead of

  SSH_PRIVATE_KEY: >
    -----BEGIN OPENSSH PRIVATE KEY-----

'|' would save the line break '\n'

Related