outposts/ldap: add ability to use multiple providers on the same outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		
							
								
								
									
										115
									
								
								outpost/pkg/ldap/instance_search.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								outpost/pkg/ldap/instance_search.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | ||||
| package ldap | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/nmcclain/ldap" | ||||
| 	"goauthentik.io/outpost/pkg/client/core" | ||||
| ) | ||||
|  | ||||
| func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) { | ||||
| 	bindDN = strings.ToLower(bindDN) | ||||
| 	baseDN := strings.ToLower("," + pi.BaseDN) | ||||
|  | ||||
| 	entries := []*ldap.Entry{} | ||||
| 	filterEntity, err := ldap.GetFilterObjectClass(searchReq.Filter) | ||||
| 	if err != nil { | ||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: error parsing filter: %s", searchReq.Filter) | ||||
| 	} | ||||
| 	if len(bindDN) < 1 { | ||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", bindDN) | ||||
| 	} | ||||
| 	if !strings.HasSuffix(bindDN, baseDN) { | ||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", bindDN, pi.BaseDN) | ||||
| 	} | ||||
|  | ||||
| 	switch filterEntity { | ||||
| 	default: | ||||
| 		return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: unhandled filter type: %s [%s]", filterEntity, searchReq.Filter) | ||||
| 	case GroupObjectClass: | ||||
| 		groups, err := pi.s.ac.Client.Core.CoreGroupsList(core.NewCoreGroupsListParams(), pi.s.ac.Auth) | ||||
| 		if err != nil { | ||||
| 			return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err) | ||||
| 		} | ||||
| 		for _, g := range groups.Payload.Results { | ||||
| 			attrs := []*ldap.EntryAttribute{ | ||||
| 				{ | ||||
| 					Name:   "cn", | ||||
| 					Values: []string{*g.Name}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "uid", | ||||
| 					Values: []string{string(g.Pk)}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "objectClass", | ||||
| 					Values: []string{GroupObjectClass, "goauthentik.io/ldap/group"}, | ||||
| 				}, | ||||
| 			} | ||||
| 			attrs = append(attrs, AKAttrsToLDAP(g.Attributes)...) | ||||
| 			// attrs = append(attrs, &ldap.EntryAttribute{Name: "description", Values: []string{fmt.Sprintf("%s", g.Name)}}) | ||||
| 			// attrs = append(attrs, &ldap.EntryAttribute{Name: "gidNumber", Values: []string{fmt.Sprintf("%d", g.UnixID)}}) | ||||
| 			// attrs = append(attrs, &ldap.EntryAttribute{Name: "uniqueMember", Values: h.getGroupMembers(g.UnixID)}) | ||||
| 			// attrs = append(attrs, &ldap.EntryAttribute{Name: "memberUid", Values: h.getGroupMemberIDs(g.UnixID)}) | ||||
| 			dn := fmt.Sprintf("cn=%s,%s", *g.Name, pi.GroupDN) | ||||
| 			entries = append(entries, &ldap.Entry{DN: dn, Attributes: attrs}) | ||||
| 		} | ||||
| 	case UserObjectClass, "": | ||||
| 		users, err := pi.s.ac.Client.Core.CoreUsersList(core.NewCoreUsersListParams(), pi.s.ac.Auth) | ||||
| 		if err != nil { | ||||
| 			return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err) | ||||
| 		} | ||||
| 		for _, u := range users.Payload.Results { | ||||
| 			attrs := []*ldap.EntryAttribute{ | ||||
| 				{ | ||||
| 					Name:   "cn", | ||||
| 					Values: []string{*u.Username}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "uid", | ||||
| 					Values: []string{strconv.Itoa(int(u.Pk))}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "name", | ||||
| 					Values: []string{*u.Name}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "displayName", | ||||
| 					Values: []string{*u.Name}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "mail", | ||||
| 					Values: []string{u.Email.String()}, | ||||
| 				}, | ||||
| 				{ | ||||
| 					Name:   "objectClass", | ||||
| 					Values: []string{UserObjectClass, "organizationalPerson", "goauthentik.io/ldap/user"}, | ||||
| 				}, | ||||
| 			} | ||||
|  | ||||
| 			if u.IsActive { | ||||
| 				attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"inactive"}}) | ||||
| 			} else { | ||||
| 				attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"active"}}) | ||||
| 			} | ||||
|  | ||||
| 			if *u.IsSuperuser { | ||||
| 				attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"inactive"}}) | ||||
| 			} else { | ||||
| 				attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"active"}}) | ||||
| 			} | ||||
|  | ||||
| 			// attrs = append(attrs, &ldap.EntryAttribute{Name: "memberOf", Values: h.getGroupDNs(append(u.OtherGroups, u.PrimaryGroup))}) | ||||
|  | ||||
| 			attrs = append(attrs, AKAttrsToLDAP(u.Attributes)...) | ||||
|  | ||||
| 			dn := fmt.Sprintf("cn=%s,%s", *u.Name, pi.UserDN) | ||||
| 			entries = append(entries, &ldap.Entry{DN: dn, Attributes: attrs}) | ||||
| 		} | ||||
| 	} | ||||
| 	pi.log.WithField("filter", searchReq.Filter).Debug("Search OK") | ||||
| 	return ldap.ServerSearchResult{Entries: entries, Referrals: []string{}, Controls: []ldap.Control{}, ResultCode: ldap.LDAPResultSuccess}, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer