sbt / sbt-pgp

PGP plugin for sbt
Other
144 stars 56 forks source link

support GPG 2.1 and above #173

Closed larochef closed 3 years ago

larochef commented 4 years ago

steps

On my ci environment, I have a version 2.2.x of gpg installed.

[root@57b8f3e6e977 /]# gpg --version
gpg (GnuPG) 2.2.17
libgcrypt 1.8.5
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /root/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

My build image is publicly available on the docker hub at makeorg/docker-sbt I'm passing the passphrase as an environment variable, using the PGP_PASSPHRASE.

I'm using the sbt-ci-release plugin which does the glue. I believe it calls publishSigned.

using latest sbt / sbt-pgp version 2.0.1

problem

When the signing part occurs I have the following error:

[info] Done compiling.
[error] gpg: signing failed: No such file or directory
[error] gpg: signing failed: No such file or directory
[error] java.lang.RuntimeException: Failure running 'gpg --batch --passphrase *********************** --detach-sign --armor --use-agent --output /some/output/file /some/input/file.  Exit code: 2
[error]     at scala.sys.package$.error(package.scala:30)
[error]     at com.jsuereth.sbtpgp.CommandLineGpgSigner.sign(PgpSigner.scala:42)
[error]     at com.jsuereth.sbtpgp.PgpSettings$.$anonfun$signingSettings$2(PgpSettings.scala:151)
[error]     at scala.collection.TraversableLike.$anonfun$flatMap$1(TraversableLike.scala:245)
[error]     at scala.collection.immutable.Map$Map4.foreach(Map.scala:236)
[error]     at scala.collection.TraversableLike.flatMap(TraversableLike.scala:245)
[error]     at scala.collection.TraversableLike.flatMap$(TraversableLike.scala:242)
[error]     at scala.collection.AbstractTraversable.flatMap(Traversable.scala:108)
[error]     at com.jsuereth.sbtpgp.PgpSettings$.$anonfun$signingSettings$1(PgpSettings.scala:146)
[error]     at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error]     at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error]     at sbt.std.Transform$$anon$4.work(Transform.scala:67)
[error]     at sbt.Execute.$anonfun$submit$2(Execute.scala:281)
[error]     at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:19)
[error]     at sbt.Execute.work(Execute.scala:290)
[error]     at sbt.Execute.$anonfun$submit$1(Execute.scala:281)
[error]     at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error]     at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error]     at java.lang.Thread.run(Thread.java:748)
[error] (signedArtifacts) Failure running 'gpg --batch --passphrase *********************** --detach-sign --armor --use-agent --output /some/intput/file /some/output/file'.  Exit code: 2

expectation

Signs correctly.

notes

With gpg 2.x a new parameter becomes mandatory to use the --passphrase parameter, in order for the command line to work properly, we should add --pinentry-mode loopback, else, the command line will want us to enter the key, which is not possible for instance in a CI environment.

Unfortunately, this parameter doesn't exist il older version of gpg and the command line will throw an error occurs.

The code here continues working on ubuntu 16.04 (in docker at least), but will break with an ubuntu 19.10.

larochef commented 4 years ago

For those having the issue, here is the workaround I just used with success:

I created a pgp.sh file in my project (with execution rights)

#! /bin/sh

gpg --pinentry-mode loopback $@

and I then replaced the gpg command, I had to do it in my build.sbt, doing it in ~/.sbt/gpg.sbt didn't get me any result:

Global / gpgCommand := (baseDirectory.value / "gpg.sh").getAbsolutePath

I hope it can help

eed3si9n commented 4 years ago

@larochef Could you clarify steps, problem, and expectation please?

  1. Which version of gpg do you have on the CI environment? How are you planning to pass in the passphrase?
  2. What command or task did you run in sbt?
  3. Exact output or observation of the current problem.
  4. What do you expect instead?

Note that you can pass passphrase to sbt-pgp by setting PGP_PASSPHRASE environment variable.

larochef commented 4 years ago

Hi Eugene,

On my ci environment, I have a version 2.2.x of gpg installed.

[root@57b8f3e6e977 /]# gpg --version
gpg (GnuPG) 2.2.17
libgcrypt 1.8.5
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /root/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2

My build image is publicly available on the docker hub at makeorg/docker-sbt I'm passing the passphrase as an environment variable, using the PGP_PASSPHRASE.

I'm using the sbt-ci-release plugin which does the glue. I believe it calls publishSigned.

When the signing part occurs I have the following error:

[info] Done compiling.
[error] gpg: signing failed: No such file or directory
[error] gpg: signing failed: No such file or directory
[error] java.lang.RuntimeException: Failure running 'gpg --batch --passphrase *********************** --detach-sign --armor --use-agent --output /some/output/file /some/input/file.  Exit code: 2
[error]     at scala.sys.package$.error(package.scala:30)
[error]     at com.jsuereth.sbtpgp.CommandLineGpgSigner.sign(PgpSigner.scala:42)
[error]     at com.jsuereth.sbtpgp.PgpSettings$.$anonfun$signingSettings$2(PgpSettings.scala:151)
[error]     at scala.collection.TraversableLike.$anonfun$flatMap$1(TraversableLike.scala:245)
[error]     at scala.collection.immutable.Map$Map4.foreach(Map.scala:236)
[error]     at scala.collection.TraversableLike.flatMap(TraversableLike.scala:245)
[error]     at scala.collection.TraversableLike.flatMap$(TraversableLike.scala:242)
[error]     at scala.collection.AbstractTraversable.flatMap(Traversable.scala:108)
[error]     at com.jsuereth.sbtpgp.PgpSettings$.$anonfun$signingSettings$1(PgpSettings.scala:146)
[error]     at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error]     at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error]     at sbt.std.Transform$$anon$4.work(Transform.scala:67)
[error]     at sbt.Execute.$anonfun$submit$2(Execute.scala:281)
[error]     at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:19)
[error]     at sbt.Execute.work(Execute.scala:290)
[error]     at sbt.Execute.$anonfun$submit$1(Execute.scala:281)
[error]     at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error]     at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error]     at java.lang.Thread.run(Thread.java:748)
[error] (signedArtifacts) Failure running 'gpg --batch --passphrase *********************** --detach-sign --armor --use-agent --output /some/intput/file /some/output/file'.  Exit code: 2

From what I've read, this parameter has become mandatory in version 2.1 of gpg

@eed3si9n do you need more information on it?

eed3si9n commented 4 years ago

@larochef Thanks I think I've got everything.

https://www.gnupg.org/documentation/manuals/gnupg/GPG-Esoteric-Options.html#GPG-Esoteric-Options says

--passphrase string Use string as the passphrase. This can only be used if only one passphrase is supplied. Obviously, this is of very questionable security on a multi-user system. Don’t use this option if you can avoid it.

Note that since Version 2.0 this passphrase is only used if the option --batch has also been given. Since Version 2.1 the --pinentry-mode also needs to be set to loopback.