GitLab Automation – Automatically Block GitLab Users Removed from LDAP

automationgitlabldapuser-management

I've migrated this question from StackOverflow.

I'm administering a Gitlab-Omnibus (Community Edition) instance in our company as an additional duty.

Gitlab uses company's Active Directory server for authentication. Our network managers create AD accounts for new employees and remove them after they leave. Gitlab normally creates its own user accounts on first login and blocks them on sign-in attempts after the AD account is removed.

Then it should be very easy to clean those "dead souls".

The problem is: users are not blocked, the status of the Gitlab account remains "Active" after an employee leaves, because nobody tries to sign in to the Gitlab after leaving. The server itself is inaccessible from the Internet, ex-employees cannot enter the office since their pass cards are destroyed, their PCs are disassembled or formatted with a fresh OS install.

So, I have to manually try to impersonate each account and check if Gitlab blocks it (thanks Gitlab developers for the Impersonation feature, at least something I've got).

I'd like to automate this process, because there are over 100 user accounts in Gitlab, and I don't receive notifications about those employees who has left the company (I'm neither HR manager, nor sysadmin; I also generally don't need them, because there are many employees that do not require Gitlab accounts).

My goal is to develop a script or a Ruby snippet that I could paste into the gitlab-rails console.

This snippet should scan all users, registered in Gitlab, check their existence in LDAP and block all missing in LDAP.

Then I would review all blocked users, transfer their personal projects to their supervisors and remove them.

The problem is that I'm completely not familiar neither with Ruby, nor with Gitlab internals.

Any help?

I do:

irb(main):039:0> User.all
=> #<ActiveRecord::Relation [#<User id:98 @n.name>, #<User id:86 @n.name2>,  ...]>

But:

irb(main):040:0> for u in User.all do
irb(main):041:1* puts u
irb(main):042:1> done
irb(main):043:1>
irb(main):044:1* ^C
irb(main):044:0>

No output.

What am I doing wrong?

Update

Correct loop syntax should be like this:

User.all.each { |u| puts u.name }

Now it is time to wait for someone leaving and find what to check to set u.state = "ldap_blocked"

Best Answer

Python-gitlab solves the problem in combination with https://ldap3.readthedocs.io/

Here is the code:

import time
from ldap3 import Server, Connection
import gitlab


GITLAB_SERVER = 'https://gitlab.example.com'
LDAP_SERVER = 'ldap.example.com'
no_block = {'root', 'ghost', 'other_custom_user'}


def main():
    gl = gitlab.Gitlab(GITLAB_SERVER, private_token='')

    server = Server(LDAP_SERVER)
    conn = Connection(server,
                      user='CN=Bind User,CN=Users,DC=example,DC=com',
                      password='highly_secret_password')
    conn.bind()

    users = gl.users.list(all=True)
    gitlab_users = {u.attributes['username']: u for u in users}
    ldap_filter = '(&(objectclass=person)(|' + ''.join(['(samaccountname='+u+')' for u in gitlab_users.keys()]) + '))'
    print(conn.search('DC=example,DC=com', ldap_filter, attributes=['cn', 'samaccountname']))

    ldap_users = {str(u.sAMAccountName) for u in conn.entries}
    to_block = set(gitlab_users.keys()).difference(ldap_users).difference(no_block)

    print("Following users will be blocked: {}".format(to_block))
    print("Waiting 10 seconds, then block")

    time.sleep(10)

    for u in to_block:
        user = gitlab_users[u]
        user.block()
        user.save()


if __name__ == '__main__':
    main()
Related Topic