feat(ldap): LDAP admin auto population EE-568 (#5875)

* feat(ldap): added ldap custom admin group component

* feat(ldap): added ldap custom admin group to LDAP and MS AD pages

* fix(ui): LDAP group search config label

* fix(ldap): removed testing code.

* fix(ldap): fixed default text in ldap custom admin group component
pull/5884/head
fhanportainer 2021-10-13 11:29:00 +13:00 committed by GitHub
parent 1ee363f8c9
commit 3d6c6e2604
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 189 additions and 3 deletions

View File

@ -153,5 +153,14 @@
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-group-search>
<ldap-custom-admin-group
style="margin-top: 5px;"
settings="$ctrl.settings"
on-search-click="($ctrl.onSearchAdminGroupsClick)"
selected-admin-groups="$ctrl.selectedAdminGroups"
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-custom-admin-group>
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId"></ldap-settings-test-login>
</ng-form>

View File

@ -14,6 +14,7 @@ import { ldapUserSearchItem } from './ldap-user-search-item';
import { ldapSettingsDnBuilder } from './ldap-settings-dn-builder';
import { ldapSettingsGroupDnBuilder } from './ldap-settings-group-dn-builder';
import { ldapCustomGroupSearch } from './ldap-custom-group-search';
import { ldapCustomAdminGroup } from './ldap-custom-admin-group';
import { ldapSettingsSecurity } from './ldap-settings-security';
import { ldapSettingsTestLogin } from './ldap-settings-test-login';
import { ldapCustomUserSearch } from './ldap-custom-user-search';
@ -37,6 +38,7 @@ export default angular
.component('ldapSettingsDnBuilder', ldapSettingsDnBuilder)
.component('ldapSettingsGroupDnBuilder', ldapSettingsGroupDnBuilder)
.component('ldapCustomGroupSearch', ldapCustomGroupSearch)
.component('ldapCustomAdminGroup', ldapCustomAdminGroup)
.component('ldapSettingsOpenLdap', ldapSettingsOpenLdap)
.component('ldapSettingsSecurity', ldapSettingsSecurity)
.component('ldapSettingsTestLogin', ldapSettingsTestLogin)

View File

@ -0,0 +1,13 @@
import controller from './ldap-custom-admin-group.controller';
export const ldapCustomAdminGroup = {
templateUrl: './ldap-custom-admin-group.html',
controller,
bindings: {
settings: '=',
selectedAdminGroups: '=',
defaultAdminGroupSearchFilter: '<',
onSearchClick: '<',
limitedFeatureId: '<',
},
};

View File

@ -0,0 +1,49 @@
export default class LdapCustomAdminGroupController {
/* @ngInject */
constructor($async, Notifications, LDAPService) {
Object.assign(this, { $async, Notifications, LDAPService });
this.groups = null;
this.groupstest = null;
this.enableAssignAdminGroup = false;
this.onRemoveClick = this.onRemoveClick.bind(this);
this.onAddClick = this.onAddClick.bind(this);
this.search = this.search.bind(this);
}
onAddClick() {
this.settings.AdminGroupSearchSettings.push({ GroupBaseDN: '', GroupAttribute: '', GroupFilter: '' });
}
onRemoveClick(index) {
this.settings.AdminGroupSearchSettings.splice(index, 1);
}
search() {
return this.$async(async () => {
try {
this.groups = null;
this.groups = await this.onSearchClick();
this.enableAssignAdminGroup = this.groups && this.groups.length > 0;
} catch (error) {
this.Notifications.error('Failure', error, 'Failed to search groups');
}
});
}
async $onInit() {
if (this.settings.AdminAutoPopulate && this.settings.AdminGroups && this.settings.AdminGroups.length > 0) {
const settings = {
...this.settings,
AdminGroupSearchSettings: this.settings.AdminGroupSearchSettings.map((search) => ({ ...search, GroupFilter: search.GroupFilter || this.defaultAdminGroupSearchFilter })),
};
this.groups = await this.LDAPService.adminGroups(settings);
}
if (this.groups && this.groups.length > 0) {
this.enableAssignAdminGroup = true;
}
}
}

View File

@ -0,0 +1,95 @@
<div class="col-sm-12 form-section-title" style="float: initial;">
Auto-populate team admins
</div>
<rd-widget ng-repeat="config in $ctrl.settings.AdminGroupSearchSettings | limitTo: (1 - $ctrl.settings.AdminGroupSearchSettings)" style="display: block; margin-bottom: 10px;">
<rd-widget-body>
<div class="form-group" ng-if="$index > 0" style="margin-bottom: 10px;">
<span class="col-sm-12 text-muted small">
Extra search configuration
</span>
</div>
<div class="form-group">
<label for="ldap_admin_group_basedn_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
Group Base DN
<portainer-tooltip position="bottom" message="The distinguished name of the element from which the LDAP server will search for groups."></portainer-tooltip>
</label>
<div class="col-sm-8 col-md-4">
<input type="text" class="form-control" id="ldap_admin_group_basedn_{{ $index }}" ng-model="config.GroupBaseDN" placeholder="dc=ldap,dc=domain,dc=tld" />
</div>
<label for="ldap_admin_group_att_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
Group Membership Attribute
<portainer-tooltip position="bottom" message="LDAP attribute which denotes the group membership."></portainer-tooltip>
</label>
<div class="col-sm-8 col-md-4">
<input type="text" class="form-control" id="ldap_admin_group_att_{{ $index }}" ng-model="config.GroupAttribute" placeholder="member" />
</div>
</div>
<div class="form-group">
<label for="ldap_admin_group_filter_{{ $index }}" class="col-sm-4 col-md-2 control-label text-left">
Group Filter
<portainer-tooltip position="bottom" message="The LDAP search filter used to select group elements, optional."></portainer-tooltip>
</label>
<div ng-class="{ 'col-sm-7 col-md-9': $index, 'col-sm-8 col-md-10': !$index }">
<input type="text" class="form-control" id="ldap_admin_group_filter_{{ $index }}" ng-model="config.GroupFilter" placeholder="(objectClass=groupOfNames)" />
</div>
<div class="col-sm-1" ng-if="$index > 0">
<button class="btn btn-sm btn-danger" type="button" ng-click="$ctrl.onRemoveClick($index)">
<i class="fa fa-trash" aria-hidden="true"></i>
</button>
</div>
</div>
</rd-widget-body>
</rd-widget>
<div class="form-group" style="margin-top: 10px;">
<div class="col-sm-12">
<button class="label label-default interactive" style="border: 0;" ng-click="$ctrl.onAddClick()">
<i class="fa fa-plus-circle" aria-hidden="true"></i> add group search configuration
</button>
</div>
<div class="col-sm-12" style="margin-top: 10px;">
<button class="btn btm-sm btn-primary" type="button" ng-click="$ctrl.search()" limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-tabindex="-1">
Fetch Admin Group(s)
</button>
<be-feature-indicator feature="$ctrl.limitedFeatureId" class="space-left"></be-feature-indicator>
<span ng-if="$ctrl.groups && $ctrl.groups.length === 0" style="margin-left: 30px;">
<i class="fa fa-exclamation-triangle text-warning" aria-hidden="true"></i> No groups found</span
>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="admin-auto-populate" class="control-label text-left text-muted" ng-class="{ 'text-muted': !$ctrl.enableAssignAdminGroup }">
Assign admin rights to group(s)
</label>
<label class="switch" style="margin-left: 20px;">
<input id="admin-auto-populate" ng-disabled="!$ctrl.enableAssignAdminGroup" name="admin-auto-populate" type="checkbox" ng-model="$ctrl.settings.AdminAutoPopulate" /><i></i>
</label>
</div>
</div>
<div class="form-group" ng-if="$ctrl.settings.AdminAutoPopulate">
<div class="col-sm-12">
<label for="group-access" class="control-label text-left">
Select Group(s)
</label>
<span
isteven-multi-select
ng-if="$ctrl.enableAssignAdminGroup"
input-model="$ctrl.groups"
output-model="$ctrl.selectedAdminGroups"
button-label="name"
item-label="name"
tick-property="selected"
helper-elements="filter"
search-property="name"
translation="{nothingSelected: 'Select one or more groups', search: 'Search...'}"
style="margin-left: 20px;"
>
</span>
</div>
</div>

View File

@ -1,5 +1,5 @@
<div class="col-sm-12 form-section-title" style="float: initial;">
Teams auto-population configurations
Group search configurations
</div>
<rd-widget ng-repeat="config in $ctrl.settings | limitTo: (1 - $ctrl.settings)" style="display: block; margin-bottom: 10px;">

View File

@ -1,5 +1,5 @@
<div class="col-sm-12 form-section-title" style="float: initial;">
Teams auto-population configurations
Group search configurations
</div>
<div style="margin-top: 10px;" ng-repeat="config in $ctrl.settings | limitTo: (1 - $ctrl.settings)">

View File

@ -114,6 +114,17 @@
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-custom-group-search>
<div limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-class="limited-be" style="margin-bottom: 20px;">
<ldap-custom-admin-group
style="margin-top: 5px;"
settings="$ctrl.settings"
on-search-click="($ctrl.onSearchAdminGroupsClick)"
selected-admin-groups="$ctrl.selectedAdminGroups"
default-admin-group-search-filter="'(objectClass=groupOfNames)'"
limited-feature-id="$ctrl.limitedFeatureId"
></ldap-custom-admin-group>
</div>
<div limited-feature-dir="{{ $ctrl.limitedFeatureId }}" limited-feature-class="limited-be">
<ldap-settings-test-login settings="$ctrl.settings" limited-feature-id="$ctrl.limitedFeatureId" show-be-indicator-if-needed="true"></ldap-settings-test-login>
</div>

View File

@ -23,6 +23,13 @@ export function buildLdapSettingsModel() {
GroupAttribute: '',
},
],
AdminGroupSearchSettings: [
{
GroupBaseDN: '',
GroupFilter: '',
GroupAttribute: '',
},
],
AutoCreateUsers: true,
};
}

View File

@ -221,7 +221,7 @@ function SettingsAuthenticationController($q, $scope, $state, Notifications, Set
if (settings.LDAPSettings.ServerType === 2) {
$scope.formValues.ldap.adSettings = settings.LDAPSettings;
} else {
$scope.formValues.ldap.ldapSettings = settings.LDAPSettings;
$scope.formValues.ldap.ldapSettings = Object.assign($scope.formValues.ldap.ldapSettings, settings.LDAPSettings);
}
if (settings.LDAPSettings.URL) {