This repository has been archived by the owner on Dec 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 39
/
CredentialsPlugin.java
100 lines (82 loc) · 6 KB
/
CredentialsPlugin.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package nu.studer.gradle.credentials;
import nu.studer.gradle.credentials.domain.CredentialsContainer;
import nu.studer.gradle.credentials.domain.CredentialsEncryptor;
import nu.studer.gradle.credentials.domain.CredentialsPersistenceManager;
import nu.studer.gradle.util.AlwaysFalseSpec;
import nu.studer.gradle.util.MD5;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.Map;
/**
* Plugin to store and access encrypted credentials using password-based encryption (PBE). The credentials are stored in the Gradle home directory in a separate file for each
* passphrase. If no passphrase is provided, a default passphrase is used and the credentials are stored in the default credentials file 'gradle.encrypted.properties'. While
* running a build, only one passphrase is active per project.
* <p>
* The plugin provides a credentials container through the 'credentials' property that is available from the Gradle project. This allows access to credentials in the form of
* <code>project.myCredentialKey</code>. The already persisted credentials can be accessed through the credentials container, and new credentials can be added to the container
* ad-hoc while the build is executed. Credentials added ad-hoc are not available beyond the lifetime of the build.
* <p>
* The plugin adds a task to add credentials and a task to remove credentials.
*/
public class CredentialsPlugin implements Plugin<Project> {
public static final String DEFAULT_PASSPHRASE_CREDENTIALS_FILE = "gradle.encrypted.properties";
public static final String DEFAULT_PASSPHRASE = ">>Default passphrase to encrypt passwords!<<";
public static final String CREDENTIALS_CONTAINER_PROPERTY = "credentials";
public static final String CREDENTIALS_PASSPHRASE_PROPERTY = "credentialsPassphrase";
public static final String CREDENTIALS_KEY_PROPERTY = "credentialsKey";
public static final String CREDENTIALS_VALUE_PROPERTY = "credentialsValue";
public static final String ADD_CREDENTIALS_TASK_NAME = "addCredentials";
public static final String REMOVE_CREDENTIALS_TASK_NAME = "removeCredentials";
private static final Logger LOGGER = LoggerFactory.getLogger(CredentialsPlugin.class);
@Override
public void apply(Project project) {
// get the passphrase from the project properties, otherwise use the default passphrase
String passphrase = getProjectProperty(CREDENTIALS_PASSPHRASE_PROPERTY, DEFAULT_PASSPHRASE, project);
// derive the name of the credentials file from the passphrase
String credentialsFileName = deriveFileNameFromPassphrase(passphrase);
// create credentials encryptor for the given passphrase
CredentialsEncryptor credentialsEncryptor = CredentialsEncryptor.withPassphrase(passphrase.toCharArray());
// create a credentials persistence manager that operates on the credentials file
File gradleUserHomeDir = project.getGradle().getGradleUserHomeDir();
File credentialsFile = new File(gradleUserHomeDir, credentialsFileName);
CredentialsPersistenceManager credentialsPersistenceManager = new CredentialsPersistenceManager(credentialsFile);
// add a new 'credentials' property and transiently store the persisted credentials for access in build scripts
CredentialsContainer credentialsContainer = new CredentialsContainer(credentialsEncryptor, credentialsPersistenceManager.readCredentials());
project.getExtensions().getExtraProperties().set(CREDENTIALS_CONTAINER_PROPERTY, credentialsContainer);
LOGGER.debug("Registered property '" + CREDENTIALS_CONTAINER_PROPERTY + "'");
// add a task instance that stores new credentials through the credentials persistence manager
AddCredentialsTask addCredentials = project.getTasks().create(ADD_CREDENTIALS_TASK_NAME, AddCredentialsTask.class);
addCredentials.setDescription("Adds the credentials specified through the project properties 'credentialsKey' and 'credentialsValue'.");
addCredentials.setGroup("Credentials");
addCredentials.setCredentialsEncryptor(credentialsEncryptor);
addCredentials.setCredentialsPersistenceManager(credentialsPersistenceManager);
addCredentials.getOutputs().upToDateWhen(AlwaysFalseSpec.INSTANCE);
LOGGER.debug(String.format("Registered task '%s'", addCredentials.getName()));
// add a task instance that removes some credentials through the credentials persistence manager
RemoveCredentialsTask removeCredentials = project.getTasks().create(REMOVE_CREDENTIALS_TASK_NAME, RemoveCredentialsTask.class);
removeCredentials.setDescription("Removes the credentials specified through the project property 'credentialsKey'.");
removeCredentials.setGroup("Credentials");
removeCredentials.setCredentialsPersistenceManager(credentialsPersistenceManager);
removeCredentials.getOutputs().upToDateWhen(AlwaysFalseSpec.INSTANCE);
LOGGER.debug(String.format("Registered task '%s'", removeCredentials.getName()));
}
private String deriveFileNameFromPassphrase(String passphrase) {
// derive the name of the file that contains the credentials from the given passphrase
String credentialsFileName;
if (passphrase.equals(DEFAULT_PASSPHRASE)) {
credentialsFileName = DEFAULT_PASSPHRASE_CREDENTIALS_FILE;
LOGGER.debug("No explicit passphrase provided. Using default credentials file name: " + credentialsFileName);
} else {
credentialsFileName = "gradle." + MD5.generateMD5Hash(passphrase) + ".encrypted.properties";
LOGGER.debug("Custom passphrase provided. Using credentials file name: " + credentialsFileName);
}
return credentialsFileName;
}
private String getProjectProperty(String key, String defaultValue, Project project) {
Map<String, ?> properties = project.getProperties();
return properties.containsKey(key) ? (String) properties.get(key) : defaultValue;
}
}