Browse code

LDAP group sync proposal

Steve Kuznetsov authored on 2015/07/15 02:47:09
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,134 @@
0
+# Syncing LDAP Groups to OpenShift Groups
1
+
2
+OpenShift cluster admins need a way to sync their OpenShift `Groups` to external records in an LDAP server. This requires that we have a way of retrieving the LDAP users that are the members of a group, determining the OpenShift `Group` name for this collection, updating the OpenShift record and optionally removing the record when the corresponding LDAP record is removed.
3
+
4
+## Use Cases
5
+1. I want to sync all LDAP groups minus some blacklist to OpenShift `Groups`
6
+* I want to sync a specific set of LDAP groups to OpenShift `Groups`
7
+* I want to sync all OpenShift groups belonging to a sync job minus some blacklist with the LDAP server
8
+* I want to sync specific OpenShift `Groups` with the LDAP server records
9
+* I want to remove OpenShift `Groups` that were previously backed by LDAP records that no longer exist
10
+* I want to specify an explicit mapping from LDAP group identifiers to OpenShift `Group` resources
11
+
12
+## Supported LDAP Group Schemas
13
+1. Groups as first-class LDAP entries with an attribute containing a list of members:
14
+  1. members listed with their DN in the attribute
15
+  * members listed with some other UID in the attribute
16
+* Users as first-class LDAP entries with an attribute containing a list of groups they are a member of:
17
+  1. groups listed by a unique name, with no additional group metadata in the LDAP server
18
+  * groups listed by DN, with the first-class group entries holding additional metadata
19
+  * groups listed by some other UID, with the first-class group entries holding additional metadata
20
+
21
+## Changes To OpenShift `Group` Metadata
22
+OpenShift `Group`'s `Annotations` will be used to store metadata regarding the sync process. `Annotations` will store:
23
+
24
+1. LDAP unique identifier (`openshift.io/ldap.uid`)
25
+* last sync time (`openshift.io/ldap.sync-time`)
26
+
27
+OpenShift `Group`'s `Labels` will also be used to store metadata regarding the sync process. `Labels` will store:
28
+
29
+1. LDAP server URL (`openshift.io/external-record-provider-url`).
30
+
31
+## Data Flow
32
+1. Determine ordered list of LDAP groups to be sync
33
+  1. For each group to sync:
34
+  * Collect LDAP group members and group metadata
35
+  * Determine OpenShift `Identities` from LDAP group member entries
36
+  * Determine OpenShift `Users` from OpenShift `Identities`
37
+  * Determine OpenShift `Group` from LDAP group metadata or explicit mapping
38
+  * Populate new OpenShift `Group`'s `Users` from resulting OpenShift `UserIdentityMappings`, update OpenShift `Group` metadata fields tied to LDAP attributes, leave other OpenShift `Group` fields unchanged
39
+
40
+##  Determining Ordered List of LDAP Groups To Sync
41
+An `LDAPGroupLister` determines what LDAP groups needs to be synced and outputs the result as a set of unique identifier strings (called "LDAP group UIDs" in this document). The other objects that take LDAP group UIDs need to understand the format of this string (e.g. these objects will be tightly coupled). For example, an `LDAPGroupLister` for schema 1 above cannot be used with a `LDAPGroupDataExtractor` for schema 2. The four `LDAPGroupLister` implementations that are necessary are:
42
+
43
+1. List LDAP group UIDs for all OpenShift `Groups` matching a `Label` selector identifying them as pertaining to the sync job, minus a blacklist
44
+* List LDAP group UIDs for some whitelist of OpenShift `Groups`
45
+* List LDAP group UIDs for all LDAP groups, minus a blacklist
46
+* List LDAP group UIDs for some whitelist of LDAP groups
47
+
48
+```go
49
+// LDAPGroupLister lists the LDAP groups that need to be synced by a job. The LDAPGroupLister needs to
50
+// be paired with an LDAPGroupDataExtractor that understands the format of the unique identifiers
51
+// returned to represent the LDAP groups to be synced.
52
+type LDAPGroupLister interface {
53
+	ListGroups() (groupUIDs []string, err error)
54
+}
55
+```
56
+
57
+## Collecting LDAP Members and Metadata
58
+An `LDAPGroupDataExtractor` gathers information on an LDAP group based on an LDAP group UID. It may cache LDAP responses for responsivity. The approach to implementing this structure will vary with LDAP schema as well as sync job request.
59
+
60
+```go
61
+// LDAPGroupDataExtractor retrieves data about an LDAP group from the LDAP server.
62
+type LDAPGroupDataExtractor interface {
63
+	// ExtractMembers returns the list of LDAP first-class user entries that are members of the LDAP
64
+	// group specified by the groupUID
65
+	ExtractMembers(groupUID string) (members []*ldap.Entry, err error)
66
+}
67
+```
68
+
69
+## Determining OpenShift `User` Names for LDAP Members
70
+The mapping of a LDAP member entry to an OpenShift `User` Name will be deterministic and simple: whatever LDAP entry attribute is used for the OpenShift `User` Name field upon creation of OpenShift `Users` will be used as the OpenShift `User` Name. As long as the `DeterministicUserIdentityMapper` is used to introduce LDAP member entries to OpenShift `User` records and the `LDAPUserToIdentityMapping` used for the sync job and `DeterministicUserIdentityMapper` is the same, the mappings created by the `LDAPUserNameMapper` will be correct.
71
+
72
+```go
73
+// LDAPUserNameMapper maps an LDAP entry representing a user to the OpenShift User Name corresponding to it
74
+type LDAPUserNameMapper interface {
75
+	UserNameFor(ldapUser *ldap.Entry) (openShiftUserName string, err error)
76
+}
77
+```
78
+
79
+## Determining OpenShift `Users` for OpenShift `Identities`
80
+A new `UserIdentityMapper` will need to be created: the `DeterministicUserIdentityMapper`, which will assume that the unique identifier retrieved from the LDAP response and integrated into the OpenShift `Identity` will be deterministicically mapped to an OpenShift `User`. This is required as otherwise there is no deterministic mapping from the `Identity` created and any OpenShift `User`. This will not be used in the sync job itself but will be necessary for creating OpenShift `Users` when migrating them from an LDAP server.
81
+
82
+```go
83
+// DeterministicUserIdentityMapper is a UserIdentityMapper that forces a deterministic mapping from
84
+// an Identity to a User.
85
+type DeterministicUserIdentityMapper struct {
86
+  // AllowIdentityCollisions determines if this UserIdentityMapper is allowed to make a mapping
87
+  // between an Identity provided by LDAP and a User that already is mapped to another Identity.
88
+  AllowIdentityCollisions bool
89
+}
90
+
91
+func (m *DeterministicUserIdentityMapper) UserFor(identity authapi.UserIdentityInfo) (user user.Info,
92
+	err error) {
93
+}
94
+```
95
+
96
+## Creating OpenShift `Groups`
97
+1. Find the OpenShift `Group` or start one if it does not exist
98
+* Populate `Annotations` and `Labels`
99
+* Overwrite `Users` list
100
+* Replace current OpenShift `Group` or create it
101
+
102
+An `LDAPGroupNameMapper` will be used to determine the name of the OpenShift `Group` record that matches a given LDAP entry representing a group. This mapping can be done with a user-defined hard mapping from LDAP group UID to OpenShift `Group` Name or a dynamic user-defined mapping of LDAP group entry attributes to OpenShift `Group` Name.
103
+
104
+```go
105
+// LDAPGroupNameMapper maps an LDAP group UID identifying a group entry to the OpenShift Group name for it
106
+type LDAPGroupNameMapper interface {
107
+  GroupNameFor(ldapGroupUID string) (openShiftGroupName string, err error)
108
+}
109
+```
110
+
111
+## Exposed Options for `oadm sync-groups`
112
+The sync command will be exposed as `oadm sync-groups [<openshift-group-name>...] --sync-config=<location>` and invoked like:
113
+* `oadm sync-groups --all-openshift --sync-config=/etc/openshift/ldap-sync-config.yaml`
114
+* `oadm sync-groups <names> --sync-config=/etc/openshift/ldap-sync-config.yaml`
115
+* `oadm sync-groups --all-ldap --sync-config=/etc/openshift/ldap-sync-config.yaml`
116
+* `oadm sync-groups --whitelist-ldap --sync-config=/etc/openshift/ldap-sync-config.yaml`
117
+* `oadm sync-groups --prune --sync-config=/etc/openshift/ldap-sync-config.yaml`
118
+
119
+The sync command will default to doing a dry-run.
120
+
121
+`--sync-config=/path/to/file` determines where the config `yaml` is located.
122
+
123
+`--all-openshift` would specify that all OpenShift `Groups` need to be synced
124
+
125
+`--all-ldap` would specify that all LDAP groups need to be synced
126
+
127
+`--whitelist-ldap=/path/to/file` would specify that an LDAP whitelist file containing LDAP group UIDs contains all the groups that need to be synced and determines where the file is located
128
+
129
+`--prune` removes OpenShift `Group` records linked to an LDAP record that no longer exists
130
+
131
+`--confirm` makes the proposed changes
132
+
133
+`-o <json,yaml>` Format for the output of a `--dry-run` should be tuneable from human-readable, `json`, or `yaml`. The latter two formats should output in a format useable by `oc replace`