2020-06-17 17:43:47 +03:00
|
|
|
from pprint import pprint
|
|
|
|
from flask import Flask
|
|
|
|
from githubapp import GitHubApp, LDAPClient
|
2020-06-18 23:48:01 +03:00
|
|
|
import os
|
2020-06-17 17:43:47 +03:00
|
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
|
github_app = GitHubApp(app)
|
2020-06-18 23:48:01 +03:00
|
|
|
ldap = LDAPClient()
|
2020-06-17 17:43:47 +03:00
|
|
|
|
|
|
|
@github_app.on('team.created')
|
|
|
|
def sync_team():
|
2020-06-19 00:58:56 +03:00
|
|
|
pprint(github_app.payload)
|
2020-06-17 17:43:47 +03:00
|
|
|
payload = github_app.payload
|
2020-06-19 17:34:51 +03:00
|
|
|
owner = github_app.payload['organization']['login']
|
|
|
|
org = github_app.installation_client.organization(owner)
|
|
|
|
team = org.team(payload['team']['id'])
|
2020-06-17 17:43:47 +03:00
|
|
|
slug = payload['team']['slug']
|
|
|
|
parent = payload['team']['parent']
|
|
|
|
ldap_members = ldap_lookup(group=slug)
|
2020-06-17 23:31:54 +03:00
|
|
|
team_members = github_lookup(
|
|
|
|
team_id=payload['team']['id'],
|
|
|
|
attribute='username'
|
|
|
|
)
|
2020-06-19 00:58:56 +03:00
|
|
|
|
2020-06-17 23:31:54 +03:00
|
|
|
compare = compare_members(
|
|
|
|
ldap_group=ldap_members,
|
|
|
|
github_team=team_members,
|
|
|
|
attribute='username'
|
|
|
|
)
|
|
|
|
pprint(compare)
|
2020-06-19 20:43:52 +03:00
|
|
|
execute_sync(
|
2020-06-19 17:34:51 +03:00
|
|
|
org=org,
|
|
|
|
team=team,
|
|
|
|
state=compare
|
|
|
|
)
|
2020-06-19 00:58:56 +03:00
|
|
|
|
2020-06-17 17:43:47 +03:00
|
|
|
|
|
|
|
def ldap_lookup(group=None):
|
|
|
|
"""
|
|
|
|
Look up members of a group in LDAP
|
2020-06-17 18:20:02 +03:00
|
|
|
:param group: The name of the group to query in LDAP
|
|
|
|
:type group: str
|
|
|
|
:return: ldap_members
|
|
|
|
:rtype: list
|
2020-06-17 17:43:47 +03:00
|
|
|
"""
|
|
|
|
group_members = ldap.get_group_members(group)
|
2020-06-17 23:31:54 +03:00
|
|
|
ldap_members = [member for member in group_members]
|
2020-06-17 17:43:47 +03:00
|
|
|
return ldap_members
|
|
|
|
|
2020-06-19 00:58:56 +03:00
|
|
|
def github_team(team_id):
|
|
|
|
owner = github_app.payload['organization']['login']
|
|
|
|
org = github_app.installation_client.organization(owner)
|
|
|
|
return org.team(team_id)
|
2020-06-17 17:43:47 +03:00
|
|
|
|
2020-06-17 23:31:54 +03:00
|
|
|
def github_lookup(team_id=None, attribute='username'):
|
2020-06-17 17:43:47 +03:00
|
|
|
"""
|
|
|
|
Look up members of a give team in GitHub
|
|
|
|
:param team_id:
|
2020-06-17 23:31:54 +03:00
|
|
|
:param attribute:
|
2020-06-17 18:20:02 +03:00
|
|
|
:type team_id: int
|
2020-06-17 23:31:54 +03:00
|
|
|
:type attribute: str
|
2020-06-17 18:20:02 +03:00
|
|
|
:return: team_members
|
|
|
|
:rtype: list
|
2020-06-17 17:43:47 +03:00
|
|
|
"""
|
2020-06-17 23:31:54 +03:00
|
|
|
team_members = []
|
2020-06-19 00:58:56 +03:00
|
|
|
team = github_team(team_id)
|
2020-06-17 23:31:54 +03:00
|
|
|
if attribute == 'email':
|
|
|
|
for m in team.members():
|
|
|
|
user = github_app.installation_client.user(m.login)
|
|
|
|
team_members.append({'username': str(user.login).casefold(),
|
|
|
|
'email': str(user.email).casefold()})
|
|
|
|
else:
|
|
|
|
for member in team.members():
|
|
|
|
team_members.append({'username': str(member).casefold(),
|
|
|
|
'email': ''})
|
2020-06-17 17:43:47 +03:00
|
|
|
return team_members
|
|
|
|
|
|
|
|
|
2020-06-17 23:31:54 +03:00
|
|
|
def compare_members(ldap_group, github_team, attribute='username'):
|
2020-06-17 18:20:02 +03:00
|
|
|
"""
|
|
|
|
Compare users in GitHub and LDAP to see which users need to be added or removed
|
|
|
|
:param ldap_group:
|
|
|
|
:param github_team:
|
2020-06-17 23:31:54 +03:00
|
|
|
:param attribute:
|
2020-06-17 18:20:02 +03:00
|
|
|
:return: sync_state
|
|
|
|
:rtype: dict
|
|
|
|
"""
|
2020-06-17 23:31:54 +03:00
|
|
|
ldap_list = [x[attribute] for x in ldap_group]
|
|
|
|
github_list = [x[attribute] for x in github_team]
|
|
|
|
add_users = list(set(ldap_list) - set(github_list))
|
|
|
|
remove_users = list(set(github_list) - set(ldap_list))
|
2020-06-17 18:20:02 +03:00
|
|
|
sync_state = {
|
|
|
|
'ldap': ldap_group,
|
|
|
|
'github': github_team,
|
|
|
|
'action': {
|
|
|
|
'add': add_users,
|
|
|
|
'remove': remove_users
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return sync_state
|
2020-06-17 17:43:47 +03:00
|
|
|
|
|
|
|
|
2020-06-19 20:43:52 +03:00
|
|
|
def execute_sync(org, team ,state):
|
2020-06-19 17:34:51 +03:00
|
|
|
for user in state['action']['add']:
|
|
|
|
# Validate that user is in org
|
|
|
|
if org.is_member(user):
|
|
|
|
team.add_or_update_membership(user)
|
|
|
|
else:
|
|
|
|
pprint(f'Skipping {user} as they are not part of the org')
|
|
|
|
|
|
|
|
for user in state['action']['remove']:
|
|
|
|
pprint(f'Removing {user}')
|
|
|
|
team.revoke_membership(user)
|