Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY] Alternative ways of sharing a connection string #2

Closed
webknjaz opened this issue Aug 27, 2019 · 22 comments
Closed

[SECURITY] Alternative ways of sharing a connection string #2

webknjaz opened this issue Aug 27, 2019 · 22 comments
Assignees
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@webknjaz
Copy link

While I also did something similar to access to other CIs, I'd like to point out that printing out such things to public logs is insecure, especially because some secrets can be exposed to that env.

I think that this action should have an option to send creds over email without exposing them publicly.

@mxschmitt
Copy link
Owner

Definitely, what do you recommend? Travis Ci has it also public afaik.

@webknjaz
Copy link
Author

I'd just accept email as an input and send the creds there.

@mxschmitt
Copy link
Owner

I'd just accept email as an input and send the creds there.

But we won't have any SMTP server etc. so they would all be probably declined or moved directly to spam.

@webknjaz
Copy link
Author

Maybe put it to https://privnote.com/ then with a user-specified password as an input? Well, could also encrypt with user-given GPG key and put it right into the log. Maybe with a helper command prompting them how to decrypt the thing.
Oh, and there's also https://keybase.io which may also be helpful...

@mxschmitt mxschmitt added the enhancement New feature or request label Aug 28, 2019
@mxschmitt mxschmitt self-assigned this Aug 28, 2019
@mxschmitt mxschmitt added the help wanted Extra attention is needed label Aug 30, 2019
@leo60228
Copy link

leo60228 commented Feb 3, 2020

https://stackoverflow.com/a/46841303/3078446 seems relevant.

@leo60228
Copy link

leo60228 commented Feb 3, 2020

const password = process.argv[2];
const data = process.argv[3];

const crypto = require('crypto');

const salt = crypto.randomBytes(16);
const key = crypto.scryptSync(password, salt, 32);
const iv = crypto.randomBytes(16);

const cipher = crypto.createCipheriv('AES-256-CBC', key, iv);

const aesbuf1 = cipher.update(data, 'utf8');
const aesbuf2 = cipher.final();

const encrypted = Buffer.concat([salt, iv, aesbuf1, aesbuf2]);

console.log(encrypted.toString('base64'));

and

const password = process.argv[2];
const data = Buffer.from(process.argv[3], 'base64');

const crypto = require('crypto');

const salt = data.subarray(0, 16);
const key = crypto.scryptSync(password, salt, 32);
const iv = data.subarray(16, 32);

const decipher = crypto.createDecipheriv('AES-256-CBC', key, iv);

const aesbuf = data.subarray(32);
let decrypted = decipher.update(aesbuf, null, 'utf8');
decrypted += decipher.final('utf8');

console.log(decrypted);

are functional (but definitely not cryptographically reviewed) scripts to do encryption using the Node standard library.

@webknjaz
Copy link
Author

webknjaz commented Feb 3, 2020

@leo60228 those snippets use AES which is symetric encryption. It's safer to use asymentric algorithms and sign the data with a public key of the person that is supposed to read the message. In this case, only the owner of the corresponding private key can decrypt it. So basically, if that gets leaked, the attacker will be able to only encrypt messages but not to read them.

@sbc100
Copy link

sbc100 commented Feb 7, 2020

With CircleCI they somehow manage to install the public SSH key of the logged-in users so only the currently logged into github users (or someone with their key) can connect.

I guess that is easier since the "enable SSH" is an even triggered via the web interface. Its really a shame this isn't just a native feature of github actions (Re-run with ssh access), since normally you only want to enable ssh for individual runs that are failing for some reason.

@FedericoCeratto
Copy link

https://tmate.io/

Only allow SSH clients with specific public keys to connect to the session. To do so, create an authorized_keys file containing public keys that are allowed to connect. In this example, we'll reuse the one sshd uses, namely ~/.ssh/authorized_keys. Then, specify the authorized keys file via the tmate CLI using -a as such: tmate -a ~/.ssh/authorized_keys

@leo60228
Copy link

leo60228 commented Mar 3, 2020

See https://github.com/leo60228.keys as well.

@leo60228
Copy link

leo60228 commented Mar 3, 2020

This seems to be the best way of handling this:

  1. Make a GET request to https://api.github.com/repos/{owner}/{repo}/collaborators.
  2. For all users with permissions.admin, make a request to {user.url}/keys (ex. https://api.github.com/users/leo60228/keys.
  3. Concatenate every key field of every entry in each user's array into a temporary file.
  4. Pass -a file to tmate.

@leo60228
Copy link

leo60228 commented Mar 3, 2020

From my understanding, https://github.com URLs aren't intended for use in scripts.

@webknjaz
Copy link
Author

webknjaz commented Mar 3, 2020

sweet

@cmfcmf
Copy link

cmfcmf commented Jun 6, 2020

  • Concatenate every key field of every entry in each user's array into a temporary file.

For reference, this is how to concatenate the keys of a single user:

curl -s https://api.github.com/users/cmfcmf/keys | jq '.[].key' --raw-output

@FedericoCeratto
Copy link

FedericoCeratto commented Jul 30, 2020

I have two more secure alternatives:

SSH over Tor:

mkdir ~/.ssh 
echo "<REPLACE_SSH_PUBKEY>" > ~/.ssh/authorized_keys 
chmod 600 ~/.ssh/authorized_keys 
chmod 770 ~/.ssh 
chmod 770 ~/ 
apt-get install -y --no-install-recommends tor 
echo "HiddenServiceDir /var/lib/tor/ssh/" >> /etc/tor/torrc 
echo "HiddenServicePort 22 127.0.0.1:22" >> /etc/tor/torrc 
systemctl reload tor 
echo "Connect using:" 
sleep 10 
echo "ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null runner@$(cat /var/lib/tor/ssh/hostname)" 

SSH over IPv6. Be aware that this exposes all running services to IPv6!

apt-get install --no-install-recommends -y miredo 
mkdir ~/.ssh 
echo "<REPLACE_SSH_PUBKEY>" > ~/.ssh/authorized_keys 
chmod 600 ~/.ssh/authorized_keys 
chmod 770 ~/.ssh 
chmod 770 ~/ 
echo "Connect using:" 
echo "  ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null runner@$(ip address show dev teredo scope global | awk '/inet6/ {print $2}' | cut -d'/' -f1)" 

@dscho
Copy link
Collaborator

dscho commented Nov 3, 2020

A couple of these suggestions seem really useful to me. At the same time, I don't think that the Action itself needs to be changed, but a Pull Request to add a hint to the README.md file would probably be useful. Maybe suggesting something like this:

- uses: DamianReeves/write-file-action
  with:
    path: ${{ env.home }}/.ssh/authorized_keys
    contents: ssh-rsa AAAAB[...]
    write-mode: append

@mvdbeek
Copy link

mvdbeek commented Jan 26, 2021

For the record, @dscho's approach works, but needed a few extra tweaks in my experience:

      - uses: DamianReeves/write-file-action@v1.0
        with:
          path: /home/runner/.ssh/authorized_keys
          contents: ssh-rsa AAAAB[...]
          write-mode: append
      - uses: DamianReeves/write-file-action@v1.0
        with:
          path: /home/runner/.tmate.conf
          contents: 'set tmate-authorized-keys "/home/runner/.ssh/authorized_keys"'
          write-mode: append
      - name: Setup tmate session
        uses: mxschmitt/action-tmate@v3

and then make sure to use a recent OS. On ubuntu-18.04 for instance you get tmate 2.2.1, which doesn't support set tmate-authorized-keys. Works fine on ubuntu-20.04.

@eine
Copy link

eine commented Feb 2, 2021

What about using a public key in a secret (which is exposed as an envvar)? That would allow using a key with a much limited scope, while using asymmetric encryption.

@dscho
Copy link
Collaborator

dscho commented Feb 5, 2021

The best idea would probably be to add a flag, say, limit-access-to-actor which uses this GitHub API call to retrieve the stored public SSH keys of the user who triggered the workflow.

dscho added a commit to dscho/action-tmate that referenced this issue Feb 5, 2021
One quite valid concern with running tmate in a GitHub workflow is that
_anybody_ can connect to the opened session. This is particularly
problematic when secret information was laid down to disk.

To address this concern, this commit introduces the Boolean input
`limit-access-to-actor`. When it is set to `true`, the Action will
install the public SSH key(s) registered with the GitHub profile of the
actor (i.e. the user triggering the workflow).

For more information how publich SSH keys can be registered, see:
https://docs.github.com/en/github/.authenticating-to-github/adding-a-new-ssh-key-to-your-github-account

If no SSH keys are registered, and the `limit-access-to-actor` input is
set to `true`, the Action will complain loudly and fail.

This closes mxschmitt#2.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
@dscho
Copy link
Collaborator

dscho commented Feb 5, 2021

The best idea would probably be to add a flag, say, limit-access-to-actor which uses this GitHub API call to retrieve the stored public SSH keys of the user who triggered the workflow.

#39 implements this idea.

@dscho
Copy link
Collaborator

dscho commented Feb 6, 2021

@mxschmitt I think this ticket may be closed now?

@mxschmitt
Copy link
Owner

Yup, thank you so much for implementing that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

9 participants