Add ability to define LDAP environment properties

This commit is contained in:
Stephen Connolly 2013-12-09 12:22:29 +00:00
parent 33a07f8aa3
commit fe4a7145a3
6 changed files with 192 additions and 43 deletions

96
pom.xml
View file

@ -1,18 +1,59 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.468</version>
<version>1.480</version>
</parent>
<artifactId>ldap</artifactId>
<version>1.7-SNAPSHOT</version>
<packaging>hpi</packaging>
<name>LDAP Plugin</name>
<description>Adds LDAP authentication to Jenkins</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/LDAP+Plugin</url>
<licenses>
<license>
<name>The MIT license</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<maven-hpi-plugin.version>1.96</maven-hpi-plugin.version>
</properties>
<scm>
<connection>scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<developerConnection>scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
</scm>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</repository>
<repository><!-- only until we release ant and javadoc plugins -->
<id>maven.jenkins-ci.org</id>
<url>http://maven.jenkins-ci.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
@ -61,44 +102,17 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
</plugin>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>${maven-hpi-plugin.version}</version>
<configuration>
<systemProperties>
<hudson.bundled.plugins>${basedir}/work/plugins/ldap.hpl</hudson.bundled.plugins>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
<scm>
<connection>scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git</connection>
<developerConnection>scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git</developerConnection>
</scm>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</repository>
<repository><!-- only until we release ant and javadoc plugins -->
<id>maven.jenkins-ci.org</id>
<url>http://maven.jenkins-ci.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<licenses>
<license>
<name>The MIT license</name>
<url>http://www.opensource.org/licenses/mit-license.php</url>
<distribution>repo</distribution>
</license>
</licenses>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
</project>
</project>

View file

@ -29,6 +29,8 @@ import hudson.Extension;
import static hudson.Util.fixNull;
import static hudson.Util.fixEmptyAndTrim;
import static hudson.Util.fixEmpty;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import jenkins.model.Jenkins;
import hudson.model.User;
@ -72,13 +74,16 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -331,6 +336,8 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm {
*/
private transient Map<String,CacheEntry<Set<String>>> groupDetailsCache = null;
private final Map<String,String> extraEnvVars;
/**
* @deprecated retained for backwards binary compatibility.
*/
@ -358,8 +365,16 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm {
this(server, rootDN, userSearchBase, userSearch, groupSearchBase, null, null, managerDN, managerPassword, inhibitInferRootDN, disableMailAddressResolver, cache);
}
@DataBoundConstructor
/**
* @deprecated retained for backwards binary compatibility.
*/
@Deprecated
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String groupSearchBase, String groupSearchFilter, String groupMembershipFilter, String managerDN, String managerPassword, boolean inhibitInferRootDN, boolean disableMailAddressResolver, CacheConfiguration cache) {
this(server, rootDN, userSearchBase, userSearch, groupSearchBase, groupSearchFilter, groupMembershipFilter, managerDN, managerPassword, inhibitInferRootDN, disableMailAddressResolver, cache, null);
}
@DataBoundConstructor
public LDAPSecurityRealm(String server, String rootDN, String userSearchBase, String userSearch, String groupSearchBase, String groupSearchFilter, String groupMembershipFilter, String managerDN, String managerPassword, boolean inhibitInferRootDN, boolean disableMailAddressResolver, CacheConfiguration cache, EnvironmentProperty[] environmentProperties) {
this.server = server.trim();
this.managerDN = fixEmpty(managerDN);
this.managerPassword = Scrambler.scramble(fixEmpty(managerPassword));
@ -374,6 +389,9 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm {
this.groupMembershipFilter = fixEmptyAndTrim(groupMembershipFilter);
this.disableMailAddressResolver = disableMailAddressResolver;
this.cache = cache;
this.extraEnvVars = environmentProperties == null || environmentProperties.length == 0
? null
: EnvironmentProperty.toMap(Arrays.asList(environmentProperties));
}
public String getServerUrl() {
@ -407,6 +425,24 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm {
return groupSearchFilter;
}
public Map<String,String> getExtraEnvVars() {
return extraEnvVars == null || extraEnvVars.isEmpty()
? Collections.<String,String>emptyMap()
: Collections.unmodifiableMap(extraEnvVars);
}
public EnvironmentProperty[] getEnvironmentProperties() {
if (extraEnvVars == null || extraEnvVars.isEmpty()) {
return new EnvironmentProperty[0];
}
EnvironmentProperty[] result = new EnvironmentProperty[extraEnvVars.size()];
int i = 0;
for (Map.Entry<String,String> entry: extraEnvVars.entrySet()) {
result[i++] = new EnvironmentProperty(entry.getKey(), entry.getValue());
}
return result;
}
/**
* Infer the root DN.
*
@ -863,4 +899,43 @@ public class LDAPSecurityRealm extends AbstractPasswordBasedSecurityRealm {
return size() > cacheSize || eldest.getValue() == null || !eldest.getValue().isValid();
}
}
public static class EnvironmentProperty extends AbstractDescribableImpl<EnvironmentProperty> implements Serializable {
private final String name;
private final String value;
@DataBoundConstructor
public EnvironmentProperty(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public String getValue() {
return value;
}
public static Map<String,String> toMap(List<EnvironmentProperty> properties) {
if (properties != null) {
final Map<String, String> result = new LinkedHashMap<String, String>();
for (EnvironmentProperty property:properties) {
result.put(property.getName(), property.getValue());
}
return result;
}
return null;
}
@Extension
public static class DescriptorImpl extends Descriptor<EnvironmentProperty> {
@Override
public String getDisplayName() {
return null;
}
}
}
}

View file

@ -45,7 +45,11 @@ initialDirContextFactory(DefaultInitialDirContextFactory, instance.getLDAPURL()
managerDn = instance.managerDN;
managerPassword = instance.getManagerPassword();
}
extraEnvVars = [(Context.REFERRAL):"follow"];
extraEnvVars = [
(Context.REFERRAL):"follow",
"com.sun.jndi.ldap.connect.timeout":"30000", // timeout if no connection after 30 seconds
"com.sun.jndi.ldap.read.timeout":"60000" // timeout if no response after 60 seconds
] + instance.getExtraEnvVars();
}
ldapUserSearch(FilterBasedLdapUserSearch, instance.userSearchBase, instance.userSearch, initialDirContextFactory) {

View file

@ -0,0 +1,38 @@
<!--
The MIT License
Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:entry field="name" title="${%Name}">
<f:textbox/>
</f:entry>
<f:entry field="value" title="${%Value}">
<f:textbox/>
</f:entry>
<f:entry title="">
<div align="right">
<f:repeatableDeleteButton />
</div>
</f:entry>
</j:jelly>

View file

@ -96,5 +96,9 @@ THE SOFTWARE.
<f:radio name="ldap.cache.ttl" value="3600" checked="${instance.cacheTTL == 3600}" title="${%1 hour}"/>
</f:entry>
</f:optionalBlock>
<f:entry title="${%Environment Properties}" help="/plugin/ldap/help-envprop.html">
<f:repeatableProperty field="environmentProperties" />
</f:entry>
</f:advanced>
</j:jelly>

View file

@ -0,0 +1,14 @@
<div>
It may be necessary to set additional LDAP provider properties (<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jndi/jndi-ldap.html">see the Oracle documentation for a full list</a>) in order to ensure optimum performance. Two specific values you should
consider setting are:
<dl>
<dt><code>com.sun.jndi.ldap.connect.timeout</code></dt>
<dd>The value is the number of milliseconds to use as the connection timeout. <br />
<b>Note:</b> As of version 1.7 of the LDAP plugin this value has a default, if not set, of 30 seconds.
</dd>
<dt><code>com.sun.jndi.ldap.read.timeout</code></dt>
<dd>The value is the number of milliseconds to use as the read timeout. <br />
<b>Note:</b> As of version 1.7 of the LDAP plugin this value has a default, if not set, of 60 seconds
</dd>
</dl>
</div>