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
140 @Deprecated
141 @Parameter(property = "gpg.passphraseServerId")
142 private String passphraseServerId;
143
144
145
146
147 @Parameter(property = "gpg.keyname")
148 private String keyname;
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 @Parameter(property = "gpg.useagent", defaultValue = "true")
165 private boolean useAgent;
166
167
168
169
170
171
172
173 @Parameter(property = "gpg.executable")
174 private String executable;
175
176
177
178
179
180
181 @Parameter(property = "gpg.defaultKeyring", defaultValue = "true")
182 private boolean defaultKeyring;
183
184
185
186
187
188
189
190
191
192
193
194
195
196 @Deprecated
197 @Parameter(property = "gpg.secretKeyring")
198 private String secretKeyring;
199
200
201
202
203
204
205
206
207
208
209
210
211
212 @Deprecated
213 @Parameter(property = "gpg.publicKeyring")
214 private String publicKeyring;
215
216
217
218
219
220
221
222
223
224
225
226 @Parameter(property = "gpg.lockMode")
227 private String lockMode;
228
229
230
231
232 @Parameter(property = "gpg.skip", defaultValue = "false")
233 private boolean skip;
234
235
236
237
238
239
240
241
242
243
244
245
246
247 @Parameter
248 private List<String> gpgArguments;
249
250
251
252
253
254
255
256 @Parameter(property = "gpg.signer", defaultValue = GpgSigner.NAME)
257 private String signer;
258
259
260
261
262 @Component
263 protected MavenSession session;
264
265
266
267
268
269
270
271
272
273
274
275
276 @Parameter(property = "gpg.bestPractices", defaultValue = "false")
277 private boolean bestPractices;
278
279
280
281
282
283
284 @Parameter(defaultValue = "${settings}", readonly = true, required = true)
285 protected Settings settings;
286
287
288
289
290
291
292
293 @Deprecated
294 private final SecDispatcher secDispatcher =
295 new DefaultSecDispatcher(new DefaultPlexusCipher(), Collections.emptyMap(), "~/.m2/settings-security.xml");
296
297 @Override
298 public final void execute() throws MojoExecutionException, MojoFailureException {
299 if (skip) {
300
301 return;
302 }
303 if (bestPractices) {
304 enforceBestPractices();
305 } else {
306 if (!isNotBlank(passphraseServerId)) {
307
308 passphraseServerId = GPG_PASSPHRASE;
309 }
310 }
311
312 doExecute();
313 }
314
315 protected void enforceBestPractices() throws MojoFailureException {
316
317 if (isNotBlank(passphrase) || isNotBlank(passphraseServerId)) {
318
319 throw new MojoFailureException(
320 "Do not store passphrase in any file (disk or SCM repository), rely on GnuPG agent or provide passphrase in "
321 + passphraseEnvName + " environment variable.");
322 }
323 }
324
325 protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
326
327 private void logBestPracticeWarning(String source) {
328 getLog().warn("");
329 getLog().warn("W A R N I N G");
330 getLog().warn("");
331 getLog().warn("Do not store passphrase in any file (disk or SCM repository),");
332 getLog().warn("instead rely on GnuPG agent or provide passphrase in ");
333 getLog().warn(passphraseEnvName + " environment variable for batch mode.");
334 getLog().warn("");
335 getLog().warn("Sensitive content loaded from " + source);
336 getLog().warn("");
337 }
338
339 protected AbstractGpgSigner newSigner(MavenProject mavenProject) throws MojoFailureException {
340 AbstractGpgSigner signer;
341 if (GpgSigner.NAME.equals(this.signer)) {
342 signer = new GpgSigner(executable);
343 } else if (BcSigner.NAME.equals(this.signer)) {
344 signer = new BcSigner(
345 session.getRepositorySession(),
346 keyEnvName,
347 keyFingerprintEnvName,
348 agentSocketLocations,
349 keyFilePath,
350 keyFingerprint);
351 } else {
352 throw new MojoFailureException("Unknown signer: " + this.signer);
353 }
354
355 signer.setLog(getLog());
356 signer.setInteractive(settings.isInteractiveMode());
357 signer.setKeyName(keyname);
358 signer.setUseAgent(useAgent);
359 signer.setHomeDirectory(homedir);
360 signer.setDefaultKeyring(defaultKeyring);
361 signer.setSecretKeyring(secretKeyring);
362 signer.setPublicKeyring(publicKeyring);
363 signer.setLockMode(lockMode);
364 signer.setArgs(gpgArguments);
365
366
367 String passphrase =
368 (String) session.getRepositorySession().getConfigProperties().get("env." + passphraseEnvName);
369 if (isNotBlank(passphrase)) {
370 signer.setPassPhrase(passphrase);
371 } else if (!bestPractices) {
372
373 passphrase = this.passphrase;
374 if (isNotBlank(passphrase)) {
375 logBestPracticeWarning("Mojo configuration");
376 signer.setPassPhrase(passphrase);
377 } else {
378
379 passphrase = loadGpgPassphrase();
380 if (isNotBlank(passphrase)) {
381 logBestPracticeWarning("settings.xml");
382 signer.setPassPhrase(passphrase);
383 } else {
384
385 passphrase = getPassphrase(mavenProject);
386 if (isNotBlank(passphrase)) {
387 logBestPracticeWarning("Project properties");
388 signer.setPassPhrase(passphrase);
389 }
390 }
391 }
392 }
393 signer.prepare();
394
395 return signer;
396 }
397
398 private boolean isNotBlank(String string) {
399 return string != null && !string.trim().isEmpty();
400 }
401
402
403
404 @Deprecated
405 private static final String GPG_PASSPHRASE = "gpg.passphrase";
406
407 @Deprecated
408 private String loadGpgPassphrase() throws MojoFailureException {
409 if (isNotBlank(passphraseServerId)) {
410 Server server = settings.getServer(passphraseServerId);
411 if (server != null) {
412 if (isNotBlank(server.getPassphrase())) {
413 try {
414 return secDispatcher.decrypt(server.getPassphrase());
415 } catch (SecDispatcherException e) {
416 throw new MojoFailureException("Unable to decrypt gpg passphrase", e);
417 }
418 }
419 }
420 }
421 return null;
422 }
423
424 @Deprecated
425 public String getPassphrase(MavenProject project) {
426 String pass = null;
427 if (project != null) {
428 pass = project.getProperties().getProperty(GPG_PASSPHRASE);
429 if (pass == null) {
430 MavenProject prj2 = findReactorProject(project);
431 pass = prj2.getProperties().getProperty(GPG_PASSPHRASE);
432 }
433 }
434 if (project != null && pass != null) {
435 findReactorProject(project).getProperties().setProperty(GPG_PASSPHRASE, pass);
436 }
437 return pass;
438 }
439
440 @Deprecated
441 private MavenProject findReactorProject(MavenProject prj) {
442 if (prj.getParent() != null
443 && prj.getParent().getBasedir() != null
444 && prj.getParent().getBasedir().exists()) {
445 return findReactorProject(prj.getParent());
446 }
447 return prj;
448 }
449 }