WIP: #5770 - Sync Groups Samba #1946
|
@ -3793,4 +3793,4 @@ INSERT INTO vn.workCenter (id, name, payrollCenterFk, counter, warehouseFk, stre
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO account.sambaConfig (id,adDomain,adController,adUser,adPassword,verifyCert,userDn,groupDn) VALUES
|
INSERT INTO account.sambaConfig (id,adDomain,adController,adUser,adPassword,verifyCert,userDn,groupDn) VALUES
|
||||||
(1,'verdnatura.es','192.168.56.102','Administrator','V3rdn4tur4$',0,'ou=VnUsers','ou=VnGroups');
|
(1,'verdnatura.es','192.168.56.101','Administrator','V3rdn4tur4$',0,'ou=VnUsers','ou=VnGroups');
|
||||||
|
|
|
@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server');
|
||||||
const ldap = require('../util/ldapjs-extra');
|
const ldap = require('../util/ldapjs-extra');
|
||||||
const {differences, toMap, printResults} = require('../util/helpers');
|
const {differences, toMap, printResults} = require('../util/helpers');
|
||||||
const execFile = require('child_process').execFile;
|
const execFile = require('child_process').execFile;
|
||||||
// const ROLE_PREFIX = 'VN_';
|
const ROLE_PREFIX = '$';
|
||||||
/**
|
/**
|
||||||
* Summary of userAccountControl flags:
|
* Summary of userAccountControl flags:
|
||||||
* https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
|
* https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
|
||||||
|
@ -172,7 +172,25 @@ module.exports = Self => {
|
||||||
await this.adClient.searchForeach(this.fullUsersDn, opts,
|
await this.adClient.searchForeach(this.fullUsersDn, opts,
|
||||||
o => usersToSync.add(o.sAMAccountName));
|
o => usersToSync.add(o.sAMAccountName));
|
||||||
},
|
},
|
||||||
|
deleteRole(role) {
|
||||||
|
return this.sambaTool('group', ['delete', role]);
|
||||||
|
},
|
||||||
|
addRole({description, name}) {
|
||||||
|
return this.sambaTool('group',
|
||||||
|
['add', `${ROLE_PREFIX}${name}`, `--groupou=${this.groupDn}`, `--description=${description}`]);
|
||||||
|
},
|
||||||
|
getRoleMembers(role) {
|
||||||
|
return this.getMembers(`(cn=${role})`, this.fullGroupsDn);
|
||||||
|
},
|
||||||
|
getMembers(filter = '', type = this.fullUsersDn) {
|
||||||
|
const options = {
|
||||||
|
scope: 'sub',
|
||||||
|
attributes: ['cn', 'member', 'member.cn']
|
||||||
|
};
|
||||||
|
if (filter !== '')
|
||||||
|
Object.assign(options, {filter});
|
||||||
|
return this.adClient.searchAll(type, options);
|
||||||
|
},
|
||||||
async syncRoles() {
|
async syncRoles() {
|
||||||
await this.init();
|
await this.init();
|
||||||
let $ = app.models;
|
let $ = app.models;
|
||||||
|
@ -184,49 +202,44 @@ module.exports = Self => {
|
||||||
// Prepare data
|
// Prepare data
|
||||||
try {
|
try {
|
||||||
// const filter = '(cn=VN_*)';
|
// const filter = '(cn=VN_*)';
|
||||||
const scope = 'sub';
|
|
||||||
// const baseDN = 'cn=Users,dc=verdnatura,dc=es';
|
// const baseDN = 'cn=Users,dc=verdnatura,dc=es';
|
||||||
// const ldapMembersGroups = await this.adClient.searchAll(baseDN, {
|
const ldapMembersGroups = await this.getMembers();
|
||||||
// scope,
|
|
||||||
// attributes: ['cn', 'member'],
|
|
||||||
// filter
|
|
||||||
// });
|
|
||||||
// OBTENER ROLES
|
// OBTENER ROLES
|
||||||
let roles = (await $.VnRole.find({
|
let roles = (await $.VnRole.find({
|
||||||
fields: ['id', 'name', 'description'],
|
fields: ['id', 'name', 'description'],
|
||||||
order: 'modified DESC',
|
order: 'modified DESC',
|
||||||
limit: 1
|
limit: 2
|
||||||
}));
|
})).reduce((map, role) => {
|
||||||
|
map.set(`${ROLE_PREFIX}${role.name}`, role);
|
||||||
let rolesName = roles.map(role => role.name);
|
return map;
|
||||||
|
}, new Map());
|
||||||
|
const rolesKeys = Array.from(roles.keys());
|
||||||
// OBTENER LDAPSJS ROLES
|
// OBTENER LDAPSJS ROLES
|
||||||
const ldapGroups = (await this.adClient.searchAll(baseDN, {
|
const ldapGroups = await this.adClient.searchAll(this.fullGroupsDn, {
|
||||||
scope,
|
scope: 'sub',
|
||||||
attributes: ['cn', 'description'],
|
attributes: ['cn', 'description'],
|
||||||
}));/* , (err, res)=>{
|
});
|
||||||
res.on('searchEntry', entry=>{
|
|
||||||
console.log(entry)
|
|
||||||
})
|
|
||||||
res.on('error', entry=>{
|
|
||||||
console.log(entry)
|
|
||||||
})
|
|
||||||
res.on('end', entry=>{
|
|
||||||
console.log(entry)
|
|
||||||
})
|
|
||||||
})*/
|
|
||||||
// OBTENER SAMBA ROLES
|
// OBTENER SAMBA ROLES
|
||||||
let sambaCurrentRoles = ldapGroups.map(({cn}) => cn);
|
let sambaCurrentGroups = ldapGroups
|
||||||
|
.filter(group => Object.prototype.hasOwnProperty.call(group, 'cn'))
|
||||||
|
.reduce((map, group) => {
|
||||||
|
map.set(`${group.cn}`, group);
|
||||||
|
return map;
|
||||||
|
}, new Map());
|
||||||
|
const sambaRolesKeys = Array.from(sambaCurrentGroups.keys());// .map(({cn}) => cn);
|
||||||
// handleExecResponse(await this.sambaTool('group', ['list']))
|
// handleExecResponse(await this.sambaTool('group', ['list']))
|
||||||
// .filter(group => group.startsWith(ROLE_PREFIX));
|
// .filter(group => group.startsWith(ROLE_PREFIX));
|
||||||
|
|
||||||
// Encontrar elementos a eliminar
|
// Encontrar elementos a eliminar
|
||||||
const rolesToDelete = differences(sambaCurrentRoles, rolesName);
|
const rolesToDelete = differences(sambaRolesKeys, rolesKeys);
|
||||||
|
|
||||||
// Encontrar elementos a insertar
|
// Encontrar elementos a insertar
|
||||||
const rolesToInsert = differences(roles, sambaCurrentRoles);
|
const rolesToInsert = differences(rolesKeys, sambaRolesKeys);
|
||||||
|
|
||||||
// Encontrar elementos a actualizar
|
// Encontrar elementos a actualizar
|
||||||
const rolesToUpdate = differences(roles, [...rolesToDelete, ...rolesToInsert]);
|
const rolesToUpdate = differences(rolesKeys, [...rolesToDelete, ...rolesToInsert]);
|
||||||
|
|
||||||
// OBTENER USUARIOS Y SUS ROLES
|
// OBTENER USUARIOS Y SUS ROLES
|
||||||
if (
|
if (
|
||||||
|
@ -249,7 +262,7 @@ module.exports = Self => {
|
||||||
console.info(`User ${user.name} has not valid role`);
|
console.info(`User ${user.name} has not valid role`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return {key: role.name, val: user.name};
|
return {key: `${ROLE_PREFIX}${role.name}`, val: user.name};
|
||||||
});
|
});
|
||||||
usersMap.set('group1', ['employee']);
|
usersMap.set('group1', ['employee']);
|
||||||
if (rolesToDelete.length > 0) {
|
if (rolesToDelete.length > 0) {
|
||||||
|
@ -269,7 +282,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
// PROCEDIMIENTO PARA ELIMINAR ROLES
|
// PROCEDIMIENTO PARA ELIMINAR ROLES
|
||||||
const resultsRoleDelete = await Promise.all(
|
const resultsRoleDelete = await Promise.all(
|
||||||
rolesToDelete.map(role => this.sambaTool('group', ['delete', role]))
|
rolesToDelete.map(this.deleteRole)
|
||||||
);
|
);
|
||||||
printResults(resultsRoleDelete);
|
printResults(resultsRoleDelete);
|
||||||
}
|
}
|
||||||
|
@ -277,16 +290,12 @@ module.exports = Self => {
|
||||||
if (rolesToInsert.length > 0) {
|
if (rolesToInsert.length > 0) {
|
||||||
// PROCEDIMIENTO PARA INSERTAR ROLES
|
// PROCEDIMIENTO PARA INSERTAR ROLES
|
||||||
const resultsRoleInsert = await Promise.all(
|
const resultsRoleInsert = await Promise.all(
|
||||||
rolesToInsert.map(
|
rolesToInsert.map(role => this.addRole(roles.get(role))));
|
||||||
({description, name}) =>
|
|
||||||
this.sambaTool('group',
|
|
||||||
['add', name, `--groupou=${this.groupDN}`, `--description="${description}"`]))
|
|
||||||
);
|
|
||||||
printResults(resultsRoleInsert);
|
printResults(resultsRoleInsert);
|
||||||
|
|
||||||
// PROCEDIMIENTO PARA INSERTAR USUARIOS ASOCIADOS AL ROL
|
// PROCEDIMIENTO PARA INSERTAR USUARIOS ASOCIADOS AL ROL
|
||||||
let usersToGroup = rolesToInsert.flatMap(role => usersMap.get(role.name).map(
|
let usersToGroup = rolesToInsert.flatMap(role => usersMap.get(role).map(
|
||||||
a => this.sambaTool('group', ['addmembers', role.name, a])
|
a => this.sambaTool('group', ['addmembers', role, a])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const resultsUserGroup = await Promise.all(usersToGroup);
|
const resultsUserGroup = await Promise.all(usersToGroup);
|
||||||
|
@ -298,21 +307,45 @@ module.exports = Self => {
|
||||||
// OBTENER LDAPSJS MIEMBROS ROLES
|
// OBTENER LDAPSJS MIEMBROS ROLES
|
||||||
|
|
||||||
for await (const role of rolesToUpdate) {
|
for await (const role of rolesToUpdate) {
|
||||||
const users = await this.sambaTool('group', ['listmembers', role]);
|
let roleHasUpdated = false;
|
||||||
const usersToDelete = differences(users, usersMap.get(role));
|
if (roles.get(role).$description != sambaCurrentGroups.get(role).description) {
|
||||||
promises.push(usersToDelete.map(user =>
|
await this.deleteRole(role);
|
||||||
this.sambaTool('group', ['removemembers', user.name])));
|
await this.addRole(roles.get(role));
|
||||||
const usersToInsert = differences(usersMap.get(role), users);
|
roleHasUpdated = true;
|
||||||
promises.push(usersToInsert.map(user =>
|
}
|
||||||
this.sambaTool('group', ['addmembers', role.name, user.name])));
|
const users = usersMap.get(role);
|
||||||
|
const currentUsers = this.handleRoleMembers(await this.getRoleMembers(role));
|
||||||
await Promise.all(promises);
|
if (!roleHasUpdated && currentUsers.length === 0 && users.length === 0) continue;
|
||||||
|
await this.handleUsersRole(role, currentUsers, users);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
handleRoleMembers(users) {
|
||||||
|
if (users.length === 0) return [];
|
||||||
|
let members = users[0]?.member;
|
||||||
|
if (!members) return [];
|
||||||
|
if (!Array.isArray(members))members = [members];
|
||||||
|
return members.map((member => member.match(/CN=(.*?),(.*)/)[1]));
|
||||||
|
},
|
||||||
|
async handleUsersRole(role, currentUsers, users) {
|
||||||
|
const forbiddenUsers = ['guest'];
|
||||||
|
users = users.filter(u => !u.includes(forbiddenUsers));
|
||||||
|
const usersToDelete = differences(currentUsers, users);
|
||||||
|
if (usersToDelete.length > 0) {
|
||||||
|
const results = await Promise.all(usersToDelete.map(user =>
|
||||||
|
this.sambaTool('group', ['removemembers', role, user])));
|
||||||
|
printResults(results);
|
||||||
|
}
|
||||||
|
const usersToInsert = differences(users, currentUsers);
|
||||||
|
if (usersToInsert.length > 0) {
|
||||||
|
const results = await Promise.all(usersToInsert.map(user =>
|
||||||
|
this.sambaTool('group', ['addmembers', role, user])));
|
||||||
|
printResults(results);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue