From 25db119d02f2a0073d41b6cb451b416948e16cfa Mon Sep 17 00:00:00 2001
From: Erik Weber
Date: Fri, 3 Jul 2020 08:55:31 +0200
Subject: [PATCH] Add Account creation/permission handling based on Azure oAuth
group membership
---
powerdnsadmin/models/setting.py | 5 ++
powerdnsadmin/routes/admin.py | 11 +++
powerdnsadmin/routes/index.py | 70 +++++++++++++++++++
.../admin_setting_authentication.html | 36 ++++++++++
4 files changed, 122 insertions(+)
diff --git a/powerdnsadmin/models/setting.py b/powerdnsadmin/models/setting.py
index b225787..bd1066e 100644
--- a/powerdnsadmin/models/setting.py
+++ b/powerdnsadmin/models/setting.py
@@ -81,6 +81,11 @@ class Setting(db.Model):
'azure_admin_group': '',
'azure_operator_group': '',
'azure_user_group': '',
+ 'azure_group_accounts_enabled': False,
+ 'azure_group_accounts_name': 'displayName',
+ 'azure_group_accounts_name_re': '',
+ 'azure_group_accounts_description': 'description',
+ 'azure_group_accounts_description_re': '',
'oidc_oauth_enabled': False,
'oidc_oauth_key': '',
'oidc_oauth_secret': '',
diff --git a/powerdnsadmin/routes/admin.py b/powerdnsadmin/routes/admin.py
index 4ee8b58..d5557a1 100644
--- a/powerdnsadmin/routes/admin.py
+++ b/powerdnsadmin/routes/admin.py
@@ -780,6 +780,17 @@ def setting_authentication():
request.form.get('azure_operator_group'))
Setting().set('azure_user_group',
request.form.get('azure_user_group'))
+ Setting().set(
+ 'azure_group_accounts_enabled', True
+ if request.form.get('azure_group_accounts_enabled') == 'ON' else False)
+ Setting().set('azure_group_accounts_name',
+ request.form.get('azure_group_accounts_name'))
+ Setting().set('azure_group_accounts_name_re',
+ request.form.get('azure_group_accounts_name_re'))
+ Setting().set('azure_group_accounts_description',
+ request.form.get('azure_group_accounts_description'))
+ Setting().set('azure_group_accounts_description_re',
+ request.form.get('azure_group_accounts_description_re'))
result = {
'status': True,
'msg':
diff --git a/powerdnsadmin/routes/index.py b/powerdnsadmin/routes/index.py
index 4df19e8..7013c01 100644
--- a/powerdnsadmin/routes/index.py
+++ b/powerdnsadmin/routes/index.py
@@ -279,6 +279,76 @@ def login():
error=('User ' + azure_username +
' is not in any authorised groups.'))
+ # Handle account/group creation, if enabled
+ if Setting().get('azure_group_accounts_enabled') and mygroups:
+ current_app.logger.info('Azure group account sync enabled')
+ for azure_group in mygroups:
+
+ name_value = Setting().get('azure_group_accounts_name')
+ description_value = Setting().get('azure_group_accounts_description')
+
+ select_values = name_value
+ if description_value != '':
+ select_values += ',' + description_value
+ azure_group_info = azure.get('groups/{}?$select={}'.format(azure_group, select_values)).text
+ current_app.logger.info('Group name for {}: {}'.format(azure_group, azure_group_info))
+ group_info = json.loads(azure_group_info)
+ if name_value in group_info:
+ group_name = group_info[name_value]
+ group_description = ''
+ if description_value in group_info:
+ group_description = group_info[description_value]
+
+ # Do regex search if enabled
+ pattern = Setting().get('azure_group_accounts_name_re')
+ if pattern != '':
+ current_app.logger.info('Matching group name {} against regex {}'.format(group_name, pattern))
+ matches = re.match(pattern,group_name)
+ if matches:
+ current_app.logger.info('Group {} matched regexp'.format(group_name))
+ group_name = matches.group(0)
+ else:
+ # Regexp didn't match, continue to next iteration
+ next
+ account = Account()
+ account_id = account.get_id_by_name(account_name=group_name)
+
+ if account_id:
+ account = Account.query.get(account_id)
+ # check if user has permissions
+ account_users = account.get_user()
+ current_app.logger.info('Group: {} Users: {}'.format(
+ group_name,
+ account_users))
+ if user.id in account_users:
+ current_app.logger.info('User id {} is already in account {}'.format(
+ user.id, group_name))
+ else:
+ account.add_user(user)
+ history = History(msg='Update account {0}'.format(
+ account.name),
+ created_by='System')
+ history.add()
+ current_app.logger.info('User {} added to Account {}'.format(
+ user.username, account.name))
+ else:
+ account.name = group_name
+ account.description = group_description
+ account.contact = ''
+ account.mail = ''
+ account.create_account()
+ history = History(msg='Create account {0}'.format(
+ account.name),
+ created_by='System')
+ history.add()
+
+ account.add_user(user)
+ history = History(msg='Update account {0}'.format(account.name),
+ created_by='System')
+ history.add()
+ current_app.logger.warning('group info: {} '.format(account_id))
+
+
login_user(user, remember=False)
signin_history(user.username, 'Azure OAuth', True)
return redirect(url_for('index.index'))
diff --git a/powerdnsadmin/templates/admin_setting_authentication.html b/powerdnsadmin/templates/admin_setting_authentication.html
index 50c00ef..0bfeae9 100644
--- a/powerdnsadmin/templates/admin_setting_authentication.html
+++ b/powerdnsadmin/templates/admin_setting_authentication.html
@@ -456,6 +456,41 @@
+
@@ -476,6 +511,7 @@
For the Scope, use User.Read openid mail profile
Replace the [tenantID] in the default URLs for authorize and token with your Tenant ID.
+
If AZURE GROUP ACCOUNT SYNC/CREATION is enabled, Accounts will be created automatically based on group membership. If an Account exists, an authenticated user with group membership is added to the Account