1
0
mirror of https://github.com/bitwarden/directory-connector synced 2025-12-05 23:53:21 +00:00

stub out OneLogin connector

This commit is contained in:
Kyle Spearrin
2020-03-12 12:42:04 -04:00
parent d9e7256804
commit d374cff51c
8 changed files with 198 additions and 3 deletions

View File

@@ -147,6 +147,26 @@
[(ngModel)]="okta.token">
</div>
</div>
<div [hidden]="directory != directoryType.OneLogin">
<div class="form-group">
<label for="oneLoginClientId">{{'clientId' | i18n}}</label>
<input type="text" class="form-control" id="oneLoginClientId" name="OneLoginClientId"
[(ngModel)]="oneLogin.clientId">
</div>
<div class="form-group">
<label for="oneLoginClientSecret">{{'clientSecret' | i18n}}</label>
<input type="text" class="form-control" id="oneLoginClientSecret" name="OneLoginClientSecret"
[(ngModel)]="oneLogin.clientSecret">
</div>
<div class="form-group">
<label for="oneLoginRegion">{{'region' | i18n}}</label>
<select class="form-control" id="oneLoginRegion" name="OneLoginRegion"
[(ngModel)]="oneLogin.region">
<option value="us">US</option>
<option value="eu">EU</option>
</select>
</div>
</div>
<div [hidden]="directory != directoryType.GSuite">
<div class="form-group">
<label for="domain">{{'domain' | i18n}}</label>

View File

@@ -19,6 +19,7 @@ import { AzureConfiguration } from '../../models/azureConfiguration';
import { GSuiteConfiguration } from '../../models/gsuiteConfiguration';
import { LdapConfiguration } from '../../models/ldapConfiguration';
import { OktaConfiguration } from '../../models/oktaConfiguration';
import { OneLoginConfiguration } from '../../models/oneLoginConfiguration';
import { SyncConfiguration } from '../../models/syncConfiguration';
import { ConnectorUtils } from '../../utils';
@@ -34,6 +35,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
gsuite = new GSuiteConfiguration();
azure = new AzureConfiguration();
okta = new OktaConfiguration();
oneLogin = new OneLoginConfiguration();
sync = new SyncConfiguration();
organizationId: string;
directoryOptions: any[];
@@ -48,6 +50,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
{ name: 'Azure Active Directory', value: DirectoryType.AzureActiveDirectory },
{ name: 'G Suite (Google)', value: DirectoryType.GSuite },
{ name: 'Okta', value: DirectoryType.Okta },
// { name: 'OneLogin', value: DirectoryType.OneLogin },
];
}
@@ -70,6 +73,8 @@ export class SettingsComponent implements OnInit, OnDestroy {
DirectoryType.AzureActiveDirectory)) || this.azure;
this.okta = (await this.configurationService.getDirectory<OktaConfiguration>(
DirectoryType.Okta)) || this.okta;
this.oneLogin = (await this.configurationService.getDirectory<OneLoginConfiguration>(
DirectoryType.OneLogin)) || this.oneLogin;
this.sync = (await this.configurationService.getSync()) || this.sync;
}
@@ -85,6 +90,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
await this.configurationService.saveDirectory(DirectoryType.GSuite, this.gsuite);
await this.configurationService.saveDirectory(DirectoryType.AzureActiveDirectory, this.azure);
await this.configurationService.saveDirectory(DirectoryType.Okta, this.okta);
await this.configurationService.saveDirectory(DirectoryType.OneLogin, this.oneLogin);
await this.configurationService.saveSync(this.sync);
}

View File

@@ -3,4 +3,5 @@ export enum DirectoryType {
AzureActiveDirectory = 1,
GSuite = 2,
Okta = 3,
OneLogin = 4,
}

View File

@@ -582,8 +582,8 @@
"message": "Hide to Tray"
},
"alwaysOnTop": {
"message": "Always on Top",
"description": "Application window should always stay on top of other windows"
"message": "Always on Top",
"description": "Application window should always stay on top of other windows"
},
"hideToMenuBar": {
"message": "Hide to Menu Bar"
@@ -599,5 +599,14 @@
},
"overwriteExisting": {
"message": "Overwrite existing organization users based on current sync settings."
},
"clientId": {
"message": "Client ID"
},
"clientSecret": {
"message": "Client Secret"
},
"region": {
"message": "Region"
}
}

View File

@@ -0,0 +1,5 @@
export class OneLoginConfiguration {
clientId: string;
clientSecret: string;
region = 'us';
}

View File

@@ -6,6 +6,7 @@ import { GSuiteConfiguration } from '../models/gsuiteConfiguration';
import { LdapConfiguration } from '../models/ldapConfiguration';
import { OktaConfiguration } from '../models/oktaConfiguration';
import { SyncConfiguration } from '../models/syncConfiguration';
import { OneLoginConfiguration } from 'src/models/oneLoginConfiguration';
const StoredSecurely = '[STORED SECURELY]';
const Keys = {
@@ -13,6 +14,7 @@ const Keys = {
gsuite: 'gsuitePrivateKey',
azure: 'azureKey',
okta: 'oktaToken',
oneLogin: 'oneLoginClientSecret',
directoryConfigPrefix: 'directoryConfig_',
sync: 'syncConfig',
directoryType: 'directoryType',
@@ -48,13 +50,17 @@ export class ConfigurationService {
case DirectoryType.GSuite:
(config as any).privateKey = await this.secureStorageService.get<string>(Keys.gsuite);
break;
case DirectoryType.OneLogin:
(config as any).clientSecret = await this.secureStorageService.get<string>(Keys.oneLogin);
break;
}
}
return config;
}
async saveDirectory(type: DirectoryType,
config: LdapConfiguration | GSuiteConfiguration | AzureConfiguration | OktaConfiguration): Promise<any> {
config: LdapConfiguration | GSuiteConfiguration | AzureConfiguration | OktaConfiguration |
OneLoginConfiguration): Promise<any> {
const savedConfig: any = Object.assign({}, config);
if (this.useSecureStorageForSecrets) {
switch (type) {
@@ -92,6 +98,14 @@ export class ConfigurationService {
savedConfig.privateKey = StoredSecurely;
}
break;
case DirectoryType.OneLogin:
if (savedConfig.clientSecret == null) {
await this.secureStorageService.remove(Keys.oneLogin);
} else {
await this.secureStorageService.save(Keys.oneLogin, savedConfig.clientSecret);
savedConfig.clientSecret = StoredSecurely;
}
break;
}
}
await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig);

View File

@@ -0,0 +1,137 @@
import { DirectoryType } from '../enums/directoryType';
import { GroupEntry } from '../models/groupEntry';
import { OneLoginConfiguration } from '../models/oneLoginConfiguration';
import { SyncConfiguration } from '../models/syncConfiguration';
import { UserEntry } from '../models/userEntry';
import { BaseDirectoryService } from './baseDirectory.service';
import { ConfigurationService } from './configuration.service';
import { DirectoryService } from './directory.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { LogService } from 'jslib/abstractions/log.service';
export class OneLoginDirectoryService extends BaseDirectoryService implements DirectoryService {
private dirConfig: OneLoginConfiguration;
private syncConfig: SyncConfiguration;
private accessToken: string;
constructor(private configurationService: ConfigurationService, private logService: LogService,
private i18nService: I18nService) {
super();
}
async getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
const type = await this.configurationService.getDirectoryType();
if (type !== DirectoryType.OneLogin) {
return;
}
this.dirConfig = await this.configurationService.getDirectory<OneLoginConfiguration>(DirectoryType.OneLogin);
if (this.dirConfig == null) {
return;
}
this.syncConfig = await this.configurationService.getSync();
if (this.syncConfig == null) {
return;
}
if (this.dirConfig.clientId == null || this.dirConfig.clientSecret == null) {
throw new Error(this.i18nService.t('dirConfigIncomplete'));
}
this.accessToken = await this.getAccessToken();
if (this.accessToken == null) {
throw new Error('Could not get access token');
}
let users: UserEntry[];
if (this.syncConfig.users) {
users = await this.getUsers(force);
}
let groups: GroupEntry[];
if (this.syncConfig.groups) {
const setFilter = this.createCustomSet(this.syncConfig.groupFilter);
groups = await this.getGroups(this.forceGroup(force, users), setFilter);
users = this.filterUsersFromGroupsSet(users, groups, setFilter);
}
return [groups, users];
}
private async getUsers(force: boolean): Promise<UserEntry[]> {
const entries: UserEntry[] = [];
const lastSync = await this.configurationService.getLastUserSyncDate();
// const oktaFilter = this.buildOktaFilter(this.syncConfig.userFilter, force, lastSync);
const setFilter = this.createCustomSet(this.syncConfig.userFilter);
this.logService.info('Querying users.');
/*
const usersPromise = this.client.listUsers({ filter: oktaFilter }).each((user: any) => {
const entry = this.buildUser(user);
if (entry != null && !this.filterOutResult(setFilter, entry.email)) {
entries.push(entry);
}
});
*/
const users = await this.client.apis.users.get_users(
{},
this.requestInterceptor());
const u2 = this.getApi('users');
return Promise.resolve([]);
}
private async getGroups(force: boolean, setFilter: [boolean, Set<string>]): Promise<GroupEntry[]> {
return Promise.resolve([]);
}
private requestInterceptor(): any {
return {
requestInterceptor: (req: any) => {
req.headers.Authorization = 'bearer:' + this.accessToken;
return req;
},
};
}
private async getAccessToken() {
const response = await fetch(`https://api.${this.dirConfig.region}.onelogin.com/auth/oauth2/v2/token`, {
method: 'POST',
headers: new Headers({
'Authorization': 'Basic ' + btoa(this.dirConfig.clientId + ':' + this.dirConfig.clientSecret),
'Content-Type': 'application/json; charset=utf-8',
'Accept': 'application/json',
}),
body: JSON.stringify({
grant_type: 'client_credentials',
}),
});
if (response.status === 200) {
const responseJson = await response.json();
if (responseJson.access_token != null) {
return responseJson.access_token;
}
}
return null;
}
private async getApi(endpoint: string): Promise<any> {
const req: RequestInit = {
method: 'GET',
headers: new Headers({
'Authorization': 'bearer:' + this.accessToken,
'Accept': 'application/json',
}),
};
const response = await fetch(
new Request(`https://api.${this.dirConfig.region}.onelogin.com/api/1/${endpoint}`, req));
if (response.status === 200) {
const responseJson = await response.json();
return responseJson;
}
return null;
}
}

View File

@@ -22,6 +22,7 @@ import { DirectoryService } from './directory.service';
import { GSuiteDirectoryService } from './gsuite-directory.service';
import { LdapDirectoryService } from './ldap-directory.service';
import { OktaDirectoryService } from './okta-directory.service';
import { OneLoginDirectoryService } from './onelogin-directory.service';
export class SyncService {
private dirType: DirectoryType;
@@ -123,6 +124,8 @@ export class SyncService {
return new LdapDirectoryService(this.configurationService, this.logService, this.i18nService);
case DirectoryType.Okta:
return new OktaDirectoryService(this.configurationService, this.logService, this.i18nService);
case DirectoryType.OneLogin:
return new OneLoginDirectoryService(this.configurationService, this.logService, this.i18nService);
default:
return null;
}