From 60ac877d38acd01660c06a700806ec620d5a26e0 Mon Sep 17 00:00:00 2001 From: Dave Zolotusky Date: Mon, 15 Nov 2021 20:39:58 +0100 Subject: [PATCH 1/2] python3 and minor output improvements fix print statements to work with Python3 replace .iterkeys() with .keys for Python3 rename "github" to "only_in_github" don't print users that were added to members list for to_add_to_github as github_user_that_quit if there are duplicate github usernames in LDAP. This happens when people enter things like "n/a" or '' for their github name in LDAP. --- .../add_ldap_users_to_employees.py | 2 +- .../check_github_users_in_ldap.py | 18 +++++++++--------- github_user_management/get_keys_for_org.py | 2 +- .../github_details_for_users.py | 4 ++-- .../org_owners_without_ldap_connection.py | 10 +++++----- requirements.txt | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/github_user_management/add_ldap_users_to_employees.py b/github_user_management/add_ldap_users_to_employees.py index 50e918b..63746a2 100644 --- a/github_user_management/add_ldap_users_to_employees.py +++ b/github_user_management/add_ldap_users_to_employees.py @@ -15,4 +15,4 @@ def check_github_usernames(github_token, ldap_url, ldap_base, github_url): print ("ldap user %s doesn't have a valid github user: %s" % (user, github_user)) else: - print github_user + print (github_user) diff --git a/github_user_management/check_github_users_in_ldap.py b/github_user_management/check_github_users_in_ldap.py index 0e06b7d..03ab758 100644 --- a/github_user_management/check_github_users_in_ldap.py +++ b/github_user_management/check_github_users_in_ldap.py @@ -11,30 +11,30 @@ def print_dict_keys_per_value(d, exclude, check_existence_for_these): for k in d: by_value[d[k]].append(k) printed_categories = [] - for v in sorted(by_value.iterkeys()): + for v in sorted(by_value.keys()): if v in exclude: continue - print v + print ("%s (%i)" % (v, len(by_value[v]))) printed_categories.append(v) for k in sorted(by_value[v]): - print " " + k + print (" " + k) for cat in check_existence_for_these: if cat not in printed_categories: - print "Good news, category %s is empty!" % cat + print ("Good news, category %s is empty!" % cat) def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org): gc = github_client.GithubClient(github_token, github_url) members = dict( - map(lambda x: (x.lower(), "github"), gc.get_members(org)) + map(lambda x: (x.lower(), "only_in_github"), gc.get_members(org)) ) with ldap_client.LdapClient(ldap_url, ldap_base) as lc: for user, shell, github_user in lc.get_github_users(): - github_user = github_user.lower() - if shell == '/dev/null': - if github_user in members: + github_user = github_user.lower().decode('UTF-8') + if shell.decode('UTF-8') == '/dev/null': + if github_user in members and members[github_user] == 'only_in_github': members[github_user] = 'github_user_that_quit' continue if github_user not in members: @@ -45,5 +45,5 @@ def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org): print_dict_keys_per_value( members, ("matching", "to_add_to_github"), - ("github", "github_user_that_quit") + ("only_in_github", "github_user_that_quit") ) diff --git a/github_user_management/get_keys_for_org.py b/github_user_management/get_keys_for_org.py index c9d6cb4..d69ef41 100644 --- a/github_user_management/get_keys_for_org.py +++ b/github_user_management/get_keys_for_org.py @@ -8,4 +8,4 @@ def main(github_token, github_url, org): github_token, github_url, org): with open("keys/%s-%s" % (member, id), 'w') as f: f.write(key) - print member + print (member) diff --git a/github_user_management/github_details_for_users.py b/github_user_management/github_details_for_users.py index cf3f43c..b33d7b0 100644 --- a/github_user_management/github_details_for_users.py +++ b/github_user_management/github_details_for_users.py @@ -11,6 +11,6 @@ def print_details_for_users(users_filename, token, github_url): user = gc.get_user(u) email = user["email"] if email: - print "Email for %s is %s" % (u, email) + print ("Email for %s is %s" % (u, email)) else: - print "no email for user " + u + print ("no email for user " + u) diff --git a/github_user_management/org_owners_without_ldap_connection.py b/github_user_management/org_owners_without_ldap_connection.py index 361c67b..bc781cd 100644 --- a/github_user_management/org_owners_without_ldap_connection.py +++ b/github_user_management/org_owners_without_ldap_connection.py @@ -17,12 +17,12 @@ def print_email_if_available(github_members, ldap_url, ldap_base, domain): else: missing_ldap_mappings.append(user) - print "there are %d users" % len(users) - print ", ".join(users) + print ("there are %d users" % len(users)) + print (", ".join(users)) if missing_ldap_mappings: - print "\nDrop these users from the team (they lack LDAP mapping)" + print ("\nDrop these users from the team (they lack LDAP mapping)") for user in missing_ldap_mappings: - print user + print (user) else: - print "\nNo users lacking LDAP mapping. Yay!" + print ("\nNo users lacking LDAP mapping. Yay!") diff --git a/requirements.txt b/requirements.txt index db4e194..e09347e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ requests==2.20.0 -python-ldap==2.4.27 -click==6.6 +python-ldap==3.3.0 +click==8.0.3 # from requests[security] cryptography==3.2 ndg-httpsclient==0.4.2 From edb3da90742f7b3ec0ddd816e9e1943630ed8a67 Mon Sep 17 00:00:00 2001 From: Dave Zolotusky Date: Mon, 15 Nov 2021 21:11:28 +0100 Subject: [PATCH 2/2] add options to remove non-matching and non-employee users optionally remove users from github org that aren't employees anymore also optionally remove users with github users names that don't match any users in the ldap org --- github_user_management/__main__.py | 11 ++++++++--- .../check_github_users_in_ldap.py | 14 ++++++++++---- github_user_management/clients/github_client.py | 10 ++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/github_user_management/__main__.py b/github_user_management/__main__.py index 5e86664..f0a6f26 100644 --- a/github_user_management/__main__.py +++ b/github_user_management/__main__.py @@ -36,6 +36,11 @@ "dc=spotify,dc=net")) domain = click.option("--domain", "-d", type=click.STRING, default="spotify.com") +remove_nonemployee = click.option("--remove-nonemployee", "-r", type=click.BOOL, + default=False, is_flag=True) +remove_nonmatching = click.option("--remove-nonmatching", "-r", type=click.BOOL, + default=False, is_flag=True) + def apply_params(click_objects): @@ -60,10 +65,10 @@ def add_ldap_users_to_employees(gh_token, ldap_url, ldap_base, gh_url): @main.command(help="Check GitHub users in LDAP") -@apply_params([gh_token, ldap_url, ldap_base, gh_url, gh_org]) -def check_github_users_in_ldap(gh_token, ldap_url, ldap_base, gh_url, gh_org): +@apply_params([gh_token, ldap_url, ldap_base, gh_url, gh_org, remove_nonemployee, remove_nonmatching]) +def check_github_users_in_ldap(gh_token, ldap_url, ldap_base, gh_url, gh_org, remove_nonemployee, remove_nonmatching): check_github.check_github_usernames( - gh_token, ldap_url, ldap_base, gh_url, gh_org + gh_token, ldap_url, ldap_base, gh_url, gh_org, remove_nonemployee, remove_nonmatching ) diff --git a/github_user_management/check_github_users_in_ldap.py b/github_user_management/check_github_users_in_ldap.py index 03ab758..d233e52 100644 --- a/github_user_management/check_github_users_in_ldap.py +++ b/github_user_management/check_github_users_in_ldap.py @@ -14,16 +14,16 @@ def print_dict_keys_per_value(d, exclude, check_existence_for_these): for v in sorted(by_value.keys()): if v in exclude: continue - print ("%s (%i)" % (v, len(by_value[v]))) + print("%s (%i)" % (v, len(by_value[v]))) printed_categories.append(v) for k in sorted(by_value[v]): - print (" " + k) + print(" " + k) for cat in check_existence_for_these: if cat not in printed_categories: - print ("Good news, category %s is empty!" % cat) + print("Good news, category %s is empty!" % cat) -def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org): +def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org, remove_nonemployee, remove_nonmatching): gc = github_client.GithubClient(github_token, github_url) members = dict( @@ -36,6 +36,8 @@ def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org): if shell.decode('UTF-8') == '/dev/null': if github_user in members and members[github_user] == 'only_in_github': members[github_user] = 'github_user_that_quit' + if remove_nonemployee: + gc.remove_member(org, github_user) continue if github_user not in members: members[github_user] = 'to_add_to_github' @@ -43,6 +45,10 @@ def check_github_usernames(github_token, ldap_url, ldap_base, github_url, org): members[github_user] = 'matching' # print "matching %s@spotify.com" % user + if remove_nonmatching: + for non_matching_member in [m for m in members if members[m] == 'only_in_github']: + gc.remove_member(org, non_matching_member) + print_dict_keys_per_value( members, ("matching", "to_add_to_github"), ("only_in_github", "github_user_that_quit") diff --git a/github_user_management/clients/github_client.py b/github_user_management/clients/github_client.py index 2880547..e0ec39e 100644 --- a/github_user_management/clients/github_client.py +++ b/github_user_management/clients/github_client.py @@ -31,6 +31,10 @@ def get(self, url): return requests.get(url, headers={ 'Authorization': 'token ' + self.auth_token}) + def delete(self, url): + return requests.delete(url, headers={ + 'Authorization': 'token ' + self.auth_token}) + def get_user(self, username): result = self.get("%s/users/%s" % (self.github_base_url, username)) if result.status_code == 404: @@ -53,6 +57,12 @@ def get_members(self, org_name, role='all'): self.github_base_url, org_name, role) return (m['login'] for m in self.traverse_pagination(url)) + def remove_member(self, org_name, member_username): + url = "%s/orgs/%s/memberships/%s" % ( + self.github_base_url, org_name, member_username) + response = self.delete(url) + return response.status_code == 204 + def yield_org_keys(auth_token, github_base_url, org_name): client = GithubClient(auth_token, github_base_url)