From f11bb8bfd4a57d58b032637449687fc77011be66 Mon Sep 17 00:00:00 2001 From: vherrlein Date: Mon, 9 Oct 2023 13:17:46 +0200 Subject: [PATCH] providers/ldap: add windows adsi support (#7098) * fix(outpost/ldap): missing user object classes * add "person" object class * update user object classes * update boolean strings to upper for being compliant tags: WIP-LDAP-Outpost-Windows-ADSI-Support * feat(outpost/ldap): add subschema attributes * add supported capability OIDs for Windows * add relevant supported ldap control OIDs tags: WIP-LDAP-Outpost-Windows-ADSI-Support * feat(outpost/ldap): update schema for windows Compatibility * add relevant dITContentRules for authentik * add all existing attribute types for Windows/Unix/Linux * add missing object classes definitions * update classes definitions for being compliant with LDAP schema * update attributes orders tags: WIP-LDAP-Outpost-Windows-ADSI-Support * feat(outpost/ldap): refine LDAP attribute types * remove unsused attribute types * order attribute types tags: WIP-LDAP-Outpost-Windows-ADSI-Support --- internal/outpost/ldap/constants/constants.go | 3 + internal/outpost/ldap/entries.go | 10 +- internal/outpost/ldap/search/direct/base.go | 23 +++++ internal/outpost/ldap/search/direct/schema.go | 94 +++++++++++-------- 4 files changed, 88 insertions(+), 42 deletions(-) diff --git a/internal/outpost/ldap/constants/constants.go b/internal/outpost/ldap/constants/constants.go index cfa85711e..a60db0e9f 100644 --- a/internal/outpost/ldap/constants/constants.go +++ b/internal/outpost/ldap/constants/constants.go @@ -25,6 +25,7 @@ const ( ) const ( + OCPerson = "person" OCUser = "user" OCOrgPerson = "organizationalPerson" OCInetOrgPerson = "inetOrgPerson" @@ -54,6 +55,8 @@ func GetContainerOCs() map[string]bool { func GetUserOCs() map[string]bool { return map[string]bool{ + OCTop: true, + OCPerson: true, OCUser: true, OCOrgPerson: true, OCInetOrgPerson: true, diff --git a/internal/outpost/ldap/entries.go b/internal/outpost/ldap/entries.go index 23bab252d..2236a9964 100644 --- a/internal/outpost/ldap/entries.go +++ b/internal/outpost/ldap/entries.go @@ -31,8 +31,8 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry { u.Email = api.PtrString("") } attrs = utils.EnsureAttributes(attrs, map[string][]string{ - "ak-active": {strconv.FormatBool(*u.IsActive)}, - "ak-superuser": {strconv.FormatBool(u.IsSuperuser)}, + "ak-active": {strings.ToUpper(strconv.FormatBool(*u.IsActive))}, + "ak-superuser": {strings.ToUpper(strconv.FormatBool(u.IsSuperuser))}, "memberOf": pi.GroupsForUser(u), "cn": {u.Username}, "sAMAccountName": {u.Username}, @@ -41,11 +41,13 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry { "displayName": {u.Name}, "mail": {*u.Email}, "objectClass": { - constants.OCUser, + constants.OCTop, + constants.OCPerson, constants.OCOrgPerson, constants.OCInetOrgPerson, - constants.OCAKUser, + constants.OCUser, constants.OCPosixAccount, + constants.OCAKUser, }, "uidNumber": {pi.GetUidNumber(u)}, "gidNumber": {pi.GetUidNumber(u)}, diff --git a/internal/outpost/ldap/search/direct/base.go b/internal/outpost/ldap/search/direct/base.go index 87eadd715..0f87b7bf3 100644 --- a/internal/outpost/ldap/search/direct/base.go +++ b/internal/outpost/ldap/search/direct/base.go @@ -33,6 +33,29 @@ func (ds *DirectSearcher) SearchBase(req *search.Request) (ldap.ServerSearchResu Name: "supportedLDAPVersion", Values: []string{"3"}, }, + { + Name: "supportedCapabilities", + Values: []string{ + "1.2.840.113556.1.4.800", //LDAP_CAP_ACTIVE_DIRECTORY_OID + "1.2.840.113556.1.4.1791", //LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID + "1.2.840.113556.1.4.1670", //LDAP_CAP_ACTIVE_DIRECTORY_V51_OID + "1.2.840.113556.1.4.1880", //LDAP_CAP_ACTIVE_DIRECTORY_ADAM_DIGEST_OID + "1.2.840.113556.1.4.1851", //LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID + "1.2.840.113556.1.4.1920", //LDAP_CAP_ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID + "1.2.840.113556.1.4.1935", //LDAP_CAP_ACTIVE_DIRECTORY_V60_OID + "1.2.840.113556.1.4.2080", //LDAP_CAP_ACTIVE_DIRECTORY_V61_R2_OID + "1.2.840.113556.1.4.2237", //LDAP_CAP_ACTIVE_DIRECTORY_W8_OID + }, + }, + { + Name: "supportedControl", + Values: []string{ + "2.16.840.1.113730.3.4.9", //VLV Request LDAPv3 Control + "2.16.840.1.113730.3.4.10", //VLV Response LDAPv3 Control + "1.2.840.113556.1.4.474", //Sort result + "1.2.840.113556.1.4.319", //Paged Result Control + }, + }, { Name: "subschemaSubentry", Values: []string{"cn=subschema"}, diff --git a/internal/outpost/ldap/search/direct/schema.go b/internal/outpost/ldap/search/direct/schema.go index 81e601846..669bb6a3b 100644 --- a/internal/outpost/ldap/search/direct/schema.go +++ b/internal/outpost/ldap/search/direct/schema.go @@ -29,62 +29,80 @@ func (ds *DirectSearcher) SearchSubschema(req *search.Request) (ldap.ServerSearc }, }, { - Name: "objectClasses", + Name: "dITContentRules", Values: []string{ - "( 2.5.6.0 NAME 'top' ABSTRACT MUST ( objectClass ) MAY (cn $ description $ displayName $ memberOf $ name ) )", - "( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( cn ) MAY (sn $ telephoneNumber ) )", - "( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL MAY (c $ l $ o $ ou $ title $ givenName $ co $ department $ company $ division $ mail $ mobile $ telephoneNumber ) )", - "( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST (cn $ member ) MAY (o $ ou ) )", - "( 1.2.840.113556.1.5.9 NAME 'user' SUP organizationalPerson STRUCTURAL MAY ( name $ displayName $ uid $ mail ) )", - "( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY MAY (cn $ description $ homeDirectory $ uid $ uidNumber $ gidNumber ) )", - "( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' AUX ( posixAccount ) MUST ( sAMAccountName ) MAY ( uidNumber $ gidNumber ))", - // Custom attributes - // Temporarily use 1.3.6.1.4.1.26027.1.1 as a base - // https://docs.oracle.com/cd/E19450-01/820-6169/working-with-object-identifiers.html#obtaining-a-base-oid - "( 1.3.6.1.4.1.26027.1.1.1 NAME 'goauthentik.io/ldap/user' SUP organizationalPerson STRUCTURAL MAY ( ak-active $ sAMAccountName $ goauthentikio-user-sources $ goauthentik.io/user/sources $ goauthentik.io/ldap/active $ goauthentik.io/ldap/superuser ) )", + "( 2.5.6.0 NAME 'top' )", + "( 2.5.6.6 NAME 'person' )", + "( 2.5.6.7 NAME 'organizationalPerson' )", + "( 2.5.6.9 NAME 'groupOfNames' )", + "( 1.2.840.113556.1.5.9 NAME 'user' )", + "( 1.3.6.1.1.1.2.0 NAME 'posixAccount' )", + "( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' )", + "( 1.3.6.1.4.1.26027.1.1.1 NAME 'goauthentik.io/ldap/user' )", }, }, { Name: "attributeTypes", Values: []string{ - "( 2.5.4.0 NAME 'objectClass' DESC 'RFC4512: object classes of the entity' EQUALITY objectIdentifierMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", - "( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts' DESC 'RFC4512: naming contexts' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )", - "( 2.5.18.10 NAME 'subschemaSubentry' DESC 'RFC4512: name of controlling subschema entry' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", - "( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion' DESC 'RFC4512: supported LDAP versions' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )", - "( 1.3.6.1.1.20 NAME 'entryDN' DESC 'DN of the entry' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )", - "( 1.3.6.1.1.4 NAME 'vendorName' DESC 'RFC3045: name of implementation vendor' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )", - "( 1.3.6.1.1.5 NAME 'vendorVersion' DESC 'RFC3045: version of implementation' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE NO-USER-MODIFICATION USAGE dSAOperation )", - "( 0.9.2342.19200300.100.1.1 NAME 'uid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 0.9.2342.19200300.100.1.3 NAME 'mail' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 0.9.2342.19200300.100.1.41 NAME 'mobile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.2.102 NAME 'memberOf' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION )", - "( 1.2.840.113556.1.2.13 NAME 'displayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.4.1 NAME 'name' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE NO-USER-MODIFICATION )", - "( 1.2.840.113556.1.2.131 NAME 'co' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.2.141 NAME 'department' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.2.146 NAME 'company' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.4.44 NAME 'homeDirectory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.4.221 NAME 'sAMAccountName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.2.840.113556.1.4.261 NAME 'division' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 1.3.6.1.1.1.1.0 NAME 'uidNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )", - "( 1.3.6.1.1.1.1.1 NAME 'gidNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )", + "( 2.5.4.0 NAME 'objectClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION )", + "( 2.5.4.4 NAME 'sn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 2.5.4.3 NAME 'cn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.6 NAME 'c' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.7 NAME 'l' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.10 NAME 'o' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )", "( 2.5.4.11 NAME 'ou' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )", - "( 2.5.4.20 NAME 'telephoneNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 2.5.4.42 NAME 'givenName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 2.5.4.0 NAME 'objectClass' SYNTAX '1.3.6.1.4.1.1466.115.121.1.38' NO-USER-MODIFICATION )", - "( 2.5.4.3 NAME 'cn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", - "( 2.5.4.4 NAME 'sn' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.12 NAME 'title' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.13 NAME 'description' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )", + "( 2.5.4.20 NAME 'telephoneNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", "( 2.5.4.31 NAME 'member' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' )", + "( 2.5.4.42 NAME 'givenName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 2.5.21.2 NAME 'dITContentRules' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION )", + "( 2.5.21.5 NAME 'attributeTypes' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION )", + "( 2.5.21.6 NAME 'objectClasses' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' NO-USER-MODIFICATION )", + "( 0.9.2342.19200300.100.1.1 NAME 'uid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )", + "( 0.9.2342.19200300.100.1.3 NAME 'mail' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 0.9.2342.19200300.100.1.41 NAME 'mobile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.2.13 NAME 'displayName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.2.146 NAME 'company' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.2.102 NAME 'memberOf' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' NO-USER-MODIFICATION )", + "( 1.2.840.113556.1.2.131 NAME 'co' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.2.141 NAME 'department' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.4.1 NAME 'name' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE NO-USER-MODIFICATION )", + "( 1.2.840.113556.1.4.44 NAME 'homeDirectory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.4.221 NAME 'sAMAccountName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.4.261 NAME 'division' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + "( 1.2.840.113556.1.4.750 NAME 'groupType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )", + "( 1.2.840.113556.1.4.782 NAME 'objectCategory' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )", + "( 1.3.6.1.1.1.1.0 NAME 'uidNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )", + "( 1.3.6.1.1.1.1.1 NAME 'gidNumber' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )", + "( 1.3.6.1.1.1.1.12 NAME 'memberUid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )", + // Custom attributes // Temporarily use 1.3.6.1.4.1.26027.1.1 as a base // https://docs.oracle.com/cd/E19450-01/820-6169/working-with-object-identifiers.html#obtaining-a-base-oid "( 1.3.6.1.4.1.26027.1.1.2 NAME ( 'goauthentik.io/ldap/superuser' 'ak-superuser' ) SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE )", "( 1.3.6.1.4.1.26027.1.1.3 NAME ( 'goauthentik.io/ldap/active' 'ak-active' ) SYNTAX '1.3.6.1.4.1.1466.115.121.1.7' SINGLE-VALUE )", + "( 1.3.6.1.4.1.26027.1.1.4 NAME ( 'goauthentik.io/ldap/sources' 'goauthentikio-user-sources' ) SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )", + }, + }, + { + Name: "objectClasses", + Values: []string{ + "( 2.5.6.0 NAME 'top' ABSTRACT MUST ( objectClass ) MAY ( objectCategory $ cn $ description $ displayName $ memberOf $ name ) )", + "( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( cn ) MAY ( sn $ telephoneNumber ) )", + "( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL MAY ( c $ l $ o $ ou $ title $ givenName $ co $ department $ company $ division $ mail $ mobile $ telephoneNumber ) )", + "( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST ( cn $ member ) MAY ( o $ ou ) )", + "( 1.2.840.113556.1.5.9 NAME 'user' SUP organizationalPerson STRUCTURAL MAY ( name $ displayName $ uid $ mail ) )", + "( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY MAY ( cn $ description $ homeDirectory $ uid $ uidNumber $ gidNumber ) )", + "( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' SUP user STRUCTURAL MAY ( uidNumber $ gidNumber $ displayName $ homeDirectory ) )", + "( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ( ou ) MAY ( c $ l ) )", + "( 1.2.840.113556.1.5.8 NAME 'group' SUP top AUXILIARY MAY ( cn $ groupType $ member ) )", + "( 1.3.6.1.1.1.2.2 NAME 'posixGroup' SUP top AUXILIARY MAY ( cn $ description $ gidNumber $ memberUid ) )", + "( 2.5.20.1 NAME 'subSchema' SUP top STRUCTURAL MAY ( dITContentRules $ attributeTypes $ objectClasses ) )", + // Custom attributes + // Temporarily use 1.3.6.1.4.1.26027.1.1 as a base + // https://docs.oracle.com/cd/E19450-01/820-6169/working-with-object-identifiers.html#obtaining-a-base-oid + "( 1.3.6.1.4.1.26027.1.1.1 NAME 'goauthentik.io/ldap/user' SUP organizationalPerson STRUCTURAL MAY ( ak-superuser $ ak-active $ sAMAccountName $ goauthentikio-user-sources $ goauthentik.io/user/sources $ goauthentik.io/ldap/active $ goauthentik.io/ldap/superuser ) )", }, }, },