mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-07 22:15:51 +01:00
Adding LDAP StartTLS support
Some LDAP server do not allow authenticate with unencrypted password.
This patch is adding the StartTLS support which takes care of the
encryption.
In order to enable the StartTLS, go to "System Settings" and select the
"Enable StartTLS" in the Authentication section. Then make sure that you
add your LDAP certificate into the Java keystore:
$ keytool -import \
-file /etc/pki/tls/certs/cacert.pem \
-alias myName \
-keystore /var/lib/gitbucket/keystore
You can list all keys from the keystore like this:
$ keytool -list -keystore /var/lib/gitbucket/keystore
This commit is contained in:
@@ -16,5 +16,8 @@
|
|||||||
# URL prefix for the GitBucket page (http://<host>:<port>/<prefix>/)
|
# URL prefix for the GitBucket page (http://<host>:<port>/<prefix>/)
|
||||||
#GITBUCKET_PREFIX=
|
#GITBUCKET_PREFIX=
|
||||||
|
|
||||||
|
# Java keystore (for LDAP StartTLS)
|
||||||
|
#GITBUCKET_KEYSTORE=/var/lib/gitbucket/keystore
|
||||||
|
|
||||||
# Other Java option
|
# Other Java option
|
||||||
#GITBUCKET_JVM_OPTS=
|
#GITBUCKET_JVM_OPTS=
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
# Default values
|
# Default values
|
||||||
GITBUCKET_HOME=/var/lib/gitbucket
|
GITBUCKET_HOME=/var/lib/gitbucket
|
||||||
GITBUCKET_WAR_FILE=/usr/share/gitbucket/lib/gitbucket.war
|
GITBUCKET_WAR_FILE=/usr/share/gitbucket/lib/gitbucket.war
|
||||||
|
GITBUCKET_KEYSTORE=/var/lib/gitbucket/keystore
|
||||||
|
|
||||||
# Pull in cq settings
|
# Pull in cq settings
|
||||||
[ -f /etc/sysconfig/gitbucket ] && . /etc/sysconfig/gitbucket
|
[ -f /etc/sysconfig/gitbucket ] && . /etc/sysconfig/gitbucket
|
||||||
@@ -29,6 +30,8 @@ RETVAL=0
|
|||||||
start() {
|
start() {
|
||||||
echo -n $"Starting GitBucket server: "
|
echo -n $"Starting GitBucket server: "
|
||||||
|
|
||||||
|
GITBUCKET_JVM_OPTS="${GITBUCKET_JVM_OPTS} -Djavax.net.ssl.trustStore=${GITBUCKET_KEYSTORE}"
|
||||||
|
|
||||||
# Compile statup parameters
|
# Compile statup parameters
|
||||||
if [ $GITBUCKET_PORT ]; then
|
if [ $GITBUCKET_PORT ]; then
|
||||||
START_OPTS="${START_OPTS} --port=${GITBUCKET_PORT}"
|
START_OPTS="${START_OPTS} --port=${GITBUCKET_PORT}"
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ trait SystemSettingsControllerBase extends ControllerBase with FlashMapSupport {
|
|||||||
"bindPassword" -> trim(label("Bind Password", optional(text()))),
|
"bindPassword" -> trim(label("Bind Password", optional(text()))),
|
||||||
"baseDN" -> trim(label("Base DN", text(required))),
|
"baseDN" -> trim(label("Base DN", text(required))),
|
||||||
"userNameAttribute" -> trim(label("User name attribute", text(required))),
|
"userNameAttribute" -> trim(label("User name attribute", text(required))),
|
||||||
"mailAttribute" -> trim(label("Mail address attribute", text(required)))
|
"mailAttribute" -> trim(label("Mail address attribute", text(required))),
|
||||||
|
"tls" -> trim(label("Enable StartTLS", optional(boolean())))
|
||||||
)(Ldap.apply))
|
)(Ldap.apply))
|
||||||
)(SystemSettings.apply)
|
)(SystemSettings.apply)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ trait SystemSettingsService {
|
|||||||
props.setProperty(LdapBaseDN, ldap.baseDN)
|
props.setProperty(LdapBaseDN, ldap.baseDN)
|
||||||
props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute)
|
props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute)
|
||||||
props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute)
|
props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute)
|
||||||
|
ldap.tls.foreach(x => props.setProperty(LdapTls, x.toString))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
props.store(new java.io.FileOutputStream(GitBucketConf), null)
|
props.store(new java.io.FileOutputStream(GitBucketConf), null)
|
||||||
@@ -69,7 +70,8 @@ trait SystemSettingsService {
|
|||||||
getOptionValue(props, LdapBindPassword, None),
|
getOptionValue(props, LdapBindPassword, None),
|
||||||
getValue(props, LdapBaseDN, ""),
|
getValue(props, LdapBaseDN, ""),
|
||||||
getValue(props, LdapUserNameAttribute, ""),
|
getValue(props, LdapUserNameAttribute, ""),
|
||||||
getValue(props, LdapMailAddressAttribute, "")))
|
getValue(props, LdapMailAddressAttribute, ""),
|
||||||
|
getOptionValue[Boolean](props, LdapTls, None)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -97,7 +99,8 @@ object SystemSettingsService {
|
|||||||
bindPassword: Option[String],
|
bindPassword: Option[String],
|
||||||
baseDN: String,
|
baseDN: String,
|
||||||
userNameAttribute: String,
|
userNameAttribute: String,
|
||||||
mailAttribute: String)
|
mailAttribute: String,
|
||||||
|
tls: Option[Boolean])
|
||||||
|
|
||||||
case class Smtp(
|
case class Smtp(
|
||||||
host: String,
|
host: String,
|
||||||
@@ -129,6 +132,7 @@ object SystemSettingsService {
|
|||||||
private val LdapBaseDN = "ldap.baseDN"
|
private val LdapBaseDN = "ldap.baseDN"
|
||||||
private val LdapUserNameAttribute = "ldap.username_attribute"
|
private val LdapUserNameAttribute = "ldap.username_attribute"
|
||||||
private val LdapMailAddressAttribute = "ldap.mail_attribute"
|
private val LdapMailAddressAttribute = "ldap.mail_attribute"
|
||||||
|
private val LdapTls = "ldap.tls"
|
||||||
|
|
||||||
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A =
|
private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A =
|
||||||
defining(props.getProperty(key)){ value =>
|
defining(props.getProperty(key)){ value =>
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package util
|
|||||||
import util.ControlUtil._
|
import util.ControlUtil._
|
||||||
import service.SystemSettingsService
|
import service.SystemSettingsService
|
||||||
import com.novell.ldap._
|
import com.novell.ldap._
|
||||||
|
import java.security.Security
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import service.SystemSettingsService.Ldap
|
import service.SystemSettingsService.Ldap
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
@@ -11,7 +13,8 @@ import scala.annotation.tailrec
|
|||||||
*/
|
*/
|
||||||
object LDAPUtil {
|
object LDAPUtil {
|
||||||
|
|
||||||
private val LDAP_VERSION: Int = 3
|
private val LDAP_VERSION: Int = LDAPConnection.LDAP_V3
|
||||||
|
private val logger = LoggerFactory.getLogger("LDAPUtil")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try authentication by LDAP using given configuration.
|
* Try authentication by LDAP using given configuration.
|
||||||
@@ -22,7 +25,8 @@ object LDAPUtil {
|
|||||||
ldapSettings.host,
|
ldapSettings.host,
|
||||||
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
||||||
ldapSettings.bindDN.getOrElse(""),
|
ldapSettings.bindDN.getOrElse(""),
|
||||||
ldapSettings.bindPassword.getOrElse("")
|
ldapSettings.bindPassword.getOrElse(""),
|
||||||
|
ldapSettings.tls.getOrElse(false)
|
||||||
) match {
|
) match {
|
||||||
case Some(conn) => {
|
case Some(conn) => {
|
||||||
withConnection(conn) { conn =>
|
withConnection(conn) { conn =>
|
||||||
@@ -41,7 +45,8 @@ object LDAPUtil {
|
|||||||
ldapSettings.host,
|
ldapSettings.host,
|
||||||
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
||||||
userDN,
|
userDN,
|
||||||
password
|
password,
|
||||||
|
ldapSettings.tls.getOrElse(false)
|
||||||
) match {
|
) match {
|
||||||
case Some(conn) => {
|
case Some(conn) => {
|
||||||
withConnection(conn) { conn =>
|
withConnection(conn) { conn =>
|
||||||
@@ -55,15 +60,35 @@ object LDAPUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def bind(host: String, port: Int, dn: String, password: String): Option[LDAPConnection] = {
|
private def bind(host: String, port: Int, dn: String, password: String, tls: Boolean): Option[LDAPConnection] = {
|
||||||
val conn: LDAPConnection = new LDAPConnection
|
if (tls) {
|
||||||
|
// Dynamically set Sun as the security provider
|
||||||
|
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
|
||||||
|
}
|
||||||
|
|
||||||
|
val conn: LDAPConnection = new LDAPConnection(new LDAPJSSEStartTLSFactory())
|
||||||
try {
|
try {
|
||||||
|
// Connect to the server
|
||||||
conn.connect(host, port)
|
conn.connect(host, port)
|
||||||
|
|
||||||
|
if (tls) {
|
||||||
|
// Secure the connection
|
||||||
|
conn.startTLS()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the server
|
||||||
conn.bind(LDAP_VERSION, dn, password.getBytes)
|
conn.bind(LDAP_VERSION, dn, password.getBytes)
|
||||||
|
|
||||||
Some(conn)
|
Some(conn)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Exception => {
|
case e: Exception => {
|
||||||
if (conn.isConnected) conn.disconnect()
|
// Provide more information if something goes wrong
|
||||||
|
logger.info("" + e)
|
||||||
|
|
||||||
|
if (conn.isConnected) {
|
||||||
|
conn.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,13 @@
|
|||||||
<span id="error-ldap_mailAttribute" class="error"></span>
|
<span id="error-ldap_mailAttribute" class="error"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" name="ldap.tls"@if(settings.ldap.flatMap(_.tls).getOrElse(false)){ checked}/> Enable StartTLS
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--====================================================================-->
|
<!--====================================================================-->
|
||||||
<!-- Notification email -->
|
<!-- Notification email -->
|
||||||
|
|||||||
Reference in New Issue
Block a user