diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java b/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java
index a565bbee..ecc60714 100644
--- a/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java
+++ b/src/main/java/de/theit/jenkins/crowd/CrowdConfigurationService.java
@@ -46,6 +46,9 @@
import com.atlassian.crowd.service.client.ClientProperties;
import com.atlassian.crowd.service.client.ClientPropertiesImpl;
import com.atlassian.crowd.service.client.CrowdClient;
+
+import hudson.util.Secret;
+
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
@@ -166,11 +169,11 @@ public class CrowdConfigurationService {
* @param pNestedGroups Specifies whether nested groups should be used when validating
* users against a group name.
*/
- public CrowdConfigurationService(String url, String applicationName, String password,
+ public CrowdConfigurationService(String url, String applicationName, Secret password,
int sessionValidationInterval, boolean useSSO,
String cookieDomain, String cookieTokenkey, Boolean useProxy,
String httpProxyHost, String httpProxyPort, String httpProxyUsername,
- String httpProxyPassword, String socketTimeout,
+ Secret httpProxyPassword, String socketTimeout,
String httpTimeout, String httpMaxConnections,
boolean useCache, Integer cacheSize, Integer cacheTTL,
String pGroupNames, boolean pNestedGroups) {
@@ -193,9 +196,9 @@ public CrowdConfigurationService(String url, String applicationName, String pass
this.useCache = useCache;
this.cacheSize = cacheSize;
this.cacheTTL = cacheTTL;
- Properties props = getProperties(url, applicationName, password, sessionValidationInterval,
+ Properties props = getProperties(url, applicationName, Secret.toString(password), sessionValidationInterval,
useSSO, cookieDomain, cookieTokenkey, useProxy, httpProxyHost, httpProxyPort, httpProxyUsername,
- httpProxyPassword, socketTimeout, httpTimeout, httpMaxConnections);
+ Secret.toString(httpProxyPassword), socketTimeout, httpTimeout, httpMaxConnections);
this.clientProperties = ClientPropertiesImpl.newInstanceFromProperties(props);
this.crowdClient = new RestCrowdClientFactory().newInstance(this.clientProperties);
this.tokenHelper = CrowdHttpTokenHelperImpl.getInstance(CrowdHttpValidationFactorExtractorImpl.getInstance());
diff --git a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java
index 4bc61994..c16ed180 100644
--- a/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java
+++ b/src/main/java/de/theit/jenkins/crowd/CrowdSecurityRealm.java
@@ -42,6 +42,7 @@
import hudson.security.SecurityRealm;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
+import hudson.util.Secret;
import jenkins.model.Jenkins;
import org.acegisecurity.AccountExpiredException;
@@ -92,7 +93,7 @@ public class CrowdSecurityRealm extends AbstractPasswordBasedSecurityRealm {
public final String applicationName;
/** Contains the application password to access Crowd. */
- public final String password;
+ public final Secret password;
/** Contains the Crowd group to which a user must belong to. */
public final String group;
@@ -129,7 +130,7 @@ public class CrowdSecurityRealm extends AbstractPasswordBasedSecurityRealm {
public final String httpProxyHost;
public final String httpProxyPort;
public final String httpProxyUsername;
- public final String httpProxyPassword;
+ public final Secret httpProxyPassword;
public final String socketTimeout;
public final String httpTimeout;
@@ -176,10 +177,10 @@ public class CrowdSecurityRealm extends AbstractPasswordBasedSecurityRealm {
* @param cache The cache configuration
*/
@DataBoundConstructor
- public CrowdSecurityRealm(String url, String applicationName, String password, String group, boolean nestedGroups,
+ public CrowdSecurityRealm(String url, String applicationName, Secret password, String group, boolean nestedGroups,
int sessionValidationInterval, boolean useSSO, String cookieDomain,
String cookieTokenkey, Boolean useProxy, String httpProxyHost, String httpProxyPort,
- String httpProxyUsername, String httpProxyPassword, String socketTimeout,
+ String httpProxyUsername, Secret httpProxyPassword, String socketTimeout,
String httpTimeout, String httpMaxConnections, CacheConfiguration cache) {
this.cookieTokenkey = cookieTokenkey;
this.useProxy = useProxy;
@@ -192,7 +193,7 @@ public CrowdSecurityRealm(String url, String applicationName, String password, S
this.httpMaxConnections = httpMaxConnections;
this.url = url.trim();
this.applicationName = applicationName.trim();
- this.password = password.trim();
+ this.password = password;
this.group = group.trim();
this.nestedGroups = nestedGroups;
this.sessionValidationInterval = sessionValidationInterval;
@@ -200,6 +201,49 @@ public CrowdSecurityRealm(String url, String applicationName, String password, S
this.cookieDomain = cookieDomain;
this.cache = cache;
}
+
+ /**
+ * Default constructor. Fields in config.jelly must match the parameter
+ * names in the "DataBoundConstructor".
+ *
+ * @param url The URL for Crowd.
+ * @param applicationName The application name.
+ * @param password The application password.
+ * @param group The group to which users must belong to. If this parameter is
+ * not specified, a users group membership will not be checked.
+ * @param nestedGroups true
when nested groups may be used.
+ * false
else.
+ * @param sessionValidationInterval The number of minutes to cache authentication validation in
+ * the session. If this value is set to 0
, each HTTP
+ * request will be authenticated with the Crowd server.
+ * @param useSSO Enable SSO authentication.
+ * @param cookieDomain The cookie domain
+ * @param cookieTokenkey The cookie token key
+ * @param useProxy Specifies if a proxy should be used
+ * @param httpProxyHost The http proxy host
+ * @param httpProxyPort The http proxy port
+ * @param httpProxyUsername The http proxy username
+ * @param httpProxyPassword The http proxy password
+ * @param socketTimeout The socket timeout
+ * @param httpTimeout The http timeout
+ * @param httpMaxConnections The http max connections
+ * @param cache The cache configuration
+ *
+ * @deprecated retained for backwards binary compatibility.
+ */
+ @Deprecated
+ public CrowdSecurityRealm(String url, String applicationName, String password, String group, boolean nestedGroups,
+ int sessionValidationInterval, boolean useSSO, String cookieDomain,
+ String cookieTokenkey, Boolean useProxy, String httpProxyHost, String httpProxyPort,
+ String httpProxyUsername, String httpProxyPassword, String socketTimeout,
+ String httpTimeout, String httpMaxConnections, CacheConfiguration cache) {
+ this(url, applicationName, Secret.fromString(password.trim()), group, nestedGroups, sessionValidationInterval, useSSO,
+ cookieDomain, cookieTokenkey, useProxy, httpProxyHost, httpProxyPort, httpProxyUsername,
+ Secret.fromString(httpProxyPassword), socketTimeout, httpTimeout, httpMaxConnections, cache);
+ // If this constructor is called, make sure to re-save the configuration.
+ // This way, migrated secrets are persisted securely without user interaction.
+ getDescriptor().save();
+ }
/**
* Fields in config.jelly must match the parameter names in the "DataBoundConstructor".
@@ -585,9 +629,9 @@ public FormValidation doTestConnection(@QueryParameter String url, @QueryParamet
// Logger log = Logger.getLogger(getClass().getName());
Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER);
CrowdConfigurationService tConfiguration = new CrowdConfigurationService(
- url, applicationName, password, sessionValidationInterval,
+ url, applicationName, Secret.fromString(password), sessionValidationInterval,
useSSO, cookieDomain, cookieTokenkey, useProxy, httpProxyHost, httpProxyPort, httpProxyUsername,
- httpProxyPassword, socketTimeout, httpTimeout, httpMaxConnections,
+ Secret.fromString(httpProxyPassword), socketTimeout, httpTimeout, httpMaxConnections,
false, null, null,
group, false
);