How can I extract secrets using GitHub Actions? - ssh

I have a fairly basic scenario. I made a dedicated ssh key for this purpose and added it to my repository secrets.
Code gets pushed to master
GitHub action uploads it to server using ssh by doing echo "${{ secrets.SSH_KEY }}" > key.
After that I can use this key to connect to my server e.g. ssh -i key devops#myserver.com lsb_release -a
The problem is that for some reason GitHub actions cannot write it to file, it writes characters *** instead of the actual secret value into the file. Therefore obviously I cannot connect to my server.
How can I connect with ssh using this secret? Is there a way to connect without using a file? Can someone who did this common scenario using GitHub actions shed some light?

GitHub Actions should be able to write a secret to a file this way. The reason you see the stars is that the log is filtered, so if a secret would be logged, it's replaced in the log with three asterisks instead. This is a security measure against an accidental disclosure of secrets, since logs are often publicly available.
However, it's a good idea to avoid writing the secret to the log anyway if possible. You can write your command like this so you don't write the secret to the log:
- run: 'echo "$SSH_KEY" > key'
shell: bash
env:
SSH_KEY: ${{secrets.SSH_KEY}}
All you'll see in the log is echo "$SSH_KEY" > key, not the secret or any asterisks.
Note that you do want quotes here, since the > character is special to YAML.
If this doesn't work to log into your server, there's likely a different issue; this technique does work for writing secrets in the general case.

I found a way to do this. We used GatsbyJS for a project and it relies on a
.env.production file for the env variables. I tried to pass them as
env: to the github action, but that didn't work and they were ignored.
Here is what I did. I base 64 encoded the .env.production file:
base64 -i .env.production
Added the output to an env variable in github action. Then in my action I do:
echo ${{ secrets.ENV_PRODUCTION_FILE }} | base64 -d > .env.production
This way the contents of my .env.production file ended being written to the machine that executes the github action.

I used sed in a GHA to replace a TOKEN in a file like this :
run: |-
sed -i "s/TOKEN/${{secrets.MY_SECRET}}/g" "thefile"
The file looks like this:
credentials "app.terraform.io" {
token = "TOKEN"
}

encode it and decode back
- run: 'echo "$SSH_KEY" | base64'
shell: bash
env:
SSH_KEY: ${{ secrets.PRIVATE_KEY }}
and decode it back echo "<encoded string>" | base64 -d

Here is how to solve your actual problem of securely logging into an SSH server using a secret stored in GitHub Actions, named GITHUB_ACTIONS_DEPLOY.
Let's call this "beep", because it will cause an audible bell on the server you login to. Maybe you use this literally ping a server in your house when somebody pushes code to your repo.
- name: Beep
# if: github.ref == 'refs/heads/XXXX' # Maybe limit only this step to some branches
run: |
eval $(ssh-agent)
ssh-add - <<< "$SSH_KEY"
echo "* ssh-rsa XXX" >> /tmp/known_hosts # Get from your local ~/.ssh/known_hosts or from ssh-keyscan
ssh -o UserKnownHostsFile=/tmp/known_hosts user#example.com "echo '\a'"
env:
SSH_KEY: ${{ secrets.PMT_GITHUB_ACTIONS_DEPLOY }}
If, actually you are using SSH as part of a rsync push task, here is how to do that:
- name: Publish
if: github.ref == 'refs/heads/XXX'
run: |
eval $(ssh-agent)
ssh-add - <<< "$SSH_KEY"
echo "* ssh-rsa XXX" >> /tmp/known_hosts
rsync $FROM user#server:
env:
SSH_KEY: ${{ secrets.GITHUB_ACTIONS_DEPLOY }}
RSYNC_RSH: "ssh -o UserKnownHostsFile=/tmp/known_hosts"

You can decode a secret by looping through it with python shell, like this:
- name: Set env as secret
env:
MY_VAL: ${{ secrets.SUPER_SECRET }}
run: |
import os
data = open("file", "w")
for q in (os.getenv("MY_VAL")):
print q
data.write(q)
shell: python
This will both print each character to stdout and store them in file called file. stdout will have an output like this, while file should have the secret string saved inside.
s
e
c
r
e
t

The good solution is to use gpg for encrypting the key, adding it to a repo and decrypting it on the server using passphrase. The passprase should be stored as github project secret of course.
More info how I did it here: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets

echo ${{secrets.AWS_ACCESS_KEY_ID}} | sed 's/./& /g'

Related

Load key "/root/.ssh/pipelines_id": invalid format

I am using bitbucket pipeline to deploy app on a ec2-server.
here is my bitbucket-pipelines.yaml file
image: atlassian/default-image:3
pipelines:
branches:
dev:
- step:
name: automated deployment
script:
- pipe: atlassian/scp-deploy:1.2.1
variables:
USER: 'ubuntu'
SERVER: $SERVER_IP
REMOTE_PATH: '/home/ubuntu/utags-test/server'
LOCAL_PATH: '${BITBUCKET_CLONE_DIR}/*'
- pipe: atlassian/ssh-run:0.4.1
variables:
SSH_USER: 'ubuntu'
SERVER: $SERVER_IP
COMMAND: 'cd /home/ubuntu/utags-test/server;docker pull paranjay1/utags-paranjay:dev;docker-compose down;docker-compose up -d'
SSH_KEY: $SERVER_PRIVATE_KEY
DEBUG: 'true'
services:
- docker
error while running pipeline
Build setup13s
pipe: atlassian/scp-deploy:1.2.1
....
....
Digest: sha256:b9111f61b5824ca7ed1cb63689a6da55ca6d6e8985eb778c36a5dfc2ffe776a8
Status: Downloaded newer image for bitbucketpipelines/scp-deploy:1.2.1
INFO: Configuring ssh with default ssh key.
INFO: Adding known hosts...
INFO: Appending to ssh config file private key path
INFO: Applied file permissions to ssh directory.
✔ Deployment finished.
pipe: atlassian/ssh-run:0.4.1
....
....
Digest: sha256:b8ff5416420ef659869bf1ea6e95502b8fa28ccd5e51321e4832d9d81fdefc18
Status: Downloaded newer image for bitbucketpipelines/ssh-run:0.4.1
INFO: Executing the pipe...
INFO: Using passed SSH_KEY
INFO: Executing command on 13.235.33.118
ssh -A -tt -i /root/.ssh/pipelines_id -o StrictHostKeyChecking=no -p 22 ubuntu#13.235.33.118 bash -c 'cd /utags-test/server;docker pull paranjay1/utags-paranjay:dev;docker-compose down;docker-compose up -d'
Load key "/root/.ssh/pipelines_id": invalid format
Load key "/root/.ssh/pipelines_id": invalid format
ubuntu#13.235.33.118: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
✖ Execution failed.
I already installed docker and docker-compose on my ec2-server
I generated the keys on bitbucket in sshkey section and added bitbucket public key to my authorized_keys file on ec2-server
$SERVER_PRIVATE_KEY contains the ec2-server private key
$SERVER_IP contains my ec2-server public IP
HOW CAN I SOLVE THIS ISSUE and what might be the cause of this error?
atlassian/ssh-run pipe documentation states the alternative SSH_KEY should be base64 encoded. My bet is you missed that info bit.
An base64 encoded alternate SSH_KEY to use instead of the key configured in the Bitbucket Pipelines admin screens (which is used by default). This should be encoded as per the instructions given in the docs for using multiple ssh keys.
Another good question would be: why aren't you using the ssh key provided by the pipeline instead?
You can use repository SSH key, so you won't need to encode it.
bitbucket.com/.../admin/addon/admin/pipelines/ssh-keys
Then remove SSH key variable and it defaultly uses repository ssh key.
you actually don't need to use "SSH_KEY: $SERVER_PRIVATE_KEY" in your pipe. you can use the default keys available in your bitbucket_repo > repository_settings > ssh_key. you can generate a key here. the generated public key should be in the remote server's "/home/ubuntu/.ssh/authorized_key" file. add your remote servers public-IP to the known host and fetch fingerprint.
but if you want to use a different ssh key then you have to add "SSH_KEY: $SERVER_PRIVATE_KEY" in your pipe. where,
$SERVER_PRIVATE_KEY - local machine's private_IP encoded to base64
you have to use $base64 -w 0 < my_ssh_key command to encode your key to base64

Getting GitLab CI to clone private repositories

I have GitLab & GitLab CI set up to host and test some of my private repos. For my composer modules under this system, I have Satis set up to resolve my private packages.
Obviously these private packages require an ssh key to clone them, and I have this working in the terminal - I can run composer install and get these packages, so long as I have the key added with ssh-add in the shell.
However, when running my tests in GitLab CI, if a project has any of these dependencies the tests will not complete as my GitLab instance needs authentication to get the deps (obviously), and the test fails saying Host key verification failed.
My question is how do I set this up so that when the runner runs the test it can authenticate to gitlab without a password? I have tried putting a password-less ssh-key in my runners ~/.ssh folder, however the build wont even add the key, "eval ssh-agent -s" followed by ssh-add seems to fail saying the agent isn't running...
See also other solutions:
git submodule permission (see Marco A.'s answer)
job token and override repo in git config (see a544jh's answer)
Here a full howto with SSH keys:
General Design
generating a pair of SSH keys
adding the private one as a secure environment variable of your project
making the private one available to your test scripts on GitLab-CI
adding the public one as a deploy key on each of your private dependencies
Generating a pair of public and private SSH keys
Generate a pair of public and private SSH keys without passphrase:
ssh-keygen -b 4096 -C "<name of your project>" -N "" -f /tmp/name_of_your_project.key
Adding the private SSH key to your project
You need to add the key as a secure environment variable to your project as
following:
browse https://<gitlab_host>/<group>/<project_name>/variables
click on "Add a variable"
fill the text field Key with SSH_PRIVATE_KEY
fill the text field Value with the private SSH key itself
click on "Save changes"
Exposing the private SSH key to your test scripts
In order to make your private key available to your test scripts you need to add
the following to your .gitlab-ci.yml file:
before_script:
# install ssh-agent
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
# run ssh-agent
- eval $(ssh-agent -s)
# add ssh key stored in SSH_PRIVATE_KEY variable to the agent store
- ssh-add <(echo "$SSH_PRIVATE_KEY")
# disable host key checking (NOTE: makes you susceptible to man-in-the-middle attacks)
# WARNING: use only in docker container, if you use it with shell you will overwrite your user's ssh config
- mkdir -p ~/.ssh
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config
Code Snippet comes from GitLab documentation
Adding the public SSH key as a deploy key to all your private dependencies
You need to register the public SSH key as deploy key to all your private
dependencies as following:
browse https://<gitlab_host>/<group>/<dependency_name>/deploy_keys
click on "New deploy key"
fill the text field Title with the name of your project
fill the text field Key with the public SSH key itself
click on "Create deploy key"
If you don't want to fiddle around with ssh keys or submodules, you can override the repo in git's configuration to authenticate with the job token instead (in gitlab-ci.yml):
before_script:
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.example.com/group/repo.git".insteadOf git#gitlab.example.com:group/repo.git
I'm posting this as an answer since others weren't completely clear and/or detailed IMHO
Starting from GitLab 8.12+, assuming the submodule repo is in the same server as the one requesting it, you can now:
Set up the repo with git submodules as usual (git submodule add git#somewhere:folder/mysubmodule.git)
Modify your .gitmodules file as follows
[submodule "mysubmodule"]
path = mysubmodule
url = ../../group/mysubmodule.git
where ../../group/mysubmodule.git is a relative path from your repository to the submodule's one.
Add the following lines to gitlab-ci.yml
variables:
GIT_SUBMODULE_STRATEGY: recursive
to instruct the runner to fetch all submodules before the build.
Caveat: if your runner seems to ignore the GIT_SUBMODULE_STRATEGY directive, you should probably consider updating it.
(source: https://docs.gitlab.com/ce/ci/git_submodules.html)
The currently accepted answer embeds Gitlab-specific requirements into my .gitmodules file. This forces a specific directory layout for local development and would complicate moving to another version control platform.
Instead, I followed the advice in Juddling's answer. Here's a more complete answer.
My .gitmodules files has the following contents:
[submodule "myproject"]
url = git#git.myhost.com:mygroup/myproject.git
In my gitlab-ci.yml I have the following:
build:
stage: build
before_script:
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}#git.myhost.com/".insteadOf "git#git.myhost.com:"
- git submodule sync && git submodule update --init
The trailing / and : are critical in the git config line, since we are mapping from SSH authentication to HTTPS. This tripped me up for a while with "Illegal port number" errors.
I like this solution because it embeds the Gitlab-specific requirements in a Gitlab-specific file, which is ignored by everything else.
I used deploy tokens to solve this issue, as setting up SSH keys for a test runner seems a little long winded.
git clone http://<username>:<deploy_token>#gitlab.example.com/tanuki/awesome_project.git
The deploy tokens are per project and are read only.
One way to solve this without changing the git repository's structure is to perform the following steps:
1. get ssh host keys
Get the ssh host keys of the server that you are running on. For gitlab.com:
run ssh-keyscan gitlab.com > known_hosts
check that ssh-keygen -lf known_hosts agrees with the fingerprints reported here.
copy the content of the known_hosts and paste it on a variable called SSH_KNOWN_HOSTS on the repository.
This step is only needed once.
2. configure the job to use ssh
before_script:
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.com".insteadOf "git#gitlab.com:"
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
The "ssh://git#gitlab.com" bit may be different if you are trying to do git clone git#gitlab.com: or pip install -e git+ssh://git#gitlab.com/...; adjust it accordingly to your needs.
At this point, your CI is able to use ssh to fetch from another (private) repository.
3. [Bonus DRY]
Use this trick to write it generically:
.enable_ssh: &enable_ssh |-
git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.com".insteadOf "ssh://git#gitlab.com"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
and enable it on jobs that need it
test:
stage: test
before_script:
- *enable_ssh
script:
- ...
If your CI runner is running on a container model, you need to use the deploy key. doc: https://docs.gitlab.com/ee/user/project/deploy_tokens/#git-clone-a-repository
git clone https://<username>:<deploy_token>#gitlab.example.com/tanuki/awesome_project.git
Create your deploy token
Add your token in CI pipeline Variable
make sure your container has the git and change the git URL by insteadOf
image: docker:latest
before_script:
- apk add --no-cache curl jq python3 py3-pip git
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.example.come/".insteadOf 'git#gitlab.example.come:'
for replace URL: https://docs.gitlab.com/ee/user/project/working_with_projects.html#authenticate-git-fetches
I had a scenario where I had to use my ssh key in 3 different scripts, so I put the ssh key stuff in a single shell script and called it first, before the other 3 scripts. This ended up not working, I think due to the ssh-agent not persisting between shell scripts, or something to that effect. I ended up actually just outputting the private key into the ~/.ssh/id_rsa file, which will for sure persist to other scripts.
.gitlab-ci.yml
script:
- ci/init_ssh.sh
- git push # or whatever you need ssh for
ci/init_ssh.sh
# only run in docker:
[[ ! -e /.dockerenv ]] && exit 0
mkdir -p ~/.ssh
echo "$GITLAB_RUNNER_SSH_KEY" > ~/.ssh/id_rsa
chmod 400 ~/.ssh/id_rsa
echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > /.ssh/config
It works like a charm!
If you are using an alpine-based image (maybe docker:latest or docker:dind), your before_script might look like this:
before_script:
- apk add --no-cache openssh-client git
- mkdir -p /.ssh && touch /.ssh/known_hosts
- ssh-keyscan gitlab.com >> /.ssh/known_hosts
- echo $SSH_KEY | base64 -d >> /.ssh/id_rsa && chmod 600 /.ssh/id_rsa
- git clone git#git.myhost.com:mygroup/myproject.git
Adding this to .gitlab-ci.yml did the trick for me.
(as mentioned here: https://docs.gitlab.com/ee/user/project/new_ci_build_permissions_model.html#dependent-repositories)
before_script:
echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
(I tried setting up SSH_PRIVATE_KEY as mentioned in one of the answers above, it won't work)
Gitlab 15.9.0 introduces an update to the pre-defined variable CI_JOB_TOKEN. Now you can control other projects' access to your private repository, see the release note and documentation.
Once access is granted, you can clone private repositories by adding this line to your job's scripts or before_scripts.
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.example.com/<namespace>/<project>
Unfortunately, this still does not play nicely with the submodule integration with Gitlab CI/CD. Instead, I do this in my projects.
# .gitlab-ci.yml
default:
before_script:
- |
cat << EOF > ~/.gitconfig
[url "https://gitlab-ci-token:${CI_JOB_TOKEN}#gitlab.example.com/<namespace>/<project>.git"]
insteadOf = git#gitlab.example.com/<namespace>/<project>.git
EOF
- git submodule update --init --recursive
And this is what my .gitmodules would look like
[submodule "terraform-eks"]
path = modules/<project>
url = git#gitlab.example.com/<namespace>/<project>.git
branch = main
Hope this help!
Seems there is finally a reasonable solution.
In short as of GitLab 8.12 all you need to do is use relative paths in the .submodules, and the git submodule update --init will simply work

Setting ssh public keys on Docker image

I setup a Docker image that supports ssh. No problem, lots of examples. However, most examples show setting a password using passwd. I want to distribute my image. Having a fixed password, especially to root, seems like a gaping security hole. Better, to me, is to setup the image with root having no password. When a user gets the image they would then copy their public ssh file to the image /root/.ssh/authorized_keys file.
Is there a recommended way to do this?
Provide a Dockerfile that builds on my image with an ADD command
that user can edit?
Provide a shell script that runs something like "cat ~/.ssh/authorized_keys | docker run -i sh -c 'cat > root/.ssh/authorized_keys"?
What about generating a private key and display it to the user?
I use this snippet as part of the entrypoint script for an image:
KEYGEN=/usr/bin/ssh-keygen
KEYFILE=/root/.ssh/id_rsa
if [ ! -f $KEYFILE ]; then
$KEYGEN -q -t rsa -N "" -f $KEYFILE
cat $KEYFILE.pub >> /root/.ssh/authorized_keys
fi
echo "== Use this private key to log in =="
cat $KEYFILE

cygwin's ssh-add returns "Could not open a connection to your authentication agent." [duplicate]

I am running into this error of:
$ git push heroku master
Warning: Permanently added the RSA host key for IP address '50.19.85.132' to the list of known hosts.
! Your key with fingerprint b7:fd:15:25:02:8e:5f:06:4f:1c:af:f3:f0:c3:c2:65 is not authorized to access bitstarter.
I tried to add the keys and I get this error below:
$ ssh-add ~/.ssh/id_rsa.pub
Could not open a connection to your authentication agent.
Did You Start ssh-agent?
You might need to start ssh-agent before you run the ssh-add command:
eval `ssh-agent -s`
ssh-add
Note that this will start the agent for msysgit Bash on Windows. If you're using a different shell or operating system, you might need to use a variant of the command, such as those listed in the other answers.
See the following answers:
ssh-add complains: Could not open a connection to your authentication agent
Git push requires username and password (contains detailed instructions on how to use ssh-agent)
How to run (git/ssh) authentication agent?.
Could not open a connection to your authentication agent
To automatically start ssh-agent and allow a single instance to work in multiple console windows, see Start ssh-agent on login.
Why do we need to use eval instead of just ssh-agent?
SSH needs two things in order to use ssh-agent: an ssh-agent instance running in the background, and an environment variable set that tells SSH which socket it should use to connect to the agent (SSH_AUTH_SOCK IIRC). If you just run ssh-agent then the agent will start, but SSH will have no idea where to find it.
from this comment.
Public vs Private Keys
Also, whenever I use ssh-add, I always add private keys to it. The file ~/.ssh/id_rsa.pub looks like a public key, I'm not sure if that will work. Do you have a ~/.ssh/id_rsa file? If you open it in a text editor, does it say it's a private key?
I tried the other solutions to no avail. I made more research and found that the following command worked. I am using Windows 7 and Git Bash.
eval $(ssh-agent)
More information in: https://coderwall.com/p/rdi_wq (web archive version)
The following command worked for me. I am using CentOS.
exec ssh-agent bash
Could not open a connection to your authentication agent
To resolve this error:
bash:
$ eval `ssh-agent -s`
tcsh:
$ eval `ssh-agent -c`
Then use ssh-add as you normally would.
Hot Tip:
I was always forgetting what to type for the above ssh-agent commands, so I created an alias in my .bashrc file like this:
alias ssh-agent-cyg='eval `ssh-agent -s`'
Now instead of using ssh-agent, I can use ssh-agent-cyg
E.g.
$ ssh-agent-cyg
SSH_AUTH_SOCK=/tmp/ssh-n16KsxjuTMiM/agent.32394; export SSH_AUTH_SOCK;
SSH_AGENT_PID=32395; export SSH_AGENT_PID;
echo Agent pid 32395;
$ ssh-add ~/.ssh/my_pk
Original Source of fix:
http://cygwin.com/ml/cygwin/2011-10/msg00313.html
MsysGit or Cygwin
If you're using Msysgit or Cygwin you can find a good tutorial at SSH-Agent in msysgit and cygwin and bash:
Add a file called .bashrc to your home folder.
Open the file and paste in:
#!/bin/bash
eval `ssh-agent -s`
ssh-add
This assumes that your key is in the conventional ~/.ssh/id_rsa location. If it isn't, include a full path after the ssh-add command.
Add to or create file ~/.ssh/config with the contents
ForwardAgent yes
In the original tutorial the ForwardAgent param is Yes, but it's a typo. Use all lowercase or you'll get errors.
Restart Msysgit. It will ask you to enter your passphrase once, and that's it (until you end the session, or your ssh-agent is killed.)
Mac/OS X
If you don't want to start a new ssh-agent every time you open a terminal, check out Keychain. I'm on a Mac now, so I used the tutorial ssh-agent with zsh & keychain on Mac OS X to set it up, but I'm sure a Google search will have plenty of info for Windows.
Update: A better solution on Mac is to add your key to the Mac OS Keychain:
ssh-add -K ~/.ssh/id_rsa
Simple as that.
Run
ssh-agent bash
ssh-add
To get more details you can search
ssh-agent
or run
man ssh-agent
ssh-add and ssh (assuming you are using the openssh implementations) require an environment variable to know how to talk to the ssh agent. If you started the agent in a different command prompt window to the one you're using now, or if you started it incorrectly, neither ssh-add nor ssh will see that environment variable set (because the environment variable is set locally to the command prompt it's set in).
You don't say which version of ssh you're using, but if you're using cygwin's, you can use this recipe from SSH Agent on Cygwin:
# Add to your Bash config file
SSHAGENT=/usr/bin/ssh-agent
SSHAGENTARGS="-s"
if [ -z "$SSH_AUTH_SOCK" -a -x "$SSHAGENT" ]; then
eval `$SSHAGENT $SSHAGENTARGS`
trap "kill $SSH_AGENT_PID" 0
fi
This will start an agent automatically for each new command prompt window that you open (which is suboptimal if you open multiple command prompts in one session, but at least it should work).
I faced the same problem for Linux, and here is what I did:
Basically, the command ssh-agent starts the agent, but it doesn't really set the environment variables for it to run. It just outputs those variables to the shell.
You need to:
eval `ssh-agent`
and then do ssh-add. See Could not open a connection to your authentication agent.
Instead of using ssh-agent -s, I used eval `ssh-agent -s` to solve this issue.
Here is what I performed step by step (step 2 onwards on Git Bash):
Cleaned up my .ssh folder at C:\user\<username>\.ssh\
Generated a new SSH key:
ssh-keygen -t rsa -b 4096 -C "xyz#abc.com"
Check if any process id(ssh agent) is already running.
ps aux | grep ssh
(Optional) If found any in step 3, kill those
kill <pids>
Started the SSH agent
$ eval `ssh-agent -s`
Added SSH key generated in step 2 to the SSH agent
ssh-add ~/.ssh/id_rsa
Try to do the following steps:
Open Git Bash and run: cd ~/.ssh
Try to run agent: eval $(ssh-agent)
Right now, you can run the following command: ssh-add -l
In Windows 10 I tried all answers listed here, but none of them seemed to work. In fact, they give a clue. To solve a problem, simply you need three commands. The idea of this problem is that ssh-add needs the SSH_AUTH_SOCK and SSH_AGENT_PID environment variables to be set with the current ssh-agent sock file path and pid number.
ssh-agent -s > temp.txt
This will save the output of ssh-agent in a file. The text file content will be something like this:
SSH_AUTH_SOCK=/tmp/ssh-kjmxRb2764/agent.2764; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3044; export SSH_AGENT_PID;
echo Agent pid 3044;
Copy something like "/tmp/ssh-kjmxRb2764/agent.2764" from the text file and run the following command directly in the console:
set SSH_AUTH_SOCK=/tmp/ssh-kjmxRb2764/agent.2764
Copy something like "3044" from the text file and run the following command directly in the console:
set SSH_AGENT_PID=3044
Now when environment variables (SSH_AUTH_SOCK and SSH_AGENT_PID) are set for the current console session, run your ssh-add command and it will not fail again to connect to ssh agent.
One thing I came across was that eval did not work for me using Cygwin, what worked for me was ssh-agent ssh-add id_rsa.
After that I came across an issue that my private key was too open, the solution I managed to find for that (from here):
chgrp Users id_rsa
as well as
chmod 600 id_rsa
finally I was able to use:
ssh-agent ssh-add id_rsa
For Windows users, I found cmd eval `ssh-agent -s` didn't work, but using Git Bash worked a treat:
eval `ssh-agent -s`; ssh-add KEY_LOCATION
And making sure the Windows service "OpenSSH Key Management" wasn't disabled.
To amplify on n3o's answer for Windows 7...
My problem was indeed that some required environment variables weren't set, and n3o is correct that ssh-agent tells you how to set those environment variables, but doesn't actually set them.
Since Windows doesn't let you do "eval," here's what to do instead:
Redirect the output of ssh-agent to a batch file with
ssh-agent > temp.bat
Now use a text editor such as Notepad to edit temp.bat. For each of the first two lines:
Insert the word "set" and a space at the beginning of the line.
Delete the first semicolon and everything that follows.
Now delete the third line. Your temp.bat should look something like this:
set SSH_AUTH_SOCK=/tmp/ssh-EorQv10636/agent.10636
set SSH_AGENT_PID=8608
Run temp.bat. This will set the environment variables that are needed for ssh-add to work.
I just got this working. Open your ~/.ssh/config file.
Append the following-
Host github.com
IdentityFile ~/.ssh/github_rsa
The page that gave me the hint Set up SSH for Git
said that the single space indentation is important... though I had a configuration in here from Heroku that did not have that space and works properly.
If you follow these instructions, your problem would be solved.
If you’re on a Mac or Linux machine, type:
eval "$(ssh-agent -s)"
If you’re on a Windows machine, type:
ssh-agent -s
I had the same problem on Ubuntu and the other solutions didn't help me.
I finally realized what my problem was. I had created my SSH keys in the /root/.ssh folder, so even when I ran ssh-add as root, it couldn't do its work and kept saying:
Could not open a connection to your authentication agent.
I created my SSH public and private keys in /home/myUsername/ folder and I used
ssh-agent /bin/sh
Then I ran
ssh-add /home/myUsername/.ssh/id_rsa
And problem was solved this way.
Note: For accessing your repository in Git, add your Git password when you are creating SSH keys with ssh-keygen -t rsa -C "your Git email here".
Let me offer another solution. If you have just installed Git 1.8.2.2 or thereabouts, and you want to enable SSH, follow the well-writen directions.
Everything through to Step 5.6 where you might encounter a slight snag. If an SSH agent is already be running you could get the following error message when you restart bash
Could not open a connection to your authentication agent
If you do, use the following command to see if more than one ssh-agent process is running
ps aux | grep ssh
If you see more than one ssh-agent service, you will need to kill all of these processes. Use the kill command as follows (the PID will be unique on your computer)
kill <PID>
Example:
kill 1074
After you have removed all of the ssh-agent processes, run the px aux | grep ssh command again to be sure they are gone, then restart Bash.
Voila, you should now get something like this:
Initializing new SSH agent...
succeeded
Enter passphrase for /c/Users/username/.ssh/id_rsa:
Now you can continue on Step 5.7 and beyond.
This will run the SSH agent and authenticate only the first time you need it, not every time you open your Bash terminal. It can be used for any program using SSH in general, including ssh itself and scp. Just add this to /etc/profile.d/ssh-helper.sh:
ssh-auth() {
# Start the SSH agent only if not running
[[ -z $(ps | grep ssh-agent) ]] && echo $(ssh-agent) > /tmp/ssh-agent-data.sh
# Identify the running SSH agent
[[ -z $SSH_AGENT_PID ]] && source /tmp/ssh-agent-data.sh > /dev/null
# Authenticate (change key path or make a symlink if needed)
[[ -z $(ssh-add -l | grep "/home/$(whoami)/.ssh/id_rsa") ]] && ssh-add
}
# You can repeat this for other commands using SSH
git() { ssh-auth; command git "$#"; }
Note: this is an answer to this question, which has been merged with this one.
That question was for Windows 7, meaning my answer was for Cygwin/MSYS/MSYS2. This one seems for some Unix, where I wouldn't expect the SSH agent needing to be managed like this.
The basic solution to run ssh-agent is answered in many answers. However runing ssh-agent many times (per each opened terminal or per remote login) will create a many copies ot ssh-agent running in memory. The scripts which is suggested to avoid that problem is long and need to write and/or copy separated file or need to write too many strings in ~/.profile or ~/.schrc. Let me suggest simple two string solution:
For sh, bash, etc:
# ~/.profile
if ! pgrep -q -U `whoami` -x 'ssh-agent'; then ssh-agent -s > ~/.ssh-agent.sh; fi
. ~/.ssh-agent.sh
For csh, tcsh, etc:
# ~/.schrc
sh -c 'if ! pgrep -q -U `whoami` -x 'ssh-agent'; then ssh-agent -c > ~/.ssh-agent.tcsh; fi'
eval `cat ~/.ssh-agent.tcsh`
What is here:
search the process ssh-agent by name and by current user
create appropriate shell script file by calling ssh-agent and run ssh-agent itself if no current user ssh-agent process found
evaluate created shell script which configure appropriate environment
It is not necessary to protect created shell script ~/.ssh-agent.tcsh or ~/.ssh-agent.sh from another users access because: at-first communication with ssh-agent is processed through protected socket which is not accessible to another users, and at-second another users can found ssh-agent socket simple by enumeration files in /tmp/ directory. As far as about access to ssh-agent process it is the same things.
In Windows 10, using the Command Prompt terminal, the following works for me:
ssh-agent cmd
ssh-add
You should then be asked for a passphrase after this:
Enter passphrase for /c/Users/username/.ssh/id_rsa:
Try the following:
ssh-agent sh -c 'ssh-add && git push heroku master'
Use parameter -A when you connect to server, example:
ssh -A root#myhost
from man page :
-A Enables forwarding of the authentication agent connection.
This can also be specified on a per-host basis in a configuration file.
Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent's
UNIX-domain socket) can access the local agent through the forwarded
connection. An attacker cannot obtain key material from the agent,
however they can perform operations on the keys that enable them to
authenticate using the identities loaded into the agent.
I had this problem, when I started ssh-agent, when it was already running. It seems that the multiple instances conflict with each other.
To see if ssh-agent is already running, check the value of the SSH_AGENT_SOCK environment variable with:
echo $SSH_AGENT_SOCK
If it is set, then the agent is presumably running.
To check if you have more than one ssh-agent running, you can review:
ps -ef | grep ssh
Of course, then you should kill any additional instances that you created.
Read user456814's answer for explanations. Here I only try to automate the fix.
If you using a Cygwin terminal with Bash, add the following to the $HOME/.bashrc file. This only starts ssh-agent once in the first Bash terminal and adds the keys to ssh-agent. (I am not sure if this is required on Linux.)
###########################
# start ssh-agent for
# ssh authentication with github.com
###########################
SSH_AUTH_SOCK_FILE=/tmp/SSH_AUTH_SOCK.sh
if [ ! -e $SSH_AUTH_SOCK_FILE ]; then
# need to find SSH_AUTH_SOCK again.
# restarting is an easy option
pkill ssh-agent
fi
# check if already running
SSH_AGENT_PID=`pgrep ssh-agent`
if [ "x$SSH_AGENT_PID" == "x" ]; then
# echo "not running. starting"
eval $(ssh-agent -s) > /dev/null
rm -f $SSH_AUTH_SOCK_FILE
echo "export SSH_AUTH_SOCK=$SSH_AUTH_SOCK" > $SSH_AUTH_SOCK_FILE
ssh-add $HOME/.ssh/github.com_id_rsa 2>&1 > /dev/null
#else
# echo "already running"
fi
source $SSH_AUTH_SOCK_FILE
Don’t forget to add your correct keys in the "ssh-add" command.
I had a similar problem when I was trying to get this to work on Windows to connect to the stash via SSH.
Here is the solution that worked for me.
Turns out I was running the Pageant ssh agent on my Windows box - I would check what you are running. I suspect it is Pageant as it comes as default with PuTTY and WinSCP.
The ssh-add does not work from command line with this type of agent
You need to add the private key via the Pageant UI window which you can get by double-clicking the Pageant icon in the taskbar (once it is started).
Before you add the key to Pageant you need to convert it to PPK format. Full instructions are available here How to convert SSH key to ppk format
That is it. Once I uploaded my key to stash I was able to use Sourcetree to create a local repository and clone the remote.
For Bash built into Windows 10, I added this to file .bash_profile:
if [ -z $SSH_AUTH_SOCK ]; then
if [ -r ~/.ssh/env ]; then
source ~/.ssh/env
if [ `ps -p $SSH_AGENT_PID | wc -l` = 1 ]; then
rm ~/.ssh/env
unset SSH_AUTH_SOCK
fi
fi
fi
if [ -z $SSH_AUTH_SOCK ]; then
ssh-agent -s | sed 's/^echo/#echo/'> ~/.ssh/env
chmod 600 ~/.ssh/env
source ~/.ssh/env > /dev/null 2>&1
fi
Using Git Bash on Windows 8.1 E, my resolution was as follows:
eval $(ssh-agent) > /dev/null
ssh-add ~/.ssh/id_rsa
I resolved the error by force stopping (killed) git processes (ssh agent), then uninstalling Git, and then installing Git again.
This worked for me.
In the CMD window, type the following command:
cd path-to-Git/bin # (for example,cd C:\Program Files\Git\bin)
bash
exec ssh-agent bash
ssh-add path/to/.ssh/id_rsa

How to make ssh-add read passphrase from a file?

I am trying to add a key to ssh-agent and want ssh-add to read the password from the key file I'm using. How is this possible?
How do I automate this process from the shell script?
Depending on your distribution and on the version of ssh-add you may be able or not to use the -p option of ssh-add that reads the passphrase from stdin in this way:
cat passfile | ssh-add -p keyfile
If this is not working you can use Expect, a Unix tool to make interactive applications non-interactive. You'll have to install it from your package manager.
I have written a tool for you in expect. Just copy the content in a file named ssh-add-pass and set executable permissions on it (chmod +x ssh-add-pass). You can also copy it to /usr/bin or /usr/local/bin to be accessible from the $PATH search.
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass keyfile passfile"
exit 1
fi
eval $(ssh-agent)
pass=$(cat $2)
expect << EOF
spawn ssh-add $1
expect "Enter passphrase"
send "$pass\r"
expect eof
EOF
The usage is simply: ssh-add-pass keyfile passfile
Similar to the answer by kenorb, but doesn't save the secret in a file:
$ SSH_ASKPASS=/path/to/ssh_give_pass.sh ssh-add $KEYFILE <<< "$KEYPASS"
where ssh_give_pass.sh is:
#!/bin/bash
# Parameter $1 passed to the script is the prompt text
# READ Secret from STDIN and echo it
read SECRET
echo $SECRET
If you have you secret in a $KEYPASSFILE, read it into a variable first with
KEYPASS=`cat $KEYPASSFILE`
Also make sure that ssh_give_pass.sh is not editable by unauthorized users - it will be easy to log all secrets passed through the script.
Here is some workaround for systems not supporting -p:
$ PASS="my_passphrase"
$ install -vm700 <(echo "echo $PASS") "$PWD/ps.sh"
$ cat id_rsa | SSH_ASKPASS="$PWD/ps.sh" ssh-add - && rm -v "$PWD/ps.sh"
where ps.sh is basically your script printing your passphrase. See: man ssh-add.
To make it more secure (to not keep it in the same file), use mktemp to generate a random private file, make it executable (chmod) and make sure it prints the passphrase to standard output once executed.
On my Ubuntu system, none of the answers worked:
ssh-add did not support the -p option.
ssh-add ignored SSH_ASKPASS, insisting on prompting for the passphrase on the controlling terminal.
I wanted to avoid installing additional packages, especially expect.
What worked in my case was:
password_source | SSH_ASKPASS=/bin/cat setsid -w ssh-add keyfile
password_source isn't really a program: it just represents whatever feeds the passphrase to ssh-add. In my case, it is a program that executes setsid and writes the passphrase to its stdin. If you keep your passphrase in a file, you are responsible for making the simple modifications: I will not enable you to hurt yourself.
setsid was already installed, and detaches the controlling terminal so that ssh-add will not try to use it to prompt for the passphrase. -w causes setsid to wait for ssh-add to exit and make its return code available. /bin/cat has the same effect as the script Ray Shannon provided, but uses a standard tool instead of replicating its functionality with a script.
With this minimal changes worked for me this bash script of #enrico.basis
#!/bin/bash
if [ $# -ne 2 ] ; then
echo "Usage: ssh-add-pass passfile keyfile"
exit 1
fi
eval 'ssh-agent -s'
passwordToFileSSH=$1
pathFileSSH=$2
expect << EOF
spawn ssh-add $pathFileSSH
expect "Enter passphrase"
send "$passwordToFileSSH\r"
expect eof
EOF
The best way is to generate a key without a passphrase