package ad import ( "gopkg.in/ldap.v2" "k8s.io/kubernetes/pkg/util/sets" "github.com/openshift/origin/pkg/auth/ldaputil" "github.com/openshift/origin/pkg/auth/ldaputil/ldapclient" "github.com/openshift/origin/pkg/cmd/admin/groups/sync/groupdetector" "github.com/openshift/origin/pkg/cmd/admin/groups/sync/interfaces" ) // NewLDAPInterface builds a new LDAPInterface using a schema-appropriate config func NewAugmentedADLDAPInterface(clientConfig ldapclient.Config, userQuery ldaputil.LDAPQuery, groupMembershipAttributes []string, userNameAttributes []string, groupQuery ldaputil.LDAPQueryOnAttribute, groupNameAttributes []string) *AugmentedADLDAPInterface { return &AugmentedADLDAPInterface{ ADLDAPInterface: NewADLDAPInterface(clientConfig, userQuery, groupMembershipAttributes, userNameAttributes), groupQuery: groupQuery, groupNameAttributes: groupNameAttributes, cachedGroups: map[string]*ldap.Entry{}, } } // AugmentedADLDAPInterface extracts the member list of an LDAP user entry from an LDAP server // with first-class LDAP entries for users and group. Group membership is on the user. The AugmentedADLDAPInterface is *NOT* thread-safe. type AugmentedADLDAPInterface struct { *ADLDAPInterface // groupQuery holds the information necessary to make an LDAP query for a specific // first-class group entry on the LDAP server groupQuery ldaputil.LDAPQueryOnAttribute // groupNameAttributes defines which attributes on an LDAP group entry will be interpreted as its name to use for an OpenShift group groupNameAttributes []string // cachedGroups holds the result of group queries for later reference, indexed on group UID // e.g. this will map an LDAP group UID to the LDAP entry returned from the query made using it cachedGroups map[string]*ldap.Entry } var _ interfaces.LDAPMemberExtractor = &AugmentedADLDAPInterface{} var _ interfaces.LDAPGroupGetter = &AugmentedADLDAPInterface{} var _ interfaces.LDAPGroupLister = &AugmentedADLDAPInterface{} // GroupEntryFor returns an LDAP group entry for the given group UID by searching the internal cache // of the AugmentedADLDAPInterface first, then sending an LDAP query if the cache did not contain the entry. // This also satisfies the LDAPGroupGetter interface func (e *AugmentedADLDAPInterface) GroupEntryFor(ldapGroupUID string) (*ldap.Entry, error) { group, exists := e.cachedGroups[ldapGroupUID] if exists { return group, nil } searchRequest, err := e.groupQuery.NewSearchRequest(ldapGroupUID, e.requiredGroupAttributes()) if err != nil { return nil, err } group, err = ldaputil.QueryForUniqueEntry(e.clientConfig, searchRequest) if err != nil { return nil, err } // cache for annotation extraction e.cachedGroups[ldapGroupUID] = group return group, nil } func (e *AugmentedADLDAPInterface) requiredGroupAttributes() []string { allAttributes := sets.NewString(e.groupNameAttributes...) // these attributes will be used for a future openshift group name mapping allAttributes.Insert(e.groupQuery.QueryAttribute) // this is used for extracting the group UID (otherwise an entry isn't self-describing) return allAttributes.List() } // Exists determines if a group idenified with its LDAP group UID exists on the LDAP server func (e *AugmentedADLDAPInterface) Exists(ldapGroupUID string) (bool, error) { groupDetector := groupdetector.NewCompoundDetector(groupdetector.NewGroupBasedDetector(e), groupdetector.NewMemberBasedDetector(e)) return groupDetector.Exists(ldapGroupUID) }