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

SSH based commit and push signing #18197

Closed
adam-moss opened this issue Oct 7, 2022 · 15 comments · Fixed by #29550
Closed

SSH based commit and push signing #18197

adam-moss opened this issue Oct 7, 2022 · 15 comments · Fixed by #29550
Labels
core:git Related to our git platform layer priority-3-medium Default priority, "should be done" but isn't prioritised ahead of others status:requirements Full requirements are not yet known, so implementation should not be started type:feature Feature (new functionality)

Comments

@adam-moss
Copy link
Contributor

What would you like Renovate to be able to do?

Add support for ssh based commit and push signing

If you have any ideas on how this should be implemented, please tell us here.

Pretty much the same way as the existing gnupg signing, but with ssh instead

Is this a feature you are interested in implementing yourself?

Maybe

@adam-moss adam-moss added priority-5-triage status:requirements Full requirements are not yet known, so implementation should not be started type:feature Feature (new functionality) labels Oct 7, 2022
@rarkins rarkins added priority-3-medium Default priority, "should be done" but isn't prioritised ahead of others core:git Related to our git platform layer and removed priority-5-triage labels Oct 10, 2022
@rarkins
Copy link
Collaborator

rarkins commented Oct 10, 2022

Leaving this as status:requirements because I think more details/planning are required first

@adam-moss
Copy link
Contributor Author

adam-moss commented Oct 15, 2022

Ideally in the config we'd be able to specify an SSH private key as the value to gitPrivateKey

We'd then need an additional attribute gitPrivateKeyType which could be either ssh or gpg, defaulting to gpg to maintain existing capability/be a non-breaking change.. Alternatively this could be inferred from the value itself potentially.

As with existing gpg signing functionality, we'd then git config the user.signingkey and commit.gpgsign attributes alongside the gpg.format attribute to ssh or gpg.

That should be all that is required, so I guess the big question is whether to explicitly state the key type or whether to automagically infer it.

@adam-moss
Copy link
Contributor Author

For ssh keys we wouldn't need to do

await importKey();

and we'd need to add an addition to set gpg.format

await exec(`git config user.signingkey ${keyId!}`, { cwd });

@rarkins
Copy link
Collaborator

rarkins commented Oct 15, 2022

If we can infer the key type, let's do that instead or requiring the user to specify it.

@adam-moss
Copy link
Contributor Author

GitLab have merged changes to show Verified/Unverified on ssh key signing now alongside the provisioning of keys as Auth, Sign, or Auth and Sign.

@rarkins rarkins added status:requirements Full requirements are not yet known, so implementation should not be started and removed status:requirements Full requirements are not yet known, so implementation should not be started labels Oct 1, 2023
@renovatebot renovatebot deleted a comment from wlodarcp Nov 8, 2023
@davinkevin
Copy link

FYI, I use renovate with signed commit & SSH.

I just mounted the required gitconfig file and ssh keys where they are expected, and it just worked.

https://gitlab.com/davinkevin.fr/home-server/-/tree/main/renovate/overlays/k8s-server?ref_type=heads

And verified in GitLab UI:
image

@adam-moss
Copy link
Contributor Author

I haven't implemented it directly in reno as we've moved over to ephemeral keys using gitsign with sigstore backed off an internal pki.

@sisp
Copy link
Contributor

sisp commented Jun 6, 2024

There seems to be a quirk with SSH-based signing. GPG-based signing requires one file, and technically SSH-based signing also needs only one file (the private SSH key), but ssh-keygen -Y sign ..., which gets called by git commit -S ... under the hood, currently requires also the public SSH key. So, with a naive implementation, Renovate would need both the private and public SSH keys for SSH-based commit signing (see a workaround at the very bottom).

This is a reproduction of the problem, which I ran in an interactive ghcr.io/renovatebot/renovate container in a temporary directory:

# Create a new SSH keypair without a passphrase
$ ssh-keygen -t ed25519 -C "renovate" -N "" -f /tmp/id_renovate
Generating public/private ed25519 key pair.
Your identification has been saved in /tmp/id_renovate
Your public key has been saved in /tmp/id_renovate.pub
The key fingerprint is:
...

# Delete the public key
$ rm /tmp/id_renovate.pub

# Restrict access permissions for the private key
$ chmod 400 /tmp/id_renovate

# Create a test repository and enable SSH-based commit signing
$ mkdir /tmp/test-repository
$ cd /tmp/test-repository
$ git init
$ git config user.name renovate
$ git config user.email [email protected]
$ git config commit.gpgsign true
$ git config gpg.format ssh
$ git config user.signingkey /tmp/id_renovate

# Add a test file and commit it
$ touch test.txt
$ git add .
$ GIT_TRACE=1 git commit -m "init"
07:45:27.414752 git.c:465               trace: built-in: git commit -m init
07:45:27.415631 run-command.c:657       trace: run_command: ssh-keygen -Y sign -n git -f /tmp/id_renovate /tmp/.git_signing_buffer_tmpeSEfAe
error: Couldn't load public key /tmp/id_renovate: No such file or directory?

fatal: failed to write commit object

The same command sequence – without deleting the public key – passes successfully.

I've submitted a PR to address this unnecessary constraint: openssh/openssh-portable#499

As a workaround, we can generate the public SSH key from the private SSH key just to satisfy ssh-keygen -Y sign ...:

ssh-keygen -y -f <private_key_file> > <public_key_file>

@rarkins
Copy link
Collaborator

rarkins commented Jun 6, 2024

Thanks for the research. The public key will be different each time it's generated, right? Will that be ok? Ie it doesn't need to match the public key on the git host. Or is it deterministic and rhetorical same every time?

@sisp
Copy link
Contributor

sisp commented Jun 6, 2024

No, the public key is always the same for a given private key.

@rarkins
Copy link
Collaborator

rarkins commented Jun 6, 2024

Maybe Renovate could generate the public key once only too, if your request to the upstream lib is not addressed quickly

@sisp
Copy link
Contributor

sisp commented Jun 6, 2024

Do you mean once per run in contrast to once per project that Renovate updates?

@rarkins
Copy link
Collaborator

rarkins commented Jun 6, 2024

Yes

@sisp
Copy link
Contributor

sisp commented Jun 6, 2024

Ah, yes, that's definitely an easy optimization.

@renovate-release
Copy link
Collaborator

🎉 This issue has been resolved in version 38.46.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
core:git Related to our git platform layer priority-3-medium Default priority, "should be done" but isn't prioritised ahead of others status:requirements Full requirements are not yet known, so implementation should not be started type:feature Feature (new functionality)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants