From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1016937-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id 3BFF41382C5
	for <garchives@archives.gentoo.org>; Thu, 12 Apr 2018 13:19:14 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 3EB02E07D0;
	Thu, 12 Apr 2018 13:19:13 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id 0DE1EE07D0
	for <gentoo-commits@lists.gentoo.org>; Thu, 12 Apr 2018 13:19:13 +0000 (UTC)
Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id A64E1335C2C
	for <gentoo-commits@lists.gentoo.org>; Thu, 12 Apr 2018 13:19:11 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 3278A278
	for <gentoo-commits@lists.gentoo.org>; Thu, 12 Apr 2018 13:19:10 +0000 (UTC)
From: "Manuel Rüger" <mrueg@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Manuel Rüger" <mrueg@gentoo.org>
Message-ID: <1523539135.7446da47cdde72a343f5715a37c55a2b3744ecab.mrueg@gentoo>
Subject: [gentoo-commits] repo/gentoo:master commit in: sys-auth/docker_auth/, sys-auth/docker_auth/files/
X-VCS-Repository: repo/gentoo
X-VCS-Files: sys-auth/docker_auth/Manifest sys-auth/docker_auth/docker_auth-1.3_p20180202.ebuild sys-auth/docker_auth/files/docker_auth-ldap-group-support-2.patch
X-VCS-Directories: sys-auth/docker_auth/ sys-auth/docker_auth/files/
X-VCS-Committer: mrueg
X-VCS-Committer-Name: Manuel Rüger
X-VCS-Revision: 7446da47cdde72a343f5715a37c55a2b3744ecab
X-VCS-Branch: master
Date: Thu, 12 Apr 2018 13:19:10 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Archives-Salt: 955713b7-60ab-4d9a-aee3-907a5767d52a
X-Archives-Hash: 65ce4f1310d6aae0de4f44dedb60cdc9

commit:     7446da47cdde72a343f5715a37c55a2b3744ecab
Author:     Manuel Rüger <mrueg <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 12 13:18:55 2018 +0000
Commit:     Manuel Rüger <mrueg <AT> gentoo <DOT> org>
CommitDate: Thu Apr 12 13:18:55 2018 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=7446da47

sys-auth/docker_auth: Update snapshot

Package-Manager: Portage-2.3.28, Repoman-2.3.9

 sys-auth/docker_auth/Manifest                      |   2 +
 .../docker_auth/docker_auth-1.3_p20180202.ebuild   |  88 +++++
 .../files/docker_auth-ldap-group-support-2.patch   | 427 +++++++++++++++++++++
 3 files changed, 517 insertions(+)

diff --git a/sys-auth/docker_auth/Manifest b/sys-auth/docker_auth/Manifest
index 585a395b24f..d75d486a2a3 100644
--- a/sys-auth/docker_auth/Manifest
+++ b/sys-auth/docker_auth/Manifest
@@ -1,4 +1,6 @@
 DIST docker_auth-1.3.tar.gz 48970 BLAKE2B 06a5aaffaa9b1dee2c371fb3dcf51ae14e4a2fc1c8d5fbf8ec9804c77abd9b2178507ed37b906886ff1ed20ac255aaf681422dfee194fa23e17b110278b5e044 SHA512 c0964a643d0269b2c7c4a1a747b421dfea8d8c42e3812a6b0dc2fa989e9e81fd6d6fd34672b19ea4472bf05be53bdd4d1c343fd241eab55d9b3496b47b3fa0c8
+DIST docker_auth-1.3_p20180202.tar.gz 49699 BLAKE2B 3575a47399f101a376f21d7644a035d06c042bf7dc57b52bfa4867967bf1df60b6b0881068503d6ac99c618280c31bdbb58f181992295cc96c035eee08e516a2 SHA512 6591298d7fdac44878fabee818ff8969d428c3682dfbbd610d3eff3e2cd2f109921a09c84994025d5deaafc5686d6d598259f0b50e3fdf79bb0d683a5693183d
+DIST github.com-GoogleCloudPlatform-gcloud-golang-20d4028b8a750c2aca76bf9fefa8ed2d0109b573.tar.gz 873021 BLAKE2B f6bd3a08081b7ddd9c61884ba3157654139c70982ffa7245ed988bb1f0fd80af98ccac556168e90ea871ccc0909d03e7f1ee7bcf7cbf2160bbf764e412d123ad SHA512 e98f269d70927bb59fee31059e2d24a5ba71837adbf1f6619b1d9df0a3ec11ef58a2bdf46de6dc45f9ee0a3985c37bc05004beac34b94bc790093aa1550c939a
 DIST github.com-GoogleCloudPlatform-gcloud-golang-bbf380d59635bf267fc8a8df03d6d261c448ee3c.tar.gz 1082782 BLAKE2B 47eba3e3ad6af13a7b7710b20e970219d27e2a5aa3e3e57cdaf015d43ca6ac758104e822735841cbfc01f6598ef5b83dd85759881ec39ae55b0d485ea76ec8f9 SHA512 d4b8f145a5007668d7b67ea63ffc221d4b56b76bfabfc7ba7b8182ca579edeca707638b4d81746ea1d7ae30915358028d026e17524e1e49a14d3f70c0efb85c2
 DIST github.com-cesanta-glog-22eb27a0ae192b290b25537b8e876556fc25129c.tar.gz 20273 BLAKE2B 982093a19a04611d3e1e9c06dd499fd7eb4730c49057e2c86042acecbf7f1920b6dd83133eb0ae07938ab995cbf809aa7d2236c67a805e3f16ff2c2535e2f66b SHA512 3c4b757fc0d0e45382b1ef0180eea2f0429e8c7ecac0089fca79bc717f6c0a04918b91a144ca78331178cc914b808b40596c6a6e214157d2f812858be31c13d6
 DIST github.com-dchest-uniuri-8902c56451e9b58ff940bbe5fec35d5f9c04584a.tar.gz 2471 BLAKE2B 9cc560893309347a9f012cdb32009bc7201511fa337339c8ced7c671e4b43100e36370dc71c47001e33e411b7707c30787a36e953fa5d15990a1f0edf38accc2 SHA512 70421b526e3040a49e63be6c892de2953b4f9ecdb01b148eb2bab3814f610a8c39bd98aad858cbaf9dcf621b52ee9ef952f0cdcdc6eca77da8ebf80dbbf1c04c

diff --git a/sys-auth/docker_auth/docker_auth-1.3_p20180202.ebuild b/sys-auth/docker_auth/docker_auth-1.3_p20180202.ebuild
new file mode 100644
index 00000000000..ddc1b177ddc
--- /dev/null
+++ b/sys-auth/docker_auth/docker_auth-1.3_p20180202.ebuild
@@ -0,0 +1,88 @@
+# Copyright 1999-2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=6
+EGO_PN="github.com/cesanta/docker_auth"
+
+EGO_VENDOR=(
+	"github.com/dchest/uniuri 8902c56451e9b58ff940bbe5fec35d5f9c04584a"
+	"github.com/deckarep/golang-set fc8930a5e645572ee00bf66358ed3414f3c13b90"
+	"github.com/docker/distribution 0700fa570d7bcc1b3e46ee127c4489fd25f4daa3"
+	"github.com/docker/libtrust aabc10ec26b754e797f9028f4589c5b7bd90dc20"
+	"github.com/facebookgo/httpdown a3b1354551a26449fbe05f5d855937f6e7acbd71"
+	"github.com/facebookgo/clock 600d898af40aa09a7a93ecb9265d87b0504b6f03"
+	"github.com/facebookgo/stats 1b76add642e42c6ffba7211ad7b3939ce654526e"
+	"github.com/go-ldap/ldap 13cedcf58a1ea124045dea529a66c849d3444c8e"
+	"github.com/cesanta/glog 22eb27a0ae192b290b25537b8e876556fc25129c"
+	"github.com/schwarmco/go-cartesian-product c2c0aca869a6cbf51e017ce148b949d9dee09bc3"
+	"github.com/syndtr/goleveldb 3c5717caf1475fd25964109a0fc640bd150fce43"
+	"github.com/golang/snappy 553a641470496b2327abcac10b36396bd98e45c9"
+	"gopkg.in/asn1-ber.v1 4e86f4367175e39f69d9358a5f17b4dda270378d github.com/go-asn1-ber/asn1-ber"
+	"gopkg.in/fsnotify.v1 629574ca2a5df945712d3079857300b5e4da0236 github.com/fsnotify/fsnotify"
+	"gopkg.in/mgo.v2 3f83fa5005286a7fe593b055f0d7771a7dce4655 github.com/go-mgo/mgo"
+	"gopkg.in/yaml.v2 a3f3340b5840cee44f372bddb5880fcbc419b46a github.com/go-yaml/yaml"
+	"golang.org/x/crypto e1a4589e7d3ea14a3352255d04b6f1a418845e5e github.com/golang/crypto"
+	"golang.org/x/sys 493114f68206f85e7e333beccfabc11e98cba8dd github.com/golang/sys"
+	"golang.org/x/net 859d1a86bb617c0c20d154590c3c5d3fcb670b07 github.com/golang/net"
+	"google.golang.org/api 39c3dd417c5a443607650f18e829ad308da08dd2 github.com/google/google-api-go-client"
+	"google.golang.org/grpc 35170916ff58e89ae03f52e778228e18207e0e02 github.com/grpc/grpc-go"
+	"github.com/golang/protobuf 11b8df160996e00fd4b55cbaafb3d84ec6d50fa8"
+	"golang.org/x/oauth2 13449ad91cb26cb47661c1b080790392170385fd github.com/golang/oauth2"
+	"cloud.google.com/go 20d4028b8a750c2aca76bf9fefa8ed2d0109b573 github.com/GoogleCloudPlatform/gcloud-golang"
+	"golang.org/x/text ab5ac5f9a8deb4855a60fab02bc61a4ec770bd49 github.com/golang/text"
+	"github.com/googleapis/gax-go 8c160ca1523d8eea3932fbaa494c8964b7724aa8"
+	"google.golang.org/genproto 595979c8a7bf586b2d293fb42246bf91a0b893d9 github.com/google/go-genproto"
+	)
+
+inherit user golang-build golang-vcs-snapshot
+EGIT_COMMIT="509a03a9622f460ded806a2c7b7b27717b3cb1f5"
+SHORT_COMMIT=${EGIT_COMMIT:0:7}
+SRC_URI="https://${EGO_PN}/archive/${EGIT_COMMIT}.tar.gz -> ${P}.tar.gz
+	${EGO_VENDOR_URI}"
+KEYWORDS="~amd64"
+
+DESCRIPTION="Docker Registry 2 authentication server"
+HOMEPAGE="https://github.com/cesanta/docker_auth"
+
+LICENSE="Apache-2.0"
+SLOT="0"
+IUSE=""
+
+RESTRICT="test"
+
+pkg_setup() {
+	enewgroup ${PN}
+	enewuser ${PN} -1 -1 /dev/null ${PN}
+}
+
+src_prepare() {
+	default
+	pushd src/${EGO_PN}
+	eapply "${FILESDIR}/${PN}-ldap-group-support-2.patch"
+	cp "${FILESDIR}/version.go" auth_server/version.go || die
+	sed -i -e "s/{version}/${PV}/" -e "s/{build_id}/${SHORT_COMMIT}/" auth_server/version.go || die
+	popd || die
+}
+
+src_compile() {
+	pushd src/${EGO_PN}/auth_server || die
+	GOPATH="${WORKDIR}/${P}" go build -o "bin/auth_server" || die
+	popd || die
+}
+
+src_install() {
+	pushd src/${EGO_PN} || die
+	dodoc README.md docs/Backend_MongoDB.md
+	insinto /usr/share/${PF}
+	doins -r examples
+	insinto /etc/docker_auth/
+	newins examples/reference.yml config.yml.example
+	dobin auth_server/bin/auth_server
+	popd || die
+	newinitd "${FILESDIR}"/${PN}.initd ${PN}
+	newconfd "${FILESDIR}"/${PN}.confd ${PN}
+	insinto /etc/logrotate.d
+	newins "${FILESDIR}"/${PN}.logrotated ${PN}
+	keepdir /var/log/docker_auth
+	fowners ${PN}:${PN} /var/log/docker_auth
+}

diff --git a/sys-auth/docker_auth/files/docker_auth-ldap-group-support-2.patch b/sys-auth/docker_auth/files/docker_auth-ldap-group-support-2.patch
new file mode 100644
index 00000000000..7c8bba4a80b
--- /dev/null
+++ b/sys-auth/docker_auth/files/docker_auth-ldap-group-support-2.patch
@@ -0,0 +1,427 @@
+From 2ee85ad8040bab72a929958b4c3c8037dbcd31ae Mon Sep 17 00:00:00 2001
+From: Kevin <kcd83@users.noreply.github.com>
+Date: Mon, 27 Feb 2017 19:09:52 +1300
+Subject: [PATCH 1/5] Initial proof of concept mapping memberOf CN to the label
+ groups #63
+
+(cherry picked from commit 4a33badac6b74617dfe3797a716a6907cf018b27)
+---
+ auth_server/authn/ldap_auth.go | 73 ++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 60 insertions(+), 13 deletions(-)
+
+diff --git a/auth_server/authn/ldap_auth.go b/auth_server/authn/ldap_auth.go
+index a3425ed..5769057 100644
+--- a/auth_server/authn/ldap_auth.go
++++ b/auth_server/authn/ldap_auth.go
+@@ -17,7 +17,6 @@
+ package authn
+ 
+ import (
+-	"bytes"
+ 	"crypto/tls"
+ 	"crypto/x509"
+ 	"fmt"
+@@ -73,10 +72,20 @@ func (la *LDAPAuth) Authenticate(account string, password PasswordString) (bool,
+ 	account = la.escapeAccountInput(account)
+ 
+ 	filter := la.getFilter(account)
+-	accountEntryDN, uSearchErr := la.ldapSearch(l, &la.config.Base, &filter, &[]string{})
++
++	// dnAndGroupAttr := []string{"DN"} // example of no groups mapping attribute
++	groupAttribute := "memberOf"
++	dnAndGroupAttr := []string{"DN", groupAttribute}
++
++	entryAttrMap, uSearchErr := la.ldapSearch(l, &la.config.Base, &filter, &dnAndGroupAttr)
+ 	if uSearchErr != nil {
+ 		return false, nil, uSearchErr
+ 	}
++	if len(entryAttrMap) < 1 || entryAttrMap["DN"] == nil || len(entryAttrMap["DN"]) != 1 {
++		return false, nil, NoMatch // User does not exist
++	}
++
++	accountEntryDN := entryAttrMap["DN"][0]
+ 	if accountEntryDN == "" {
+ 		return false, nil, NoMatch // User does not exist
+ 	}
+@@ -95,6 +104,20 @@ func (la *LDAPAuth) Authenticate(account string, password PasswordString) (bool,
+ 		return false, nil, bindErr
+ 	}
+ 
++	// Extract group names from the attribute values
++	if entryAttrMap[groupAttribute] != nil {
++		rawGroups := entryAttrMap[groupAttribute]
++		labels := make(map[string][]string)
++		var groups []string
++		for _, value := range rawGroups {
++			cn := la.getCNFromDN(value)
++			groups = append(groups, cn)
++		}
++		labels["groups"] = groups
++
++		return true, labels, nil
++	}
++
+ 	return true, nil, nil
+ }
+ 
+@@ -185,9 +208,9 @@ func (la *LDAPAuth) getFilter(account string) string {
+ 
+ //ldap search and return required attributes' value from searched entries
+ //default return entry's DN value if you leave attrs array empty
+-func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, attrs *[]string) (string, error) {
++func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, attrs *[]string) (map[string][]string, error) {
+ 	if l == nil {
+-		return "", fmt.Errorf("No ldap connection!")
++		return nil, fmt.Errorf("No ldap connection!")
+ 	}
+ 	glog.V(2).Infof("Searching...basedDN:%s, filter:%s", *baseDN, *filter)
+ 	searchRequest := ldap.NewSearchRequest(
+@@ -198,30 +221,54 @@ func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, att
+ 		nil)
+ 	sr, err := l.Search(searchRequest)
+ 	if err != nil {
+-		return "", err
++		return nil, err
+ 	}
+ 
+ 	if len(sr.Entries) == 0 {
+-		return "", nil // User does not exist
++		return nil, nil // User does not exist
+ 	} else if len(sr.Entries) > 1 {
+-		return "", fmt.Errorf("Too many entries returned.")
++		return nil, fmt.Errorf("Too many entries returned.")
+ 	}
+ 
+-	var buffer bytes.Buffer
++	result := make(map[string][]string)
+ 	for _, entry := range sr.Entries {
++
+ 		if len(*attrs) == 0 {
+ 			glog.V(2).Infof("Entry DN = %s", entry.DN)
+-			buffer.WriteString(entry.DN)
++			result["DN"] = []string{entry.DN}
+ 		} else {
+ 			for _, attr := range *attrs {
+-				values := strings.Join(entry.GetAttributeValues(attr), " ")
+-				glog.V(2).Infof("Entry %s = %s", attr, values)
+-				buffer.WriteString(values)
++				var values []string
++				if attr == "DN" {
++					// DN is excluded from attributes
++					values = []string{entry.DN}
++				} else {
++					values = entry.GetAttributeValues(attr)
++				}
++				valuesString := strings.Join(values, "\n")
++				glog.V(2).Infof("Entry %s = %s", attr, valuesString)
++				result[attr] = values
++			}
++		}
++	}
++
++	return result, nil
++}
++
++func (la *LDAPAuth) getCNFromDN(dn string) string {
++	parsedDN, err := ldap.ParseDN(dn)
++	if err != nil || len(parsedDN.RDNs) > 0 {
++		for _, rdn := range parsedDN.RDNs {
++			for _, rdnAttr := range rdn.Attributes {
++				if rdnAttr.Type == "CN" {
++					return rdnAttr.Value
++				}
+ 			}
+ 		}
+ 	}
+ 
+-	return buffer.String(), nil
++	// else try using raw DN
++	return dn
+ }
+ 
+ func (la *LDAPAuth) Stop() {
+
+From 3f5e1b78519238ca65e6084f48cbdd56531e4c84 Mon Sep 17 00:00:00 2001
+From: Kevin <kcd83@users.noreply.github.com>
+Date: Tue, 28 Feb 2017 18:09:55 +1300
+Subject: [PATCH 2/5] Apply attribute mapping from configuration
+
+(cherry picked from commit ddde2fa779e746d7e74cd972a4c6795c72f17ee6)
+---
+ auth_server/authn/ldap_auth.go | 127 ++++++++++++++++++++++++-----------------
+ 1 file changed, 75 insertions(+), 52 deletions(-)
+
+diff --git a/auth_server/authn/ldap_auth.go b/auth_server/authn/ldap_auth.go
+index 5769057..99c9146 100644
+--- a/auth_server/authn/ldap_auth.go
++++ b/auth_server/authn/ldap_auth.go
+@@ -27,17 +27,23 @@ import (
+ 	"github.com/cesanta/glog"
+ )
+ 
++type LabelMap struct {
++	Attribute string `yaml:"attribute,omitempty"`
++	ParseCN   bool   `yaml:"parse_cn,omitempty"`
++}
++
+ type LDAPAuthConfig struct {
+-	Addr                  string `yaml:"addr,omitempty"`
+-	TLS                   string `yaml:"tls,omitempty"`
+-	InsecureTLSSkipVerify bool   `yaml:"insecure_tls_skip_verify,omitempty"`
+-	CACertificate         string `yaml:"ca_certificate,omitempty"`
+-	Base                  string `yaml:"base,omitempty"`
+-	Filter                string `yaml:"filter,omitempty"`
+-	BindDN                string `yaml:"bind_dn,omitempty"`
+-	BindPasswordFile      string `yaml:"bind_password_file,omitempty"`
+-	GroupBaseDN           string `yaml:"group_base_dn,omitempty"`
+-	GroupFilter           string `yaml:"group_filter,omitempty"`
++	Addr                  string              `yaml:"addr,omitempty"`
++	TLS                   string              `yaml:"tls,omitempty"`
++	InsecureTLSSkipVerify bool                `yaml:"insecure_tls_skip_verify,omitempty"`
++	CACertificate         string              `yaml:"ca_certificate,omitempty"`
++	Base                  string              `yaml:"base,omitempty"`
++	Filter                string              `yaml:"filter,omitempty"`
++	BindDN                string              `yaml:"bind_dn,omitempty"`
++	BindPasswordFile      string              `yaml:"bind_password_file,omitempty"`
++	LabelMaps             map[string]LabelMap `yaml:"labels,omitempty"`
++	GroupBaseDN           string              `yaml:"group_base_dn,omitempty"`
++	GroupFilter           string              `yaml:"group_filter,omitempty"`
+ }
+ 
+ type LDAPAuth struct {
+@@ -73,22 +79,19 @@ func (la *LDAPAuth) Authenticate(account string, password PasswordString) (bool,
+ 
+ 	filter := la.getFilter(account)
+ 
+-	// dnAndGroupAttr := []string{"DN"} // example of no groups mapping attribute
+-	groupAttribute := "memberOf"
+-	dnAndGroupAttr := []string{"DN", groupAttribute}
++	labelAttributes, labelsConfigErr := la.getLabelAttributes()
++	if labelsConfigErr != nil {
++		return false, nil, labelsConfigErr
++	}
+ 
+-	entryAttrMap, uSearchErr := la.ldapSearch(l, &la.config.Base, &filter, &dnAndGroupAttr)
++	accountEntryDN, entryAttrMap, uSearchErr := la.ldapSearch(l, &la.config.Base, &filter, &labelAttributes)
+ 	if uSearchErr != nil {
+ 		return false, nil, uSearchErr
+ 	}
+-	if len(entryAttrMap) < 1 || entryAttrMap["DN"] == nil || len(entryAttrMap["DN"]) != 1 {
+-		return false, nil, NoMatch // User does not exist
+-	}
+-
+-	accountEntryDN := entryAttrMap["DN"][0]
+ 	if accountEntryDN == "" {
+ 		return false, nil, NoMatch // User does not exist
+ 	}
++
+ 	// Bind as the user to verify their password
+ 	if len(accountEntryDN) > 0 {
+ 		err := l.Bind(accountEntryDN, string(password))
+@@ -104,21 +107,13 @@ func (la *LDAPAuth) Authenticate(account string, password PasswordString) (bool,
+ 		return false, nil, bindErr
+ 	}
+ 
+-	// Extract group names from the attribute values
+-	if entryAttrMap[groupAttribute] != nil {
+-		rawGroups := entryAttrMap[groupAttribute]
+-		labels := make(map[string][]string)
+-		var groups []string
+-		for _, value := range rawGroups {
+-			cn := la.getCNFromDN(value)
+-			groups = append(groups, cn)
+-		}
+-		labels["groups"] = groups
+-
+-		return true, labels, nil
++	// Extract labels from the attribute values
++	labels, labelsExtractErr := la.getLabelsFromMap(entryAttrMap)
++	if labelsExtractErr != nil {
++		return false, nil, labelsExtractErr
+ 	}
+ 
+-	return true, nil, nil
++	return true, labels, nil
+ }
+ 
+ func (la *LDAPAuth) bindReadOnlyUser(l *ldap.Conn) error {
+@@ -208,9 +203,9 @@ func (la *LDAPAuth) getFilter(account string) string {
+ 
+ //ldap search and return required attributes' value from searched entries
+ //default return entry's DN value if you leave attrs array empty
+-func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, attrs *[]string) (map[string][]string, error) {
++func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, attrs *[]string) (string, map[string][]string, error) {
+ 	if l == nil {
+-		return nil, fmt.Errorf("No ldap connection!")
++		return "", nil, fmt.Errorf("No ldap connection!")
+ 	}
+ 	glog.V(2).Infof("Searching...basedDN:%s, filter:%s", *baseDN, *filter)
+ 	searchRequest := ldap.NewSearchRequest(
+@@ -221,38 +216,66 @@ func (la *LDAPAuth) ldapSearch(l *ldap.Conn, baseDN *string, filter *string, att
+ 		nil)
+ 	sr, err := l.Search(searchRequest)
+ 	if err != nil {
+-		return nil, err
++		return "", nil, err
+ 	}
+ 
+ 	if len(sr.Entries) == 0 {
+-		return nil, nil // User does not exist
++		return "", nil, nil // User does not exist
+ 	} else if len(sr.Entries) > 1 {
+-		return nil, fmt.Errorf("Too many entries returned.")
++		return "", nil, fmt.Errorf("Too many entries returned.")
+ 	}
+ 
+-	result := make(map[string][]string)
++	attributes := make(map[string][]string)
++	var entryDn string
+ 	for _, entry := range sr.Entries {
+-
++		entryDn = entry.DN
+ 		if len(*attrs) == 0 {
+-			glog.V(2).Infof("Entry DN = %s", entry.DN)
+-			result["DN"] = []string{entry.DN}
++			glog.V(2).Infof("Entry DN = %s", entryDn)
+ 		} else {
+ 			for _, attr := range *attrs {
+-				var values []string
+-				if attr == "DN" {
+-					// DN is excluded from attributes
+-					values = []string{entry.DN}
+-				} else {
+-					values = entry.GetAttributeValues(attr)
+-				}
+-				valuesString := strings.Join(values, "\n")
+-				glog.V(2).Infof("Entry %s = %s", attr, valuesString)
+-				result[attr] = values
++				values := entry.GetAttributeValues(attr)
++				glog.V(2).Infof("Entry %s = %s", attr, strings.Join(values, "\n"))
++				attributes[attr] = values
+ 			}
+ 		}
+ 	}
+ 
+-	return result, nil
++	return entryDn, attributes, nil
++}
++
++func (la *LDAPAuth) getLabelAttributes() ([]string, error) {
++	labelAttributes := make([]string, len(la.config.LabelMaps))
++	i := 0
++	for key, mapping := range la.config.LabelMaps {
++		if mapping.Attribute == "" {
++			return nil, fmt.Errorf("Label %s is missing 'attribute' to map from", key)
++		}
++		labelAttributes[i] = mapping.Attribute
++		i++
++	}
++	return labelAttributes, nil
++}
++
++func (la *LDAPAuth) getLabelsFromMap(attrMap map[string][]string) (map[string][]string, error) {
++	labels := make(map[string][]string)
++	for key, mapping := range la.config.LabelMaps {
++		if mapping.Attribute == "" {
++			return nil, fmt.Errorf("Label %s is missing 'attribute' to map from", key)
++		}
++
++		mappingValues := attrMap[mapping.Attribute]
++		if mappingValues != nil {
++			if mapping.ParseCN {
++				// shorten attribute to its common name
++				for i, value := range mappingValues {
++					cn := la.getCNFromDN(value)
++					mappingValues[i] = cn
++				}
++			}
++			labels[key] = mappingValues
++		}
++	}
++	return labels, nil
+ }
+ 
+ func (la *LDAPAuth) getCNFromDN(dn string) string {
+
+From 98c4191ee4eae3e3e823c91226179c740e77f3a9 Mon Sep 17 00:00:00 2001
+From: Kevin <kcd83@users.noreply.github.com>
+Date: Tue, 28 Feb 2017 18:27:16 +1300
+Subject: [PATCH 3/5] Remove unused configuration fields, never implemented?
+
+(cherry picked from commit cd37001980267a99a9faa19f1927891af63acb90)
+---
+ auth_server/authn/ldap_auth.go | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/auth_server/authn/ldap_auth.go b/auth_server/authn/ldap_auth.go
+index 99c9146..1135dad 100644
+--- a/auth_server/authn/ldap_auth.go
++++ b/auth_server/authn/ldap_auth.go
+@@ -42,8 +42,6 @@ type LDAPAuthConfig struct {
+ 	BindDN                string              `yaml:"bind_dn,omitempty"`
+ 	BindPasswordFile      string              `yaml:"bind_password_file,omitempty"`
+ 	LabelMaps             map[string]LabelMap `yaml:"labels,omitempty"`
+-	GroupBaseDN           string              `yaml:"group_base_dn,omitempty"`
+-	GroupFilter           string              `yaml:"group_filter,omitempty"`
+ }
+ 
+ type LDAPAuth struct {
+
+From 1b5d134966c8bd1cba9afaeca284476e66a495e5 Mon Sep 17 00:00:00 2001
+From: Kevin <kcd83@users.noreply.github.com>
+Date: Fri, 1 Sep 2017 22:50:19 +1200
+Subject: [PATCH 4/5] Add LDAP label map examples to the reference config
+
+(cherry picked from commit 2fd43be4e5c2cfe177d9e1d36bcd1b29f4d6f262)
+---
+ examples/reference.yml | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/examples/reference.yml b/examples/reference.yml
+index 6ab4ba2..26182fd 100644
+--- a/examples/reference.yml
++++ b/examples/reference.yml
+@@ -140,6 +140,16 @@ ldap_auth:
+   # User query settings. ${account} is expanded from auth request 
+   base: o=example.com
+   filter: (&(uid=${account})(objectClass=person))
++  # Labels can be mapped from LDAP attributes
++  labels:
++    # Add the user's title to a label called title
++    title:
++      attribute: title
++    # Add the user's memberOf values to a label called groups
++    groups:
++      attribute: memberOf
++      # Special handling to simplify the values to just the common name
++      parse_cn: true
+ 
+ mongo_auth:
+   # Essentially all options are described here: https://godoc.org/gopkg.in/mgo.v2#DialInfo
+
+From 1bc75974e70ff7a84bdf3323889b81e44ea3dc00 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Manuel=20R=C3=BCger?= <manuel@rueg.eu>
+Date: Thu, 12 Apr 2018 15:00:51 +0200
+Subject: [PATCH 5/5] reference.yml: Add example ACL
+
+---
+ examples/reference.yml | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/examples/reference.yml b/examples/reference.yml
+index 26182fd..4bdec24 100644
+--- a/examples/reference.yml
++++ b/examples/reference.yml
+@@ -263,6 +263,12 @@ acl:
+   - match: {name: "${labels:project}-{labels:tier}/*"}
+     actions: ["push", "pull"]
+     comment: "Users can push to a project-tier/* that they are assigned to"
++  - match: {labels: {"title": "Developer"}}
++    actions: ["*"]
++    comment: "If you call yourself a developer you can do anything (this ACL is an example for LDAP labels as defined above)"
++  - match: {labels: {"groups": "Admin"}}
++    actions: ["push"]
++    comment: "If you are part of the admin group you can push. (this ACL is an example for LDAP labels as defined above)"
+   # Access is denied by default.
+ 
+ # (optional) Define to query ACL from a MongoDB server.