Usage

Sign artifacts with GnuPG

Signs all of a project's attached artifacts with GnuPG.

You need to have previously configured the default key using GnuPG.

gpg also needs to be on the search path.

First you add the plugin to your pom.xml like this:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-gpg-plugin</artifactId>
        <version>3.2.2</version>
        <executions>
          <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
              <goal>sign</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Ideally, if invoked on workstation, you should rely on gpg-agent to collect passphrase from, as in that way no secrets will enter terminal history nor any file on disk. In agent-less (batch) sessions, typically on CI, you should provide passphrases via environment variable (see goals).

Note: When using the GPG Plugin in combination with the Maven Release Plugin, on a developer Workstation, you should rely on gpg-agent, but have it "primed", as Release plugin invokes build in batch mode, that will prevent agent to present the "pinentry pop up". If fully unattended release is being done, for example on a CI system, then with useAgent set to false one can pass the passphrase via environment variable.

To prime gpg-agent caches, one can perform simple "sign" operation on workstation like this echo "test" | gpg --clearsign or can use gpg command gpg-preset-passphrase.

General remark regarding environment variables: Examples below are NOT instructions how to invoke Maven, as if you'd follow these examples literally, it would defy the goal of not leaking cleartext passphrases, as these would end up in terminal history! You should set these environment variables on your own discretion in some secure manner.

MAVEN_GPG_PASSPHRASE=thephrase mvn release:perform

One "real life" example, on Un*x systems could be this:

read -s -p "Enter your GnuPG key passphrase: " MAVEN_GPG_PASSPHRASE; mvn release:perform

Finally, the passphrase can be given on the command line as well, but this is not recommended, and plugin will emit warnings. This mode of invocation is highly discouraged, as passphrase in cleartext is recorded into Terminal history.

mvn verify -Dgpg.passphrase=thephrase

Security considerations

In the future, plugin will operate in bestPractices mode enabled, and will fail the build if any violation of those is detected. The goal of this change was to protect plugin users from possible "leaks" of sensitive information (like passphrase is). Sensitive information like passphrases should never be stored on disks (plaintext or quasi-encrypted), nor should be used in way they may "leak" into other files (for example bash terminal history).

Hence, examples below will work by emit warnings. In the future, once "best practices" become enforced, these examples will not work anymore.

Configure passphrase in settings.xml

NOTE: These techniques below are highly discouraged. Ideally sensitive information should enter via gpg-agent or via environment variables.

Instead of specifying the passphrase on the command line, you can place it in your local settings.xml either in clear or encrypted text.

<settings>
  [...]
  <servers>
    [...]
    <server>
      <id>gpg.passphrase</id>
      <passphrase>clear or encrypted text</passphrase>
    </server>
  </servers>
</settings>

Configure passphrase in settings.xml with a keyname

To allow discovery of keyname and passphrase at build time, configure this plugin to map both keyname and passphraseServerId to a fixed property.

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-gpg-plugin</artifactId>
        <version>3.2.2</version>
        <executions>
          <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
              <goal>sign</goal>
            </goals>
            <configuration>
              <keyname>${gpg.keyname}</keyname>
              <passphraseServerId>${gpg.keyname}</passphraseServerId>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

and use local settings.xml to discover the passphrase via the keyname

<settings>
  [...]
  <servers>
    [...]
    <server>
      <id>your.keyname</id>
      <passphrase>clear or encrypted text</passphrase>
    </server>
  </servers>

  [...]
  <profiles>
    <profile>
      <id>my_profile_id</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <gpg.keyname>your.keyname</gpg.keyname>
      </properties>
    </profile>
  <profiles>
</settings>