eclipse-jgit / jgit

JGit, the Java implementation of git
https://www.eclipse.org/jgit/
Other
117 stars 33 forks source link

Signing service is not available #10

Closed pragmaxim closed 8 months ago

pragmaxim commented 8 months ago

Version

6.8.0.202311291450-r

Operating System

Linux/Unix

Bug description

Signing a commit fails when it is enabled in .gitconfig

Actual behavior

Doing :

git.commit().setMessage(message).setSigningKey(gpgID).call()

When :

cat ~/.gitconfig
[commit]
    gpgsign = true

leads to :

org.eclipse.jgit.api.errors.ServiceUnavailableException: Signing service is not available                        
        at org.eclipse.jgit.api.CommitCommand.sign(CommitCommand.java:328)                                                                                                                                                                     
        at org.eclipse.jgit.api.CommitCommand.call(CommitCommand.java:283)                                                    

see https://hub.spigotmc.org/jira/si/jira.issueviews:issue-html/BUILDTOOLS-536/BUILDTOOLS-536.html

Problem is that it is not really easy to sign git commits with Bouncy Castle at least IDK how.

Expected behavior

jgit should either succeed with the defailt GpgSigner or there should be easy alternative with BouncyCastle

Relevant log output

org.eclipse.jgit.api.errors.ServiceUnavailableException: Signing service is not available                        
        at org.eclipse.jgit.api.CommitCommand.sign(CommitCommand.java:328)                                                                                                                                                                     
        at org.eclipse.jgit.api.CommitCommand.call(CommitCommand.java:283)                                                    


### Other information

_No response_
tomaswolf commented 8 months ago

Do you have bundle org.eclipse.jgit.gpg.bc in your application? It provides the only signer implementation JGit has, and it does use BouncyCastle. JGit uses the Java ServiceLoader to find the implementation, so it must be on the classpath.

pragmaxim commented 8 months ago

So if I have it on a classpath and do this :

Security.addProvider(new BouncyCastleProvider())

Then :

git.commit().setMessage(message).setSigningKey(gpgID).call()

Would use the org.eclipse.jgit.gpg.bc.internal.BouncyCastleGpgSigner instead of the the system one?

tomaswolf commented 8 months ago

JGit by default does not include any implementation of GpgSigner. The only implementation we provide is the one in bundle org.eclipse.jgit.gpg.bc. So I have no idea what you mean by "the system GpgSigner".

JGit has no implementation of that interface that would use the gpg executable installed on the system.

It should not be necessary to install the BouncyCastleProvider. It will be installed automatically if needed.

pragmaxim commented 8 months ago

That is very strange ... I can sign my commits with git.commit().setMessage(message).setSigningKey(gpgID).call() even without having org.eclipse.jgit.gpg.bc on classpath fine unless .gitconfig contains :

[commit]
    gpgsign = true

So if it actually uses the BouncyCastle underneath, then something really reads the ~/.gitconfig ... I might debug it later

pragmaxim commented 8 months ago

@tomaswolf it needs explicit setting of CredentialsProvider and GpgSigner ... For future reference :

import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.gpg.bc.internal.BouncyCastleGpgSigner
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider
import java.io.File
import java.security.Security

Security.addProvider(new BouncyCastleProvider())
val git = Git.open(new File("/tmp/foo"))
val barFile = new File("/tmp/foo/bar")

git.add().addFilepattern(barFile.getName).call()
git.commit()
  .setMessage("test")
  .setCredentialsProvider(new UsernamePasswordCredentialsProvider("id", "passphrase"))
  .setGpgSigner(new BouncyCastleGpgSigner)
  .call()

Happy new year 2024!!!