132 lines
4.2 KiB
JavaScript
132 lines
4.2 KiB
JavaScript
|
|
const ldap = require('../util/ldapjs-extra');
|
|
const ssh = require('node-ssh');
|
|
|
|
/**
|
|
* Summary of userAccountControl flags:
|
|
* https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
|
|
*/
|
|
const UserAccountControlFlags = {
|
|
ACCOUNTDISABLE: 2
|
|
};
|
|
|
|
module.exports = Self => {
|
|
Self.getSynchronizer = async function() {
|
|
return await Self.findOne({
|
|
fields: [
|
|
'host',
|
|
'adDomain',
|
|
'adController',
|
|
'adUser',
|
|
'adPassword',
|
|
'verifyCert'
|
|
]
|
|
});
|
|
};
|
|
|
|
Object.assign(Self.prototype, {
|
|
async init() {
|
|
let sshClient = new ssh.NodeSSH();
|
|
await sshClient.connect({
|
|
host: this.adController,
|
|
username: this.adUser,
|
|
password: this.adPassword
|
|
});
|
|
|
|
let adUser = `cn=${this.adUser},${this.usersDn()}`;
|
|
|
|
let adClient = ldap.createClient({
|
|
url: `ldaps://${this.adController}:636`,
|
|
tlsOptions: {rejectUnauthorized: this.verifyCert}
|
|
});
|
|
await adClient.bind(adUser, this.adPassword);
|
|
|
|
Object.assign(this, {
|
|
sshClient,
|
|
adClient
|
|
});
|
|
},
|
|
|
|
async deinit() {
|
|
await this.sshClient.dispose();
|
|
await this.adClient.unbind();
|
|
},
|
|
|
|
usersDn() {
|
|
let dnBase = this.adDomain
|
|
.split('.')
|
|
.map(part => `dc=${part}`)
|
|
.join(',');
|
|
return `cn=Users,${dnBase}`;
|
|
},
|
|
|
|
async syncUser(userName, info, password) {
|
|
let {sshClient} = this;
|
|
|
|
let sambaUser = await this.adClient.searchOne(this.usersDn(), {
|
|
scope: 'sub',
|
|
attributes: ['userAccountControl'],
|
|
filter: `(&(objectClass=user)(sAMAccountName=${userName}))`
|
|
});
|
|
let isEnabled = sambaUser
|
|
&& !(sambaUser.userAccountControl & UserAccountControlFlags.ACCOUNTDISABLE);
|
|
|
|
if (process.env.NODE_ENV === 'test')
|
|
return;
|
|
|
|
if (info.hasAccount) {
|
|
if (!sambaUser) {
|
|
await sshClient.exec('samba-tool user create', [
|
|
userName,
|
|
'--uid-number', `${info.uidNumber}`,
|
|
'--mail-address', info.corporateMail,
|
|
'--random-password'
|
|
]);
|
|
await sshClient.exec('samba-tool user setexpiry', [
|
|
userName,
|
|
'--noexpiry'
|
|
]);
|
|
await sshClient.exec('mkhomedir_helper', [
|
|
userName,
|
|
'0027'
|
|
]);
|
|
}
|
|
if (!isEnabled) {
|
|
await sshClient.exec('samba-tool user enable', [
|
|
userName
|
|
]);
|
|
}
|
|
if (password) {
|
|
await sshClient.exec('samba-tool user setpassword', [
|
|
userName,
|
|
'--newpassword', password
|
|
]);
|
|
}
|
|
} else if (isEnabled) {
|
|
await sshClient.exec('samba-tool user disable', [
|
|
userName
|
|
]);
|
|
console.log(` -> User '${userName}' disabled on Samba`);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Gets Samba enabled users.
|
|
*
|
|
* @param {Set} usersToSync
|
|
*/
|
|
async getUsers(usersToSync) {
|
|
const LDAP_MATCHING_RULE_BIT_AND = '1.2.840.113556.1.4.803';
|
|
let filter = `!(userAccountControl:${LDAP_MATCHING_RULE_BIT_AND}:=${UserAccountControlFlags.ACCOUNTDISABLE})`;
|
|
|
|
let opts = {
|
|
scope: 'sub',
|
|
attributes: ['sAMAccountName'],
|
|
filter: `(&(objectClass=user)(${filter}))`
|
|
};
|
|
await this.adClient.searchForeach(this.usersDn(), opts,
|
|
o => usersToSync.add(o.sAMAccountName));
|
|
}
|
|
});
|
|
};
|