Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-40703

Support injection of maven-gpg-plugin:sign config params in Maven Settings files

      When signing artifacts with GPG, Maven apps usually rely on the Maven GPG Plugin and thus store secrets in Maven settings.xml.

      These secrets should be handled by the Jenkins Config File Provider Plugin.

      Key configuration parameters that should be handled by the Config File Provider Plugin:

      http://maven.apache.org/plugins/maven-gpg-plugin/sign-mojo.html

      • gpg.keyname: The "name" of the key to sign with. Passed to gpg as --local-user.
      • gpg.passphrase: The passphrase to use when signing. If not given, look up the value under Maven settings using server id at 'passphraseServerKey' configuration.
      • gpg.passphraseServerId: Server id to lookup the passphrase under Maven settings.
      • gpg.useagent: Server id to lookup the passphrase under Maven settings.
      • gpg.homedir
      • gpg.publicKeyring: The path to a public keyring to add to the list of keyrings. By default, only the pubring.gpg from gpg's home directory is considered. Use this option (and defaultKeyring if required) to use a different public key. Note: Relative paths are resolved against gpg's home directory, not the project base directory.
      • gpg.secretKeyring: The path to a secret keyring to add to the list of keyrings. By default, only the secring.gpg from gpg's home directory is considered. Use this option (in combination with publicKeyring and defaultKeyring if required) to use a different secret key. Note: Relative paths are resolved against gpg's home directory, not the project base directory.
        gpg.useagent: Passes --use-agent or --no-use-agent to gpg. If using an agent, the passphrase is optional as the agent will provide it. For gpg2, specify true as --no-use-agent was removed in gpg2 and doesn't ask for a passphrase anymore.
      • gpg.defaultKeyring: Whether to add the default keyrings from gpg's home directory to the list of used keyrings.
      • gpg.homedir: The directory from which gpg will load keyrings. If not specified, gpg will use the value configured for its installation, e.g. ~/.gnupg or %APPDATA%/gnupg.

      Maybe we should also consider http://kohsuke.org/pgp-maven-plugin but I'm not sure that this plugin is widely adopted and actively maintained.

      References:

      • https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration.html
        • ~/.gnupg This is the default home directory which is used if neither the environment variable GNUPGHOME nor the option --homedir is given.
        • ~/.gnupg/pubring.gpg : The public keyring.
        • ~/.gnupg/secring.gpg: The private keyring (used by GnuPG versions before 2.1. It is not used by GnuPG 2.1 and later).
        • ~/.gnupg/trustdb.gpg The trust database. There is no need to backup this file; it is better to backup the ownertrust values (see option --export-ownertrust).

          [JENKINS-40703] Support injection of maven-gpg-plugin:sign config params in Maven Settings files

          Maybe it makes more sense to offer this feature through the credentials binding plugin.

          Cyrille Le Clerc added a comment - Maybe it makes more sense to offer this feature through the credentials binding plugin.

          would you expect the config-file-provider plugin to inject these settings as properties into the settings.xml?

          Dominik Bartholdi added a comment - would you expect the config-file-provider plugin to inject these settings as properties into the settings.xml ?

          imod I tend to think that my initial writing "Support injection of maven-gpg-plugin:sign config params in Maven Settings files" is not good, that it's not about Maven settings.xml and that maven-gpg-plugin credentials should be handled by the withMaven(){...} plugin.

          I feel that there is no perfect solution because there is an inconsistency in Maven itself with most credentials handled in settings.xml through "<server>" definitions but some credentials used by some plugins bypass this <server> mechanism to directly consume credentials.

          • Maybe it should be a withGpg(){...} wrapping step that would expose the GPG keys through environment variables. The problem is that the environment variables consumed by the maven-gpg-plugin (gpg.secretKeyring, gpg.passphrase...) are specific to this plugin and are not standard to GPG --> we don't want the "withGpg(){...}" wrapping step to have a "logical dependency" on Maven
          • Maybe we do it with the Jenkins config-file-provider plugin because it is the plugin in which we handle credentials consumed by Maven but it is awkward because the config-file-provider plugin is about Maven settings.xml and credentials consumed by the maven-gpg-plugin are not managed in settings.xml but in pom.xml and through default environment variable names
          • Maybe we should do it in the withMaven(){...}. The "small glitch" I see is that most of credentials used by Maven builds are managed in settings.xml through the Jenkins config-file-provider plugin and we would do something inconsistent for GPG credentials.

          Cyrille Le Clerc added a comment - imod I tend to think that my initial writing "Support injection of maven-gpg-plugin:sign config params in Maven Settings files" is not good, that it's not about Maven settings.xml and that maven-gpg-plugin credentials should be handled by the withMaven(){... } plugin. I feel that there is no perfect solution because there is an inconsistency in Maven itself with most credentials handled in settings.xml through " <server> " definitions but some credentials used by some plugins bypass this <server> mechanism to directly consume credentials. Maybe it should be a withGpg(){... } wrapping step that would expose the GPG keys through environment variables. The problem is that the environment variables consumed by the maven-gpg-plugin ( gpg.secretKeyring , gpg.passphrase ...) are specific to this plugin and are not standard to GPG --> we don't want the " withGpg(){... }" wrapping step to have a "logical dependency" on Maven Maybe we do it with the Jenkins config-file-provider plugin because it is the plugin in which we handle credentials consumed by Maven but it is awkward because the config-file-provider plugin is about Maven settings.xml and credentials consumed by the maven-gpg-plugin are not managed in settings.xml but in pom.xml and through default environment variable names Maybe we should do it in the withMaven(){... }. The "small glitch" I see is that most of credentials used by Maven builds are managed in settings.xml through the Jenkins config-file-provider plugin and we would do something inconsistent for GPG credentials.

          hmm, yeah - strange situation.

          ...to be honest: as a user, I don't like the withXXX wrapper stuff - all this nested wrapping of code within the different closers are awkward and make the pipeline scripts very hard to read.

          Dominik Bartholdi added a comment - hmm, yeah - strange situation. ...to be honest: as a user, I don't like the withXXX wrapper stuff - all this nested wrapping of code within the different closers are awkward and make the pipeline scripts very hard to read.

          imod piling these wrappers reminds me stacktraces with Spring Framework. I have already discussed with jglick of the drawback of nesting these "withXxx(){...}" wrappers. I imagined to declare these wrappers at the "node(){...}" declaration level, it likely to not be the direction.
          The solution may come from Declarative Pipelines.

          Note that the "stage" step recently became a wrapper with "stage(){...}"

          Cyrille Le Clerc added a comment - imod piling these wrappers reminds me stacktraces with Spring Framework. I have already discussed with jglick of the drawback of nesting these " withXxx(){... }" wrappers. I imagined to declare these wrappers at the " node(){... }" declaration level, it likely to not be the direction. The solution may come from Declarative Pipelines. Note that the " stage " step recently became a wrapper with " stage(){... }"

          James Nord added a comment -

          sounds like this should just be withCredentials(...)  {...} and that there should be a GPG credential type.

          James Nord added a comment - sounds like this should just be withCredentials(...)  {... } and that there should be a GPG credential type.

          Good catch teilo! we are on the way to greatly simplify this integration.

          Cyrille Le Clerc added a comment - Good catch teilo ! we are on the way to greatly simplify this integration.

          Steve Todorov added a comment - - edited

          cleclerc do you know what is the state of this issue? We are currently preparing some jobs which will be using the `maven-gpg-plugin` to sign maven artifacts. However the only way this would ever work is by doing `mvn release:perform -Darguments=-Dgpg.passphrase=thephrase` and passing the password via the CLI is something we would like to avoid.

          Can't there just be a `Maven passphrase` credential kind which you can add in the credentials section and then from the `Config File Management` you can add the `serverid` to use the defined credentials?

          Steve Todorov added a comment - - edited cleclerc do you know what is the state of this issue? We are currently preparing some jobs which will be using the `maven-gpg-plugin` to sign maven artifacts. However the only way this would ever work is by doing `mvn release:perform -Darguments=-Dgpg.passphrase=thephrase` and passing the password via the CLI is something we would like to avoid. Can't there just be a `Maven passphrase` credential kind which you can add in the credentials section and then from the `Config File Management` you can add the `serverid` to use the defined credentials?

            domi Dominik Bartholdi
            cleclerc Cyrille Le Clerc
            Votes:
            5 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated: