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

Support git commit signing using OpenPGP #1544

Merged
merged 14 commits into from
Mar 24, 2024

Conversation

hendrikmaus
Copy link
Contributor

@hendrikmaus hendrikmaus commented Feb 13, 2023

This Pull Request fixes/closes #97.

It changes the following:

  • Add a new trait called Sign
  • Implement Sign for gpg commit signing via shellout
    • Users with a working signing setup will find that it just works in gitui as well
  • Add entrypoints for all natively supported methods
  • Add potential entrypoint for pure rust implementations behind a gitconfig value of gitui.signing_methods

I followed the checklist:

  • I added unittests
  • I ran make check without errors
  • I tested the overall application
  • I added an appropriate item to the changelog

Todo:

  • Test in Windows 🪟
  • Documentation
  • Draft an isolated integration test running in a container

Draft an isolated integration test running in a container

Since shellouts call out to actual system binaries, @extrawurst and I came up with the idea to create a test that runs in the isolation of a container. Inside of that environment, it could generate a GPG key and do an actual commit to verify the signature was created as expected.

Update: will be tracked in a follow-up issue.

@hendrikmaus hendrikmaus mentioned this pull request Feb 13, 2023
@hendrikmaus
Copy link
Contributor Author

Will attend to the failures in CI within the next days.

@ZCShou
Copy link

ZCShou commented Feb 20, 2023

waiting for this feature ready

@hendrikmaus
Copy link
Contributor Author

Looking into the CI errors again now.

@hendrikmaus
Copy link
Contributor Author

hendrikmaus commented Feb 20, 2023

🆗 ✅ The previous error was caused by a doctest I added. The other unit tests prepare their environment, the doctest does not. Since I added it as documentation only, I deactivated the doctest and the CI run in my fork was good now: https://github.com/hendrikmaus/gitui/actions/runs/4221076989

@extrawurst if you'd approve another CI run here, thanks.

@melMass
Copy link

melMass commented Mar 14, 2023

Hey just checking the status of this PR?
I can test on macOS and windows easily if needed :)

@hendrikmaus
Copy link
Contributor Author

Both would be appreciated, thank you.

@utkarshgupta137
Copy link
Contributor

Tested it on macOS. Authoring commits works fine, but some simple operations like amending & rewording the last commit don't work. I've created a PR with workarounds: hendrikmaus#1.

@tmikeschu
Copy link

👋 hello! Any movement on this by chance? Thanks!

@ZCShou
Copy link

ZCShou commented Apr 26, 2023

👋 hello! Any movement on this by chance? Thanks!

I‘m also waiting for this feature

@hendrikmaus
Copy link
Contributor Author

hendrikmaus commented Apr 26, 2023

Haven’t had time to continue, but will do so in the beginning of May June (sry for the delay).

Will tackle these:

  • Fix amending and rewording, thanks @utkarshgupta137 for already preparing a change-set
  • Align configuration with the existing pattern (in progress)
  • Test on Windows
  • Documentation
  • Integration test

@nrabulinski
Copy link

Hey, how's the progress on this? :)

@hendrikmaus
Copy link
Contributor Author

Can someone test a current build on a Windows environment? I'd appreciate that.

@damccull
Copy link

damccull commented Jun 8, 2023

To test this, would we need to download this PR's code, compile, and run? Or is there some auto-generated binary for testing I should download somewhere?

@hendrikmaus
Copy link
Contributor Author

At this point there are no pre-compiled binaries. So you have to download and compile it.

@SirusCodes
Copy link

I compiled it with cargo install gitui and tried to run the binary from .cargo dir but it is showing me the same error. I might be doing something wrong...

PS: I don't have experience in working with Rust.

image

@hendrikmaus
Copy link
Contributor Author

I reckon you compiled the master branch as that is the error that was shown before this initiative started.
Here is the zip file of my branch on github: https://github.com/hendrikmaus/gitui/archive/refs/heads/gpg-commit-signing.zip

@Sped0n
Copy link

Sped0n commented Jun 17, 2023

works like a charm on ventura👌

just want this pr to be merged as soon as possible

image

@Sped0n
Copy link

Sped0n commented Jun 17, 2023

I compiled it with cargo install gitui and tried to run the binary from .cargo dir but it is showing me the same error. I might be doing something wrong...

PS: I don't have experience in working with Rust.

image

maybe install with command below?

cargo install --git https://github.com/hendrikmaus/gitui --branch gpg-commit-signing

@eclairevoyant
Copy link

eclairevoyant commented Jun 20, 2023

@hendrikmaus works for me on windows 11 (built with rust using MSVC toolchain, GnuPG as program for signing)

  • Password prompt appears correctly when signing is enabled by default
  • Commits are in fact signed (verified with git log --show-signature)

@hendrikmaus
Copy link
Contributor Author

Thank you for the feedback, that is good news.

@hendrikmaus
Copy link
Contributor Author

@extrawurst re configuration.

As we were talking about this the other day, did you take another look at the available approaches? I.e. .gitconfig file versus the gitui options?

@damccull
Copy link

Well, I installed it from the git repo and it definitely tries to sign now. However, I'm using my ssh key to sign rather than a gpg key and it says that's unsupported. Would this capability be difficult to add?

@hendrikmaus
Copy link
Contributor Author

@damccull out of scope here, but the change-set already prepares an entry point for that in the code. There is another open issue about signing with ssh keys in #1149

@damccull
Copy link

Ah, thanks.

@hendrikmaus
Copy link
Contributor Author

@extrawurst re configuration.

As we were talking about this the other day, did you take another look at the available approaches? I.e. .gitconfig file versus the gitui options?

I think it would be feasible to pass a new optional struct with the signing options down into the asyncgit crate from here: https://github.com/hendrikmaus/gitui/blob/24bb8ac57e2f7c8320eb4e6b75c8dc4739b6b7e0/src/components/commit.rs#L274

The asyncgit::sync::commit function has more than 40 call sites, mostly tests, that would need to be adjusted. The signatures of asyncgit::sync::reword and asyncgit::sync::amend would also be affected as they call commit.

I would propose something like Option<CommitConfig> to implement it open for extension. We might see the need to pass more configurations down to commit and I wouldn't want to limit it to only the signing options now. What do you think @extrawurst ?

@1vnt
Copy link

1vnt commented Jul 19, 2023

Any updates on this?

@hendrikmaus
Copy link
Contributor Author

I’ll have a look and verify that.

@hendrikmaus
Copy link
Contributor Author

Did not mean to close this. Was updating the PR.

@extrawurst
Copy link
Owner

extrawurst commented Mar 23, 2024

ok lets reopen :)

Screenshot 2024-03-23 at 11 39 50

these will be tracked in another issue
…signing

* 'master' of github.com:extrawurst/gitui: (52 commits)
  Git Config Commit Comments (extrawurst#2145)
  update changelog for 0.25.2
  fix another github action warning
  upgrade version
  prepare release
  preapre for release
  changelog
  fixes tag annotation being broken in 0.25 (extrawurst#2139)
  update changelog
  fix: 2114
  Bump backtrace from 0.3.69 to 0.3.70
  Fixed: - Cargo clippy errors
  cargo updates
  cargo update
  todo
  update changelog
  fix: index out of bounds when blaming a file ending with a blank line (extrawurst#2130)
  Bump bitflags from 2.4.2 to 2.5.0
  Bump clap from 4.5.2 to 4.5.3
  fix chrono deprecations
  ...
@hendrikmaus hendrikmaus reopened this Mar 23, 2024
@hendrikmaus
Copy link
Contributor Author

We're back ;)

@hendrikmaus
Copy link
Contributor Author

Removed the testing files, as discussed, and will track them in a new issue later.

Now taking a look at the ssh signing PR to see if it could easily be refactored to use the Sign trait.

@hendrikmaus
Copy link
Contributor Author

The steps should roughly be:

  • move the logic of fn fetch_ssh_key(config: &Config) -> Option<PrivateKey> to SignBuilder::from_gitconfig's match arm for ssh
  • create smth like pub struct SSHSign and implement Sign for it using sk.sign which is all that is needed once the keypair was found
  • the logic in the commit function does not need to change as it uses whatever the SignBuilder returns to sign the data. That is given the ssh signing also works on the commit's UTF-8 data
    • the Sign impl expects a UTF-8 encoded string slice, while the ssh impl seems to sign the buffer byte slice; will do a quick check to see I should change the trait to accept a byte slice as well

@hendrikmaus
Copy link
Contributor Author

According to git's documentation, commits are encouraged to be UTF-8, but any encoding can be used. So the raw bytes of the commit buffer should be signed rather than converting it to UTF-8 first.

Will implement the change in the Sign trait.

@hendrikmaus
Copy link
Contributor Author

Done.

@hendrikmaus hendrikmaus requested a review from extrawurst March 23, 2024 19:31
@hendrikmaus
Copy link
Contributor Author

@extrawurst if you would approve the CI run, this is ready to be merged.

let sign = SignBuilder::from_gitconfig(&repo, &config)?;
let signed_commit = sign.sign(&buffer)?;
let commit_id =
repo.commit_signed(commit, &signed_commit, None)?;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to support more than just gpg the third parameter signature_field needs to take something out of sign which in this case has to be gpgsig but something else for ssh

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to support more than just gpg the third parameter signature_field needs to take something out of sign which in this case has to be gpgsig but something else for ssh

I very much wish for ssh signing. I don't PGP/GPG but i ssh all the time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@damccull this one only adds openpgp; there is another PR that wants to add ssh signing. @extrawurst wants them to adopt the Sign trait once this one here is merged though.

@extrawurst
Copy link
Owner

another followup: this does not sign tags

Repository owner deleted a comment from damccull Mar 24, 2024
@extrawurst extrawurst merged commit 5b3e2c9 into extrawurst:master Mar 24, 2024
17 of 18 checks passed
@extrawurst
Copy link
Owner

wohooooo its merged! @hendrikmaus thanks for sticking with this through the end. could you please write an issue with the way you planned to do actual testing of this in CI via docker? also ideally pointing to the commits you reverted as inspiration, so that someone can take that up!

@hendrikmaus
Copy link
Contributor Author

hendrikmaus commented Mar 24, 2024

another followup: this does not sign tags

@extrawurst correct. it tags a signed commit just fine, but the tag itself isn't signed due to that. The way git signs tags is different from how it is done for commits. I will open an issue with git2-rs to see if there is more information on it since I cannot seem to find anything in the docs that hints how to sign a tag.

I prepped the trait to differ between signing commits and tags, but I won't provide an implementation for tags with this PR.

IndianBoy42 pushed a commit to IndianBoy42/gitui that referenced this pull request Jun 4, 2024
* Support git commit signing using OpenPGP
* workaround for amending signed commits
* workaround for rewording signed commits
* support signing initial commit
* return both signature and signature_field value from sign

---------

Co-authored-by: Utkarsh Gupta <utkarshgupta137@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

GPG sign commits