1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.gpg;
20
21 import java.io.File;
22 import java.util.Collections;
23 import java.util.List;
24
25 import org.apache.maven.execution.MavenSession;
26 import org.apache.maven.plugin.AbstractMojo;
27 import org.apache.maven.plugin.MojoExecutionException;
28 import org.apache.maven.plugin.MojoFailureException;
29 import org.apache.maven.plugins.annotations.Component;
30 import org.apache.maven.plugins.annotations.Parameter;
31 import org.apache.maven.project.MavenProject;
32 import org.apache.maven.settings.Server;
33 import org.apache.maven.settings.Settings;
34 import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
35 import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
36 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
37 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
38
39
40
41
42 public abstract class AbstractGpgMojo extends AbstractMojo {
43 public static final String DEFAULT_ENV_MAVEN_GPG_KEY = "MAVEN_GPG_KEY";
44 public static final String DEFAULT_ENV_MAVEN_GPG_FINGERPRINT = "MAVEN_GPG_KEY_FINGERPRINT";
45 public static final String DEFAULT_ENV_MAVEN_GPG_PASSPHRASE = "MAVEN_GPG_PASSPHRASE";
46
47
48
49
50
51
52
53 @Parameter(property = "gpg.agentSocketLocations", defaultValue = ".gnupg/S.gpg-agent")
54 private String agentSocketLocations;
55
56
57
58
59
60
61
62
63
64
65
66
67 @Parameter(property = "gpg.keyFilePath", defaultValue = "maven-signing-key.key")
68 private String keyFilePath;
69
70
71
72
73
74
75 @Parameter(property = "gpg.keyFingerprint")
76 private String keyFingerprint;
77
78
79
80
81
82
83
84
85
86
87 @Parameter(property = "gpg.keyEnvName", defaultValue = DEFAULT_ENV_MAVEN_GPG_KEY)
88 private String keyEnvName;
89
90
91
92
93
94
95
96 @Parameter(property = "gpg.keyFingerprintEnvName", defaultValue = DEFAULT_ENV_MAVEN_GPG_FINGERPRINT)
97 private String keyFingerprintEnvName;
98
99
100
101
102
103
104
105 @Parameter(property = "gpg.passphraseEnvName", defaultValue = DEFAULT_ENV_MAVEN_GPG_PASSPHRASE)
106 private String passphraseEnvName;
107
108
109
110
111
112
113
114 @Parameter(property = "gpg.homedir")
115 private File homedir;
116
117
118
119
120
121
122
123
124
125
126 @Deprecated
127 @Parameter(property = GPG_PASSPHRASE)
128 private String passphrase;
129
130
131
132
133
134
135
136
137
138
139 @Deprecated
140 @Parameter(property = "gpg.passphraseServerId", defaultValue = GPG_PASSPHRASE)
141 private String passphraseServerId;
142
143
144
145
146 @Parameter(property = "gpg.keyname")
147 private String keyname;
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 @Parameter(property = "gpg.useagent", defaultValue = "true")
164 private boolean useAgent;
165
166
167
168
169
170
171
172 @Parameter(property = "gpg.executable")
173 private String executable;
174
175
176
177
178
179
180 @Parameter(property = "gpg.defaultKeyring", defaultValue = "true")
181 private boolean defaultKeyring;
182
183
184
185
186
187
188
189
190
191
192
193
194
195 @Deprecated
196 @Parameter(property = "gpg.secretKeyring")
197 private String secretKeyring;
198
199
200
201
202
203
204
205
206
207
208
209
210
211 @Deprecated
212 @Parameter(property = "gpg.publicKeyring")
213 private String publicKeyring;
214
215
216
217
218
219
220
221
222
223
224
225 @Parameter(property = "gpg.lockMode")
226 private String lockMode;
227
228
229
230
231 @Parameter(property = "gpg.skip", defaultValue = "false")
232 private boolean skip;
233
234
235
236
237
238
239
240
241
242
243
244
245
246 @Parameter
247 private List<String> gpgArguments;
248
249
250
251
252
253
254
255 @Parameter(property = "gpg.signer", defaultValue = GpgSigner.NAME)
256 private String signer;
257
258
259
260
261 @Component
262 protected MavenSession session;
263
264
265
266
267
268
269
270
271
272
273
274
275 @Parameter(property = "gpg.bestPractices", defaultValue = "false")
276 private boolean bestPractices;
277
278
279
280
281
282
283 @Parameter(defaultValue = "${settings}", readonly = true, required = true)
284 protected Settings settings;
285
286
287
288
289
290
291
292 @Deprecated
293 private final SecDispatcher secDispatcher =
294 new DefaultSecDispatcher(new DefaultPlexusCipher(), Collections.emptyMap(), "~/.m2/settings-security.xml");
295
296 @Override
297 public final void execute() throws MojoExecutionException, MojoFailureException {
298 if (skip) {
299
300 return;
301 }
302 if (bestPractices && (isNotBlank(passphrase) || isNotBlank(passphraseServerId))) {
303
304 throw new MojoFailureException(
305 "Do not store passphrase in any file (disk or SCM repository), rely on GnuPG agent or provide passphrase in "
306 + passphraseEnvName + " environment variable.");
307 }
308
309 doExecute();
310 }
311
312 protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
313
314 private void logBestPracticeWarning(String source) {
315 getLog().warn("");
316 getLog().warn("W A R N I N G");
317 getLog().warn("");
318 getLog().warn("Do not store passphrase in any file (disk or SCM repository),");
319 getLog().warn("instead rely on GnuPG agent or provide passphrase in ");
320 getLog().warn(passphraseEnvName + " environment variable for batch mode.");
321 getLog().warn("");
322 getLog().warn("Sensitive content loaded from " + source);
323 getLog().warn("");
324 }
325
326 protected AbstractGpgSigner newSigner(MavenProject mavenProject) throws MojoFailureException {
327 AbstractGpgSigner signer;
328 if (GpgSigner.NAME.equals(this.signer)) {
329 signer = new GpgSigner(executable);
330 } else if (BcSigner.NAME.equals(this.signer)) {
331 signer = new BcSigner(
332 session.getRepositorySession(),
333 keyEnvName,
334 keyFingerprintEnvName,
335 agentSocketLocations,
336 keyFilePath,
337 keyFingerprint);
338 } else {
339 throw new MojoFailureException("Unknown signer: " + this.signer);
340 }
341
342 signer.setLog(getLog());
343 signer.setInteractive(settings.isInteractiveMode());
344 signer.setKeyName(keyname);
345 signer.setUseAgent(useAgent);
346 signer.setHomeDirectory(homedir);
347 signer.setDefaultKeyring(defaultKeyring);
348 signer.setSecretKeyring(secretKeyring);
349 signer.setPublicKeyring(publicKeyring);
350 signer.setLockMode(lockMode);
351 signer.setArgs(gpgArguments);
352
353
354 String passphrase =
355 (String) session.getRepositorySession().getConfigProperties().get("env." + passphraseEnvName);
356 if (isNotBlank(passphrase)) {
357 signer.setPassPhrase(passphrase);
358 } else if (!bestPractices) {
359
360 passphrase = this.passphrase;
361 if (isNotBlank(passphrase)) {
362 logBestPracticeWarning("Mojo configuration");
363 signer.setPassPhrase(passphrase);
364 } else {
365
366 passphrase = loadGpgPassphrase();
367 if (isNotBlank(passphrase)) {
368 logBestPracticeWarning("settings.xml");
369 signer.setPassPhrase(passphrase);
370 } else {
371
372 passphrase = getPassphrase(mavenProject);
373 if (isNotBlank(passphrase)) {
374 logBestPracticeWarning("Project properties");
375 signer.setPassPhrase(passphrase);
376 }
377 }
378 }
379 }
380 signer.prepare();
381
382 return signer;
383 }
384
385 private boolean isNotBlank(String string) {
386 return string != null && !string.trim().isEmpty();
387 }
388
389
390
391 @Deprecated
392 private static final String GPG_PASSPHRASE = "gpg.passphrase";
393
394 @Deprecated
395 private String loadGpgPassphrase() throws MojoFailureException {
396 if (isNotBlank(passphraseServerId)) {
397 Server server = settings.getServer(passphraseServerId);
398 if (server != null) {
399 if (isNotBlank(server.getPassphrase())) {
400 try {
401 return secDispatcher.decrypt(server.getPassphrase());
402 } catch (SecDispatcherException e) {
403 throw new MojoFailureException("Unable to decrypt gpg passphrase", e);
404 }
405 }
406 }
407 }
408 return null;
409 }
410
411 @Deprecated
412 public String getPassphrase(MavenProject project) {
413 String pass = null;
414 if (project != null) {
415 pass = project.getProperties().getProperty(GPG_PASSPHRASE);
416 if (pass == null) {
417 MavenProject prj2 = findReactorProject(project);
418 pass = prj2.getProperties().getProperty(GPG_PASSPHRASE);
419 }
420 }
421 if (project != null && pass != null) {
422 findReactorProject(project).getProperties().setProperty(GPG_PASSPHRASE, pass);
423 }
424 return pass;
425 }
426
427 @Deprecated
428 private MavenProject findReactorProject(MavenProject prj) {
429 if (prj.getParent() != null
430 && prj.getParent().getBasedir() != null
431 && prj.getParent().getBasedir().exists()) {
432 return findReactorProject(prj.getParent());
433 }
434 return prj;
435 }
436 }