Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

maven-gpg-plugin failing with "Inappropriate ioctl for device" when running under Jenkins

When Jenkins triggers maven-gpg-plugin in a remote Linux shell it fails with gpg: signing failed: Inappropriate ioctl for device. This used to work until recently. I don't know what changed.

I found a lot of online references suggesting export GPG_TTY=$(tty) but this doesn't work for ssh connections as tty is null. Any ideas?

like image 907
Gili Avatar asked Jan 01 '19 04:01

Gili


2 Answers

I found an excellent explanation over at https://myshittycode.com/2017/08/07/maven-gpg-plugin-prevent-signing-prompt-or-gpg-signing-failed-no-such-file-or-directory-error/

I will re-post the gist of the post in case the page goes down:

If you 1) initially had it working in the past, and 2) have tried all sorts of solutions from the web, and still couldn’t get it working, chances are you have unconsciously upgraded GPG version from 2.0 to 2.1.

Sounds about right...

To fix this, GPG 2.1 requires --pinentry-mode to be set to loopback in order to pick up gpg.passphrase value defined in Maven settings.xml.

So, update Maven GPG Plugin configuration in pom.xml to the following:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>1.6</version>
    <executions>
        <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
                <goal>sign</goal>
            </goals>
            <configuration>
                <gpgArguments>
                    <arg>--pinentry-mode</arg>
                    <arg>loopback</arg>
                </gpgArguments>
            </configuration>
        </execution>
    </executions>
</plugin>
like image 200
Gili Avatar answered Oct 17 '22 10:10

Gili


To build on Gili's answer:

Rather than modify every pom.xml to make Jenkins happy, you can add the following to ~/.gnupg/gpg.conf on Jenkins slaves with newer gpg:

pinentry-mode loopback

Puppet

You can also automate this. I'm using puppet to create gpg.conf files with this entry if gpg version is 2.1 or higher:

Template

<% if scope.lookupvar("gpg_version").to_f >= 2.1 %>
pinentry-mode loopback
<% end %>

Fact

Facter.add("gpg_version") do
  setcode do

    result = ''
    begin
      first_line = `gpg --version`.split("\n")[0]
      match = first_line.match /.* ([0-9\.]*)$/
      result = match[1]
    rescue

    end
    result
  end
end

like image 2
Akom Avatar answered Oct 17 '22 11:10

Akom