Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ For the grafana integration the following 3 must exist and have valid values, th
- GONB_GRAFANA_MAIN_ORG - allow management of Grafana `Main Org.`, default `False`
- GONB_GRAFANA_TEAM_FOLDER - create team folder, default `True`
- GONB_SSO_PROVIDER - specify if the provider is based on a IAM used for Grafana authentication, default `True`.
- GONB_GRAFANA_DELETE_EXTERNAL_AUTH_USERS - if set to `True` gonb will delete users that are not in the
source system, but have been created just by Grafana through the auth process. Default is `False`.
This options should typical only be used if all users are provisioned by gonb.

> If `GONB_SSO_PROVIDER` is True there is some updating operations that are not done by gonb, e.g. update a
> user's name or email.
Expand Down
6 changes: 5 additions & 1 deletion gonb/grafana.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
GONB_SSO_PROVIDER = 'GONB_SSO_PROVIDER'
GONB_GRAFANA_MAIN_ORG = 'GONB_GRAFANA_MAIN_ORG'
GONB_GRAFANA_TEAM_FOLDER = 'GONB_GRAFANA_TEAM_FOLDER'
GONB_GRAFANA_DELETE_EXTERNAL_AUTH_USERS = 'GONB_GRAFANA_DELETE_EXTERNAL_AUTH_USERS'

MAIN_ORG = 'Main Org.'
ADMIN = 'Admin'
Expand Down Expand Up @@ -575,12 +576,15 @@ def provision(self, iam_organisations: Dict[str, Organization]) \
# for organisation_name in set(source_users_idx.keys()).union(set(self.customer_users_idx.keys())):
# Only manage users that is part of we got from the source
users_managed = {}
# This enables that external auth users can be deleted - only use this if all users are provisioned from IAM
# and not automaticaly added in grafana
delete_external_auth_users = strtobool(os.getenv(GONB_GRAFANA_DELETE_EXTERNAL_AUTH_USERS, 'FALSE'))
for organisation_name in set(iam_organisations.keys()):
users_managed[organisation_name] = {}
users_managed[organisation_name][UPDATED] = \
self._update_users(organisation_name, diff_users.update(organisation_name), iam_organisations)
users_managed[organisation_name][REMOVED] = \
self._remove_users(organisation_name, diff_users.delete(organisation_name))
self._remove_users(organisation_name, diff_users.delete(organisation_name, delete_external_auth_users))
users_managed[organisation_name][ADDED] = \
self._add_users(organisation_name, diff_users.add(organisation_name), iam_organisations)

Expand Down
7 changes: 4 additions & 3 deletions gonb/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,17 @@ def add(self, organisation_name: str) -> Set[str]:
add_users.remove(self.exclude_user)
return add_users

def delete(self, organisation_name: str) -> Set[str]:
def delete(self, organisation_name: str, delete_external_sso_users: bool = False) -> Set[str]:
self._init(organisation_name=organisation_name)
del_users = self.grafana_users_idx[organisation_name] - self.iam_users_idx[organisation_name]
if self.exclude_user in del_users:
del_users.remove(self.exclude_user)
# Exclude users from grafana that have external auth
for user_name in del_users:
if self._grafana_orgs[organisation_name].users[user_name].external_auth:
for user_name in del_users.copy():
if self._grafana_orgs[organisation_name].users[user_name].external_auth and not delete_external_sso_users:
log.info("exclude delete of user due to external SSO", extra={'organization': organisation_name, 'user': user_name})
self._grafana_orgs[organisation_name].users.pop(user_name)
del_users.remove(user_name)
return del_users

def update(self, organisation_name: str) -> Set[str]:
Expand Down
49 changes: 49 additions & 0 deletions tests/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,55 @@ def test_diff(self):
self.assertEqual(len(diff.add('foo_org')), 0)
self.assertEqual(len(diff.delete('foo_org')), 1)

def test_diff_external_auth(self):
orgs_grafana: Dict[str, Organization] = {}
org = Organization(organisation_name='foo_org', org_id=100)
orgs_grafana[org.organisation_name] = org

orgs_iam: Dict[str, Organization] = {}
org = Organization(organisation_name='foo_org', org_id=None)
orgs_iam[org.organisation_name] = org

user = User(login_name="andy@foo.com")
user.name = "Andy Borg"
user.email = user.login
user.role = 'Viewer'
orgs_iam['foo_org'].users[user.login] = user

user = User(login_name="andy@foo.com")
user.name = "Andy Borg"
user.email = user.login
user.role = 'Viewer'
user.user_id = 200
orgs_grafana['foo_org'].users[user.login] = user

user = User(login_name="bull@foo.com")
user.name = "Bull Borg"
user.email = user.login
user.role = 'Viewer'
user.user_id = 201
user.external_auth = True
orgs_grafana['foo_org'].users[user.login] = user

# "Same" user in both orgs
diff = DiffUsers(iam_orgs=orgs_iam, grafana_orgs=orgs_grafana, exclude_user="foobar_admin")
self.assertEqual(len(diff.update('foo_org')), 0)
self.assertEqual(len(diff.add('foo_org')), 0)
# External auth user is not deleted
self.assertEqual(len(diff.delete('foo_org')), 0)

# Need to add it again since it was pop'ed in the previous delete
user = User(login_name="bull@foo.com")
user.name = "Bull Borg"
user.email = user.login
user.role = 'Viewer'
user.user_id = 201
user.external_auth = True
orgs_grafana['foo_org'].users[user.login] = user
diff = DiffUsers(iam_orgs=orgs_iam, grafana_orgs=orgs_grafana, exclude_user="foobar_admin")
# External auth user is deleted
self.assertEqual(len(diff.delete('foo_org', True)), 1)


if __name__ == '__main__':
unittest.main()
Loading