Adambean / gitlab-ce-ldap-sync

Synchronise users and groups (including group members) from an LDAP instance with Gitlab CE (and EE in free tier) self-hosted instance(s).
Apache License 2.0
61 stars 23 forks source link

Reenabled users stay blocked in GitLab #4

Closed jsiegers closed 5 years ago

jsiegers commented 5 years ago

I'm using FreeIPA where you can disable a user (so it still exists). When that happens the user disappears from LDAP itself. In this case I've disabled the user rdkoning. I then get this error:

[info] Group "externals" members are external.
[warning] Group #3 / member #1: User not found "gitlab01".
[warning] Group #3 / member #2: User not found "gitlab02".
[notice] 0 directory group "externals" member(s) recognised.
[notice] Disabling Gitlab users of which don't exist in directory...
[warning] Disabling Gitlab user #4 "rdkoning".
[notice] 1 Gitlab user(s) disabled.
[notice] Updating users of which were already in both Gitlab and the directory...
[info] Updating Gitlab user #4 "rdkoning".
[error] Gitlab user "rdkoning" has no LDAP details available. This should not happen!

What has happened inside GitLab is that this user is now blocked and marked as external. Blocked I get but don't really understand why it's now marked as external. Perhaps this is something GitLab does? Please note that the user still exists in FreeIPA and is inside FreeIPA still a member of it's groups.

When I now renable the user again and sync it then everything looks alright. The user is placed inside of every group again, etc. But inside GitLab the user is now no longer an external user but is still blocked!

I'm expecting that when I reenable a user that it's no longer external and no longer blocked.

Here is the output of the sync after I've reenabled the user:

[notice] Loading configuration.
[notice] Loaded configuration.
[notice] Validating configuration.
[notice] Validated configuration.
[notice] Retrieving directory users and groups.
[notice] Establishing LDAP connection.
[notice] LDAP connection established.
[notice] 8 directory user(s) found.
[info] Found directory user "jsiegers" [uid=jsiegers,cn=users,cn=accounts,dc=postlab,dc=cloud].
[info] Found directory user "pmlombert" [uid=pmlombert,cn=users,cn=accounts,dc=postlab,dc=cloud].
[info] Found directory user "rdkoning" [uid=rdkoning,cn=users,cn=accounts,dc=postlab,dc=cloud].
[info] Found directory user "tvdmaat" [uid=tvdmaat,cn=users,cn=accounts,dc=postlab,dc=cloud].
[info] User "gitlab01" in ignore list.
[info] User "gitlab02" in ignore list.
[info] User "gitlab-ldap-bind-user" in ignore list.
[notice] 4 directory user(s) recognised.
[notice] 6 directory group(s) found.
[info] Found directory group "gitlab-admins".
[info] Group "gitlab-admins" members are administrators.
[warning] Group #1 / member #1: User not found "gitlab01".
[notice] 0 directory group "gitlab-admins" member(s) recognised.
[info] Found directory group "hedge".
[info] Found directory group "hedge" member "pmlombert".
[info] Found directory group "hedge" member "rdkoning".
[info] Found directory group "hedge" member "tvdmaat".
[info] Found directory group "hedge" member "jsiegers".
[warning] Group #2 / member #5: User not found "gitlab01".
[notice] 4 directory group "hedge" member(s) recognised.
[info] Found directory group "externals".
[info] Group "externals" members are external.
[warning] Group #3 / member #1: User not found "gitlab01".
[warning] Group #3 / member #2: User not found "gitlab02".
[notice] 0 directory group "externals" member(s) recognised.
[info] Group "postlab-cloud" in ignore list.
[info] Found directory group "test-team-3".
[warning] Group #5 / member #1: User not found "gitlab01".
[info] Found directory group "test-team-3" member "jsiegers".
[info] Found directory group "test-team-3" member "rdkoning".
[notice] 2 directory group "test-team-3" member(s) recognised.
[notice] 4 directory group(s) recognised.
[notice] LDAP connection closed.
[notice] Retrieved directory users and groups.
[notice] Deploying users and groups to Gitlab instances.
[notice] Establishing Gitlab connection.
[notice] Finding all existing Gitlab users...
[info] Found Gitlab user #5 "tvdmaat".
[info] Found Gitlab user #4 "rdkoning".
[info] Found Gitlab user #3 "pmlombert".
[info] Found Gitlab user #2 "jsiegers".
[info] Gitlab built-in root user will be ignored.
[notice] 4 Gitlab user(s) found.
[notice] Creating directory users of which don't exist in Gitlab...
[notice] 0 Gitlab user(s) created.
[notice] Disabling Gitlab users of which don't exist in directory...
[notice] 0 Gitlab user(s) disabled.
[notice] Updating users of which were already in both Gitlab and the directory...
[info] Updating Gitlab user #2 "jsiegers".
[info] Updating Gitlab user #3 "pmlombert".
[info] Updating Gitlab user #4 "rdkoning".
[info] Updating Gitlab user #5 "tvdmaat".
[notice] 4 Gitlab user(s) updated.
[notice] Finding all existing Gitlab groups...
[info] Found Gitlab group #11 "hedge" [hedge].
[info] Found Gitlab group #9 "test team 3" [test-team-3].
[notice] 2 Gitlab group(s) found.
[notice] Creating directory groups of which don't exist in Gitlab...
[warning] Not creating Gitlab group "externals" [externals]: No members in directory group, or config gitlab->options->createEmptyGroups is disabled.
[warning] Not creating Gitlab group "gitlab admins" [gitlab-admins]: No members in directory group, or config gitlab->options->createEmptyGroups is disabled.
[notice] 0 Gitlab group(s) created.
[notice] Deleting Gitlab groups of which don't exist in directory...
[notice] 0 Gitlab group(s) deleted.
[notice] Updating groups of which were already in both Gitlab and the directory...
[info] Updating Gitlab group #11 "hedge" [hedge].
[info] Updating Gitlab group #9 "test team 3" [test-team-3].
[notice] 2 Gitlab group(s) updated.
[notice] Synchronising Gitlab group members with directory group members...
[notice] Synchronising 4 member(s) for group #11 "hedge" [hedge]...
[notice] Finding existing group members...
[info] Gitlab built-in root user will be ignored.
[info] Found Gitlab group member #2 "jsiegers".
[info] Found Gitlab group member #3 "pmlombert".
[info] Found Gitlab group member #5 "tvdmaat".
[notice] 3 Gitlab group "hedge" [hedge] member(s) found.
[notice] Adding missing group members...
[info] Adding user #4 "rdkoning" to group #11 "hedge" [hedge].
[notice] 1 Gitlab group "hedge" [hedge] member(s) added.
[notice] Deleting extra group members...
[notice] 0 Gitlab group "hedge" [hedge] member(s) deleted.
[notice] Synchronising 2 member(s) for group #9 "test team 3" [test-team-3]...
[notice] Finding existing group members...
[info] Gitlab built-in root user will be ignored.
[info] Found Gitlab group member #2 "jsiegers".
[notice] 1 Gitlab group "test team 3" [test-team-3] member(s) found.
[notice] Adding missing group members...
[info] Adding user #4 "rdkoning" to group #9 "test team 3" [test-team-3].
[notice] 1 Gitlab group "test team 3" [test-team-3] member(s) added.
[notice] Deleting extra group members...
[notice] 0 Gitlab group "test team 3" [test-team-3] member(s) deleted.
[notice] Gitlab connection closed.
[notice] Deployed users and groups to Gitlab instances.
Adambean commented 5 years ago

I'm using FreeIPA where you can disable a user (so it still exists). When that happens the user disappears from LDAP itself. In this case I've disabled the user rdkoning. I then get this error:

[notice] Updating users of which were already in both Gitlab and the directory...
[info] Updating Gitlab user #4 "rdkoning".
[error] Gitlab user "rdkoning" has no LDAP details available. This should not happen!

What has happened inside GitLab is that this user is now blocked and marked as external. Blocked I get but don't really understand why it's now marked as external. Perhaps this is something GitLab does? Please note that the user still exists in FreeIPA and is inside FreeIPA still a member of it's groups.

I get why that error is happening. It's because it's trying to sync the user's details (name, email, isAdmin, isExternal, etc) based on what's been seen by LDAP, but the user's LDAP details are no longer available because you've disabled it. -- The LDAP query you've used is likely filtering disabled users out intentionally with the "nsAccountLock" attribute.

There is nothing wrong here other than the over-emphasis of the error message. It just needs to be a less shouty information message.

Adambean commented 5 years ago

What has happened inside GitLab is that this user is now blocked and marked as external. Blocked I get but don't really understand why it's now marked as external. Perhaps this is something GitLab does?

This is something I did:

!$this->dryRun ? ($gitlabUser = $gitlab->api("users")->block($gitlabUserId)) : $this->logger->warning("Operation skipped due to dry run.");
!$this->dryRun ? ($gitlabUser = $gitlab->api("users")->update($gitlabUserId, [
    "admin"             => false,
    "can_create_group"  => false,
    "external"          => true,
])) : $this->logger->warning("Operation skipped due to dry run.");

Setting external to true is probably a bit overcautious, but when a user is re-enabled that external flag (should) be updated according to their group's external configuration.

Adambean commented 5 years ago

When I now renable the user again and sync it then everything looks alright. The user is placed inside of every group again, etc. But inside GitLab the user is now no longer an external user but is still blocked!

I'm expecting that when I reenable a user that it's no longer external and no longer blocked.

Here is the output of the sync after I've reenabled the user:

I'm not seeing any errors there, or that the user is being re-created. I think what's been missed is an API call to unblock the user. This can likely be resolved as follows:

if ($gitlab->api("users")->all(["username" => $gitlabUserName, "blocked" => true])) {
    $this->logger->info(sprintf("Enabling Gitlab user #%d \"%s\".", $gitlabUserId, $gitlabUserName));
    $gitlabUser = null;
    !$this->dryRun ? ($gitlabUser = $gitlab->api("users")->unblock($gitlabUserId)) : $this->logger->warning("Operation skipped due to dry run.");
}

It should be inserted into the block for updating user details just before $this->logger->info(sprintf("Updating Gitlab user #%d \"%s\".", $gitlabUserId, $gitlabUserName)); near line 1081 as follows:

if ($this->in_array_i($gitlabUserName, $config["gitlab"]["options"]["userNamesToIgnore"])) {
    $this->logger->info(sprintf("User \"%s\" in ignore list.", $gitlabUserName));
    continue;
}

if ($gitlab->api("users")->all(["username" => $gitlabUserName, "blocked" => true])) {
    $this->logger->info(sprintf("Enabling Gitlab user #%d \"%s\".", $gitlabUserId, $gitlabUserName));
    $gitlabUser = null;
    !$this->dryRun ? ($gitlabUser = $gitlab->api("users")->unblock($gitlabUserId)) : $this->logger->warning("Operation skipped due to dry run.");
}

$this->logger->info(sprintf("Updating Gitlab user #%d \"%s\".", $gitlabUserId, $gitlabUserName));
$gitlabUser = null;

I've not tested this out yet.

Adambean commented 5 years ago

Just tested it, seemed to work fine.

Forgot to reference this issue in my commit, but here it is.

Revision: 6eb1398b845ccddaefa2fd139dbb11f0d7f1d4d2
Author: Adam Reece
Date: 09/03/2019 11:46:07
Message:
Fixed user not being unblocked after re-appearing in the directory.

----
Modified: src/LdapSyncCommand.php
jsiegers commented 5 years ago

Cheers again! It also works now over here!