Continuous deployment with public github repositories and travis encrypt - capistrano

We are looking at setting up continuous deployment for our ruby on rails apps which are currently deployed using Capistrano. They are stored in public repo's on github.
I have read the documentation on how to do this with travis-ci.org and it looks like you do something similar to the following:-
gem install travis
travis login
travis encrypt DEPLOY_KEY="password" --add
openssl aes-256-cbc -k "password" -in deploy_id_rsa -out config/deploy_id_rsa_enc_travis -a
Then add this to the travis.yml file
after_success:
- "openssl aes-256-cbc -k $DEPLOY_KEY -in config/deploy_id_rsa_enc_travis -d -a -out config/deploy_id_rsa"
- "bundle exec cap deploy"
and this to your deploy.rb file
set :ssh_options, keys: ["config/deploy_id_rsa"] if File.exist?("config/deploy_id_rsa")
Now my question is, how does this keep the private keys safe. I'm guessing you only commit the following files to the github public repo.
config/deploy_id_rsa_enc_travis
travis.yml
deploy.rb
and the that private key should be deleted, not committed.
Is there anything else I should look out for?

The sample code you provided is taking a private key named deploy_id_rsa and encrypting it with a password. That password is then stored in Travis as a "secret". This encrypted version of the key is called deploy_id_rsa_enc_travis. You can safely commit this file: the idea is that only someone who holds the password (i.e. Travis) will be able to decrypt it.
I would look out for:
Choose a complex and impossible to guess password to perform the encryption.
How "secret" are Travis secrets? Is there any chance that the $DEPLOY_KEY (password) will get echoed to the console output, for example? Can someone log into Travis and view the secrets?
Generate a deploy_id_rsa specifically for this purpose. Do not reuse an existing key.
Ensure the key corresponds to a deploy user that is locked down (e.g. does not have sudo abilities).
Never commit the original, unencrypted key: deploy_id_rsa.
Also consider moving your Capistrano deployment to a separate, private repo. Capistrano allows you to keep your app and your deployment configuration in separate places. That way information about your server infrastructure will not be visible to the public.

Related

GitHub Action appleboy/ssh-action: How do I avoid that the SSH key ends up on the server?

To log in from GitHub to my external server I use/test appleboy/ssh-action. As soon as I am on the server I start a git pull to get the latest changes to the server. However, this also includes the .github/workflows folder. And in a GH action yml file is my SSH password. I would like to avoid this. But I don't know how. Somebody know how to do this?
You should not store the password in the YAML file itself. Instead, use the GitHub Actions secrets functionality in the repository settings to store the password as a secret, and then pass it in through the environment. For example, you can pipe a secret like so:
- run: echo $PASSWORD | my-program-here
env:
PASSWORD: ${{secrets.SSH_PASSWORD}}
You can see an example of how this kind of approach is use in the Git LFS release workflow.

How does git know who I am when I use ssh to log in?

I set up SSH login for github using the following instructions, and although it works, I can't figure out why it works: https://help.github.com/articles/generating-ssh-keys/
My understanding of SSH is as follows: client creates a key pair, client gives public key to server, and when client wants to log in, he encrypts a message of server's choice using his private key to prove that he is really the client.
Now: I upload my public key XXX to Github. When I do "ssh -T git#github.com", Github has to know I am trying to log in as me, so that he can decrypt my message using XXX, right? So ssh has to send that information...but how does ssh know anything about Github, or what my username is? And what if I have multiple key pairs - which key would ssh use?
When you add your SSH public key to your GitHub account, you associate that key with your GitHub account.
By default, the command ssh -T git#github.com searches for id_dsa and id_rsa files. To confirm this, try ssh -T git#github.com -v.
If you have keys associated to different github accounts, you would have to specify with -i to use different accounts. ssh -T git#github.com -i /path/to/mykey
In short:
SSH client send public key to server
Server finds your name according to public key (unique), but needs to verify that you have also the private key, therefore he sends you a some message
Your client signs that message using your private key
Server verifies the signature and if it is valid, you are allowed access
This is based on public key cryptography, specially digital signature technique (google for more details).
In a shared-account scenario, authentication/authorization is handled by the application.
I'm not sure Github is using it, but one solution for non-shell account authorization is Gitosis, and it used for precisely the purpose you describe. There are separate key pairs for each user. This much is similar to how Github does things.
The basic notion of how Gitosis works (deferring the authentication and authorization to gitosis) is explained on the app readme page, but the mechanics may require a review of the source code. Based on a cursory examination, it looks like the mechanics of this method are mostly via git hooks on the server.

Can Travis CI use an encrypted file in different forks of the same repo?

I'm trying to get a Travis CI build to work in both my own private fork and the repo of my organization.
I encrypted a config file using the travis encrypt-file command and it seems to have created two environment variables in the travis settings for my own fork that look like: "encrypted_d1234_key" and "encrypted_d1234_iv".
These are used when the build runs to decrypt the config file, like so:
openssl aes-256-cbc -K $encrypted_d1234_key -iv $encrypted_d1234_iv -in test.config.enc -out test.config -d
Can I somehow copy those secure environment variables over to the settings for my org's repo so that the build can decrypt the config file whether it's in my fork or my org's fork.
Or is there a better way to handle these situations?
This is might be the same issue as: What do I need for Travis-CI to decrypt secure variables on my fork?
I figured out a way to get this working. Since you can't get the keys that Travis generates for you, you just have to generate your own keys. Then, encrypt your secret goodies and push the keys into any private repo that needs them (and whose members you trust):
openssl aes-256-cbc -K 1000000000000000000000000000000000000000000000000000000000000001 -iv 10000000000000000000000000000001 -in test.config -out test.config.enc
Now, we give the keys to Travis, which stores them on a per-repo basis. These commands store them in whatever repo is set up as "origin" in git:
travis env set encrypted_d1234_key 1000000000000000000000000000000000000000000000000000000000000001
travis env set encrypted_d1234_iv 10000000000000000000000000000001
Also store them in your org's repo.
travis env set encrypted_d1234_key 1000000000000000000000000000000000000000000000000000000000000001 -r MyOrg/MyRepo
travis env set encrypted_d1234_iv 10000000000000000000000000000001 -r MyOrg/MyRepo
This is (partially) explained in the "Manual Encryption" section of the Encrypting Files docs.
Note that there are some Security Restrictions when testing Pull Requests. Travis supplies you with an environment variable so you can conditionally skip tests that require secure config.

How to automate cloning private GitHub with Chef

Everyday I must launch new EC2 instances (or any other server with public IP). I'm provisioning it with Chef, creating vhosts, uploading databases etc.
I need to clone there a couple of private repos from GitHub. What would be the best way to do this?
I could manually generate an ssh key, and add it for each GitHub repo I need, then run the script - but it's a lot of work.
I could go for git clone git://user:password#github.com/*****/*****.git, but obviously I don't want to store my password this way
What else?
Is there any way to:
store a private key (or password?) in a recipe/cookbook or
generate new key, and synchronize it via API with GitHub (but this would lead to hundreds of keys in my GitHub account)
Store your key in an S3 bucket and use IAM roles/policies to control access. Citadel makes this easy to integrate with Chef. See my post about secrets management with Chef for a summary of other options.
Shameless plug: the deploy_key cookbook.
I created this cookbook with this precise use case in mind. It manages the entire lifecycle of deploy keys in GitHub, BitBucket and GitLab. It creates a key locally (so that it never has to be sent over the network), adds it to the repo as a deploy_key (read-only, so that these keys don't ever push changes to the repo), and can be used to delete the key files and remove the keys from the repo.
All actions are idempotent so if you're afraid your repos will be flooded with too many deploy_keys you can either remove the key from the repo after use (via Chef, :remove action), or have a periodic clean up task to delete all deploy_keys. Next time Chef runs, it will notice that the key is absent and re-add it.
The only secret you need to protect are the credentials to the repo, which can be protected in the same way you do other secrets.

Github sign in before a push

When I try to push my project on Github, I have to sign in every time with my Github account before the push. And I don't understand why, on certain projects I don't need to do this, only on one project.
MacBook-Pro-Firstname:ProjectName firstname$ git push origin master
Username for 'https://github.com': email#gmail.com
Password for 'https://email#gmail.com#gmail.com#github.com': *******
How can I remove the sign in process?
GitHub offers two different authentication methods for read/write access. The first, which you appear to be using, is the HTTPS method and requires username/password authentication. The other way is via SSH which uses public/private key pairs to authenticate rather than a username/password combination.
To change the URL of the repository to the SSH version, you can use git config remote.origin.url git#github.com:username/repository.git
It sounds like you already have SSH keys generated and added to your account if you don't need to authenticate for some projects, but if you don't you can set it up via this link.
I am not entirely sure but I believe you will need to create an SSH key: https://help.github.com/articles/generating-ssh-keys
You need to set up a public SSH key with Github. See this article: https://help.github.com/articles/generating-ssh-keys