mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-10 21:33:20 +00:00
stub out directory service auth/querying
This commit is contained in:
18
package-lock.json
generated
18
package-lock.json
generated
@@ -4572,14 +4572,14 @@
|
||||
}
|
||||
},
|
||||
"googleapis": {
|
||||
"version": "28.1.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-28.1.0.tgz",
|
||||
"integrity": "sha512-+kDXcTq5YUGjrzNOjE6eDaSQ/92bpBrDqj5TGz/AwhnXDqNVGMQey6eRQNMPdrJMYYBSZGYHza1CSIxO/LHEeA==",
|
||||
"version": "29.0.0",
|
||||
"resolved": "https://registry.npmjs.org/googleapis/-/googleapis-29.0.0.tgz",
|
||||
"integrity": "sha512-qac2RSPObw80AOvSPV9hus8VyRxrdaTnsUmttdO6hO12fBE5jI/R9XytUOuB3Z/4LP+1NpprNyKSHm9xXuJx2w==",
|
||||
"requires": {
|
||||
"google-auth-library": "1.4.0",
|
||||
"pify": "3.0.0",
|
||||
"qs": "6.5.1",
|
||||
"string-template": "1.0.0",
|
||||
"url-template": "2.0.8",
|
||||
"uuid": "3.2.1"
|
||||
}
|
||||
},
|
||||
@@ -8961,11 +8961,6 @@
|
||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||
"dev": true
|
||||
},
|
||||
"string-template": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz",
|
||||
"integrity": "sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
@@ -10068,6 +10063,11 @@
|
||||
"prepend-http": "1.0.4"
|
||||
}
|
||||
},
|
||||
"url-template": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
|
||||
"integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE="
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
"electron-log": "2.2.14",
|
||||
"electron-store": "1.3.0",
|
||||
"electron-updater": "2.21.4",
|
||||
"googleapis": "28.1.0",
|
||||
"googleapis": "29.0.0",
|
||||
"keytar": "4.1.0",
|
||||
"ldapjs": "1.0.2",
|
||||
"lunr": "2.1.6",
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<i class="fa fa-rocket"></i>
|
||||
|
||||
The dashboard!!
|
||||
|
||||
<button (click)="gsuite()">G Suite</button>
|
||||
<button (click)="ldap()">LDAP</button>
|
||||
<button (click)="azuread()">Azure AD</button>
|
||||
|
||||
@@ -12,6 +12,10 @@ import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { ModalComponent } from 'jslib/angular/components/modal.component';
|
||||
|
||||
import { AzureDirectoryService } from '../../services/azure-directory.service';
|
||||
import { GSuiteDirectoryService } from '../../services/gsuite-directory.service';
|
||||
import { LdapDirectoryService } from '../../services/ldap-directory.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: 'dashboard.component.html',
|
||||
@@ -21,4 +25,19 @@ export class DashboardComponent {
|
||||
|
||||
constructor(analytics: Angulartics2, toasterService: ToasterService,
|
||||
i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver) { }
|
||||
|
||||
gsuite() {
|
||||
const gsuite = new GSuiteDirectoryService();
|
||||
const entries = gsuite.getEntries();
|
||||
}
|
||||
|
||||
ldap() {
|
||||
const gsuite = new LdapDirectoryService();
|
||||
const entries = gsuite.getEntries();
|
||||
}
|
||||
|
||||
azuread() {
|
||||
const gsuite = new AzureDirectoryService();
|
||||
const entries = gsuite.getEntries();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,74 @@
|
||||
import * as graph from '@microsoft/microsoft-graph-client';
|
||||
import * as https from 'https';
|
||||
import * as querystring from 'querystring';
|
||||
|
||||
import { DirectoryService } from 'src/services/directory.service';
|
||||
|
||||
const Key = '';
|
||||
const ApplicationId = '';
|
||||
const Tenant = '';
|
||||
|
||||
export class AzureDirectoryService implements DirectoryService {
|
||||
getEntries(force = false) {
|
||||
private client: graph.Client;
|
||||
|
||||
async getEntries(force = false) {
|
||||
this.client = graph.Client.init({
|
||||
authProvider: (done) => {
|
||||
const data = querystring.stringify({
|
||||
client_id: ApplicationId,
|
||||
client_secret: Key,
|
||||
grant_type: 'client_credentials',
|
||||
scope: 'https://graph.microsoft.com/.default',
|
||||
});
|
||||
|
||||
const req = https.request({
|
||||
host: 'login.microsoftonline.com',
|
||||
path: '/' + Tenant + '/oauth2/v2.0/token',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Content-Length': Buffer.byteLength(data),
|
||||
},
|
||||
}, (res) => {
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (chunk: string) => {
|
||||
const d = JSON.parse(chunk);
|
||||
if (res.statusCode === 200 && d.access_token != null) {
|
||||
done(null, d.access_token);
|
||||
} else if (d.error != null && d.error_description != null) {
|
||||
done(d.error + ' (' + res.statusCode + '): ' + d.error_description, null);
|
||||
} else {
|
||||
done('Unknown error (' + res.statusCode + ').', null);
|
||||
}
|
||||
});
|
||||
}).on('error', (err) => {
|
||||
done(err, null);
|
||||
});
|
||||
|
||||
req.write(data);
|
||||
req.end();
|
||||
},
|
||||
});
|
||||
|
||||
await this.getUsers();
|
||||
await this.getGroups();
|
||||
}
|
||||
|
||||
private getUsers() {
|
||||
private async getUsers() {
|
||||
const request = this.client.api('/users/delta');
|
||||
const users = await request.get();
|
||||
console.log(users);
|
||||
}
|
||||
|
||||
private async getGroups() {
|
||||
const request = this.client.api('/groups/delta');
|
||||
const groups = await request.get();
|
||||
console.log(groups);
|
||||
|
||||
groups.value.forEach(async (g: any) => {
|
||||
const membersRequest = this.client.api('/groups/' + g.id + '/members');
|
||||
const members = await membersRequest.get();
|
||||
console.log(members);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,69 @@
|
||||
import { JWT } from 'google-auth-library';
|
||||
import { google, GoogleApis } from 'googleapis';
|
||||
import { Admin } from 'googleapis/build/src/apis/admin/directory_v1';
|
||||
|
||||
import { DirectoryService } from 'src/services/directory.service';
|
||||
|
||||
const PrivateKey = '';
|
||||
const ClientEmail = '';
|
||||
const AdminEmail = '';
|
||||
const Domain = '';
|
||||
|
||||
export class GSuiteDirectoryService implements DirectoryService {
|
||||
getEntries(force = false) {
|
||||
private client: JWT;
|
||||
private service: Admin;
|
||||
private authParams: any;
|
||||
|
||||
constructor() {
|
||||
this.service = google.admin<Admin>('directory_v1');
|
||||
}
|
||||
|
||||
async getEntries(force = false) {
|
||||
await this.auth();
|
||||
await this.getUsers();
|
||||
await this.getGroups();
|
||||
}
|
||||
|
||||
private async getUsers() {
|
||||
const service = google.admin<Admin>('directory_v1');
|
||||
const groups = await service.groups.list();
|
||||
const response = await this.service.users.list(this.authParams);
|
||||
console.log(response);
|
||||
}
|
||||
|
||||
private async getGroups() {
|
||||
const response = await this.service.groups.list(this.authParams);
|
||||
console.log(response);
|
||||
|
||||
if (response.data.groups.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
response.data.groups.forEach(async (g) => {
|
||||
const params: any = Object.assign({
|
||||
groupKey: g.id,
|
||||
}, this.authParams);
|
||||
const members = await this.service.members.list(params);
|
||||
console.log(members);
|
||||
});
|
||||
}
|
||||
|
||||
private async auth() {
|
||||
this.client = new google.auth.JWT({
|
||||
email: ClientEmail,
|
||||
key: PrivateKey,
|
||||
subject: AdminEmail,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/admin.directory.user.readonly',
|
||||
'https://www.googleapis.com/auth/admin.directory.group.readonly',
|
||||
'https://www.googleapis.com/auth/admin.directory.group.member.readonly',
|
||||
],
|
||||
});
|
||||
|
||||
await this.client.authorize();
|
||||
this.authParams = {
|
||||
auth: this.client,
|
||||
domain: Domain,
|
||||
};
|
||||
|
||||
// TODO: add customer?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,38 +2,64 @@ import * as ldap from 'ldapjs';
|
||||
|
||||
import { DirectoryService } from 'src/services/directory.service';
|
||||
|
||||
const Url = 'ldap://ldap.forumsys.com:389';
|
||||
const Username = 'cn=read-only-admin,dc=example,dc=com';
|
||||
const Password = 'password';
|
||||
|
||||
export class LdapDirectoryService implements DirectoryService {
|
||||
getEntries(force = false) {
|
||||
private client: ldap.Client;
|
||||
|
||||
async getEntries(force = false) {
|
||||
await this.auth();
|
||||
await this.getUsers();
|
||||
}
|
||||
|
||||
private getUsers() {
|
||||
const client = ldap.createClient({
|
||||
url: 'ldap://127.0.0.1:1389'
|
||||
});
|
||||
|
||||
const options: ldap.SearchOptions = {
|
||||
filter: '(&(l=Seattle)(email=*@foo.com))',
|
||||
filter: null,
|
||||
scope: 'sub',
|
||||
attributes: ['dn', 'sn', 'cn']
|
||||
attributes: ['dn', 'sn', 'cn'],
|
||||
};
|
||||
|
||||
client.search('o=example', options, (error, response) => {
|
||||
if (error != null) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client.search('dc=example,dc=com', options, (err, res) => {
|
||||
if (err != null) {
|
||||
console.error('search error: ' + err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
response.on('searchEntry', (entry) => {
|
||||
console.log('entry: ' + JSON.stringify(entry.object));
|
||||
res.on('searchEntry', (entry) => {
|
||||
console.log(entry);
|
||||
});
|
||||
response.on('searchReference', (referral) => {
|
||||
res.on('searchReference', (referral) => {
|
||||
console.log('referral: ' + referral.uris.join());
|
||||
});
|
||||
response.on('error', (err) => {
|
||||
console.error('error: ' + err.message);
|
||||
res.on('error', (resErr) => {
|
||||
console.error('error: ' + resErr.message);
|
||||
reject(resErr);
|
||||
});
|
||||
response.on('end', (result) => {
|
||||
res.on('end', (result) => {
|
||||
console.log('status: ' + result.status);
|
||||
});
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async auth() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.client = ldap.createClient({
|
||||
url: Url,
|
||||
});
|
||||
|
||||
this.client.bind(Username, Password, (err) => {
|
||||
if (err != null) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ const common = {
|
||||
},
|
||||
plugins: [],
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
extensions: ['.tsx', '.ts', '.js', '.json'],
|
||||
alias: {
|
||||
jslib: path.join(__dirname, 'jslib/src')
|
||||
},
|
||||
@@ -136,6 +136,7 @@ const renderer = {
|
||||
filename: '[name].js.map',
|
||||
include: ['app/main.js']
|
||||
}),
|
||||
new webpack.DefinePlugin({ 'global.GENTLY': false }),
|
||||
extractCss
|
||||
]
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user