update ldap configuration

This commit is contained in:
vmware 2016-08-18 18:31:41 +08:00 committed by wemeya
parent 0fc7363a4c
commit ad78449266
5 changed files with 107 additions and 29 deletions

View File

@ -26,10 +26,25 @@ auth_mode = db_auth
#The url for an ldap endpoint.
ldap_url = ldaps://ldap.mydomain.com
#ldap_searchdn, set the user who has the permission to search the LDAP/AD server. If your ldap/AD server does not support anonymous search, you should configure it and ldap_search_pwd.
#ldap_searchdn = cn=admin,ou=people,dc=mydomain,dc=com
#the password of the ldap_searchdn
#ldap_search_pwd = admin
#The basedn template to look up a user in LDAP and verify the user's password.
#For AD server, uses this template:
#ldap_basedn = CN=%s,OU=Dept1,DC=mydomain,DC=com
ldap_basedn = uid=%s,ou=people,dc=mydomain,dc=com
ldap_basedn = ou=people,dc=mydomain,dc=com
#ldap filter, set the attribute to filter a user, you can add as many as you need, be sure the grammar is right. If needed, configure it.
#ldap_filter = objectClass=person
#the exclusive attribute to distinguish a user, it can be uid or cn or mail or email or sAMAccountName, for example: ldap_uid = uid
ldap_uid = uid
#ldap_scope, set the scope to search, 1-LDAP_SCOPE_BASE, 2-LDAP_SCOPE_ONELEVEL, 3-LDAP_SCOPE_SUBTREE, default is 3
ldap_scope = 3
#The password for the root user of mysql db, change this before any production use.
db_password = root123

View File

@ -47,7 +47,21 @@ email_ssl = rcp.get("configuration", "email_ssl")
harbor_admin_password = rcp.get("configuration", "harbor_admin_password")
auth_mode = rcp.get("configuration", "auth_mode")
ldap_url = rcp.get("configuration", "ldap_url")
# this two options are either both set or unset
if rcp.has_option("configuration", "ldap_searchdn"):
ldap_searchdn = rcp.get("configuration", "ldap_searchdn")
ldap_search_pwd = rcp.get("configuration", "ldap_search_pwd")
else:
ldap_searchdn = ""
ldap_search_pwd = ""
ldap_basedn = rcp.get("configuration", "ldap_basedn")
# ldap_filter is null by default
if rcp.has_option("configuration", "ldap_filter"):
ldap_filter = rcp.get("configuration", "ldap_filter")
else:
ldap_filter = ""
ldap_uid = rcp.get("configuration", "ldap_uid")
ldap_scope = rcp.get("configuration", "ldap_scope")
db_password = rcp.get("configuration", "db_password")
self_registration = rcp.get("configuration", "self_registration")
use_compressed_js = rcp.get("configuration", "use_compressed_js")
@ -118,7 +132,12 @@ render(os.path.join(templates_dir, "ui", "env"),
auth_mode=auth_mode,
harbor_admin_password=harbor_admin_password,
ldap_url=ldap_url,
ldap_searchdn =ldap_searchdn,
ldap_search_pwd =ldap_search_pwd,
ldap_basedn=ldap_basedn,
ldap_filter=ldap_filter,
ldap_uid=ldap_uid,
ldap_scope=ldap_scope,
self_registration=self_registration,
use_compressed_js=use_compressed_js,
ui_secret=ui_secret,

View File

@ -10,7 +10,12 @@ HARBOR_ADMIN_PASSWORD=$harbor_admin_password
HARBOR_URL=$ui_url
AUTH_MODE=$auth_mode
LDAP_URL=$ldap_url
LDAP_SEARCH_DN=$ldap_searchdn
LDAP_SEARCH_PWD=$ldap_search_pwd
LDAP_BASE_DN=$ldap_basedn
LDAP_FILTER=$ldap_filter
LDAP_UID=$ldap_uid
LDAP_SCOPE=$ldap_scope
UI_SECRET=$ui_secret
SELF_REGISTRATION=$self_registration
USE_COMPRESSED_JS=$use_compressed_js

View File

@ -40,62 +40,96 @@ const metaChars = "&|!=~*<>()"
// be associated to other entities in the system.
func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) {
ldapURL := os.Getenv("LDAP_URL")
if ldapURL == "" {
return nil, errors.New("Can not get any available LDAP_URL.")
}
log.Debug("ldapURL:", ldapURL)
p := m.Principal
for _, c := range metaChars {
if strings.ContainsRune(p, c) {
return nil, fmt.Errorf("the principal contains meta char: %q", c)
}
}
ldapURL := os.Getenv("LDAP_URL")
if ldapURL == "" {
return nil, errors.New("Can not get any available LDAP_URL.")
}
log.Debug("ldapURL:", ldapURL)
ldap, err := openldap.Initialize(ldapURL)
if err != nil {
return nil, err
}
ldap.SetOption(openldap.LDAP_OPT_PROTOCOL_VERSION, openldap.LDAP_VERSION3)
ldapBaseDn := os.Getenv("LDAP_BASE_DN")
if ldapBaseDn == "" {
return nil, errors.New("Can not get any available LDAP_BASE_DN.")
}
log.Debug("baseDn:", ldapBaseDn)
baseDn := fmt.Sprintf(ldapBaseDn, m.Principal)
log.Debug("baseDn:", baseDn)
ldapSearchDn := os.Getenv("LDAP_SEARCH_DN")
if ldapSearchDn != "" {
log.Debug("Search DN: ", ldapSearchDn)
ldapSearchPwd := os.Getenv("LDAP_SEARCH_PWD")
err = ldap.Bind(ldapSearchDn, ldapSearchPwd)
if err != nil {
log.Debug("Bind search dn error", err)
return nil, err
}
}
err = ldap.Bind(baseDn, m.Password)
attrName := os.Getenv("LDAP_UID")
filter := os.Getenv("LDAP_FILTER")
if filter != "" {
filter = "(&(" + filter + ")(" + attrName + "=" + m.Principal + "))"
} else {
filter = "(" + attrName + "=" + m.Principal + ")"
}
log.Debug("one or more filter", filter)
ldapScope := os.Getenv("LDAP_SCOPE")
var scope int
if ldapScope == "1" {
scope = openldap.LDAP_SCOPE_BASE
} else if ldapScope == "2" {
scope = openldap.LDAP_SCOPE_ONELEVEL
} else {
scope = openldap.LDAP_SCOPE_SUBTREE
}
attributes := []string{"uid", "cn", "mail", "email"}
result, err := ldap.SearchAll(ldapBaseDn, scope, filter, attributes)
if err != nil {
return nil, err
}
if len(result.Entries()) == 0 {
log.Warningf("Not found an entry.")
return nil, nil
} else if len(result.Entries()) != 1 {
log.Warningf("Found more than one entry.")
return nil, nil
}
en := result.Entries()[0]
bindDN := en.Dn()
log.Debug("found entry:", en)
err = ldap.Bind(bindDN, m.Password)
if err != nil {
log.Debug("Bind user error", err)
return nil, err
}
defer ldap.Close()
scope := openldap.LDAP_SCOPE_SUBTREE // LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
filter := "objectClass=*"
attributes := []string{"mail"}
result, err := ldap.SearchAll(baseDn, scope, filter, attributes)
if err != nil {
return nil, err
}
u := models.User{}
if len(result.Entries()) == 1 {
en := result.Entries()[0]
for _, attr := range en.Attributes() {
val := attr.Values()[0]
if attr.Name() == "mail" {
u.Email = val
}
for _, attr := range en.Attributes() {
val := attr.Values()[0]
switch attr.Name() {
case "uid":
u.Realname = val
case "cn":
u.Realname = val
case "mail":
u.Email = val
case "email":
u.Email = val
}
}
u.Username = m.Principal
log.Debug("username:", u.Username, ",email:", u.Email)
exist, err := dao.UserExists(u, "username")
if err != nil {
return nil, err

View File

@ -48,7 +48,12 @@ The parameters are described below - note that at the very least, you will need
* **harbor_admin_password**: The adminstrator's password. _Note that the default username/password are **admin/Harbor12345** ._
* **auth_mode**: The type of authentication that is used. By default it is **db_auth**, i.e. the credentials are stored in a database. For LDAP authentication, set this to **ldap_auth**.
* **ldap_url**: The LDAP endpoint URL (e.g. `ldaps://ldap.mydomain.com`). _Only used when **auth_mode** is set to *ldap_auth* ._
* **ldap_searchdn**: The dn of the user who has the permission to search a ldap/AD server (e.g. `cn=admin,ou=people,dc=mydomain,dc=com`).
* **ldap_search_pwd**: The password of the user who was set as the ldap_searchdn.
* **ldap_basedn**: The basedn template for verifying the user's credential against an LDAP (e.g. `uid=%s,ou=people,dc=mydomain,dc=com` ) or an AD (e.g. `CN=%s,OU=Dept1,DC=mydomain,DC=com`) server. _Only used when **auth_mode** is set to *ldap_auth* ._
* **ldap_filter**:The attribute to filter a user, you can add as many as you need, be sure the grammar is right. If not needed, comment it (e.g. `ldap_filter = objectClass=person`).
* **ldap_uid**:The exclusive attribute to distinguish a user, it can be uid or cn or mail or email(e.g. `ldap_uid = uid`).
* **ldap_scope**:The scope to search, 1-LDAP_SCOPE_BASE, 2-LDAP_SCOPE_ONELEVEL, 3-LDAP_SCOPE_SUBTREE, default is 3(e.g. `ldap_scope = 3`).
* **db_password**: The root password for the mySQL database used for **db_auth**. _Change this password for any production use!_
* **self_registration**: (**on** or **off**. Default is **on**) Enable / Disable the ability for a user to register themselves. When disabled, new users can only be created by the Admin user, only an admin user can create new users in Harbor. _NOTE: When **auth_mode** is set to **ldap_auth**, self-registration feature is **always** disabled, and this flag is ignored._
* **use_compressed_js**: (**on** or **off**. Default is **on**) For production use, turn this flag to **on**. In development mode, set it to **off** so that js files can be modified separately.