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

Compare commits

..

15 Commits

Author SHA1 Message Date
Kyle Spearrin
e6a5a3c8c1 update jslib 2019-08-30 14:21:52 -04:00
Kyle Spearrin
3f3590a223 update jslib 2019-08-20 13:47:52 -04:00
Kyle Spearrin
c1f64d7b82 disable-library-validation entitlement 2019-07-31 23:44:11 -04:00
Kyle Spearrin
f90611c96f update keytar 2019-07-31 23:43:34 -04:00
Kyle Spearrin
630e21f7c1 update jslib 2019-07-25 20:43:09 -04:00
Kyle Spearrin
2e81642c0e bump version 2019-07-25 14:21:04 -04:00
Kyle Spearrin
39514b9550 update jslib 2019-07-25 14:18:23 -04:00
Kyle Spearrin
2da82d5610 notarize directory connector 2019-07-25 14:17:50 -04:00
Kyle Spearrin
69f33a08b6 upgrade electron builder 2019-07-24 15:30:43 -04:00
Kyle Spearrin
a05e9c7746 upgrade to electron 5 2019-07-24 14:37:43 -04:00
Kyle Spearrin
d8031e4f49 update jslib 2019-07-10 08:39:21 -04:00
Kyle Spearrin
e6aa07ba5c plaintext secrets env variable 2019-07-05 11:57:25 -04:00
Kyle Spearrin
173129014a re-set state service on log in 2019-07-02 08:37:52 -04:00
Kyle Spearrin
8d4baa6d31 simlink for windows 2019-06-24 21:13:07 -04:00
Kyle Spearrin
20463ce653 update jslib, add node https proxy 2019-06-24 11:09:41 -04:00
11 changed files with 1417 additions and 1088 deletions

1
.gitignore vendored
View File

@@ -14,3 +14,4 @@ yarn-error.log
.DS_Store .DS_Store
*.nupkg *.nupkg
*.provisionprofile *.provisionprofile
*.env

2
jslib

Submodule jslib updated: 8375f7381a...b74ee7b3ee

2303
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@
"sub:pull": "git submodule foreach git pull origin master", "sub:pull": "git submodule foreach git pull origin master",
"sub:commit": "npm run sub:pull && git commit -am \"update submodule\"", "sub:commit": "npm run sub:pull && git commit -am \"update submodule\"",
"postinstall": "npm run sub:init", "postinstall": "npm run sub:init",
"simlink:win": "rm -rf ./jslib && cmd /c mklink /J .\\jslib ..\\jslib",
"rebuild": "./node_modules/.bin/electron-rebuild", "rebuild": "./node_modules/.bin/electron-rebuild",
"reset": "rimraf ./node_modules/keytar/* && npm install", "reset": "rimraf ./node_modules/keytar/* && npm install",
"lint": "tslint src/**/*.ts || true", "lint": "tslint src/**/*.ts || true",
@@ -38,10 +39,10 @@
"electron": "npm run build:main && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 ./build --watch\" \"npm run build:renderer:watch\"", "electron": "npm run build:main && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 ./build --watch\" \"npm run build:renderer:watch\"",
"clean:dist": "rimraf ./dist/*", "clean:dist": "rimraf ./dist/*",
"clean:dist:cli": "rimraf ./dist-cli/*", "clean:dist:cli": "rimraf ./dist-cli/*",
"pack:lin": "npm run clean:dist && build --linux --x64 -p never", "pack:lin": "npm run clean:dist && electron-builder --linux --x64 -p never",
"pack:mac": "npm run clean:dist && build --mac -p never", "pack:mac": "npm run clean:dist && electron-builder --mac -p never",
"pack:win": "npm run clean:dist && build --win --x64 --ia32 -p never -c.win.certificateSubjectName=\"8bit Solutions LLC\"", "pack:win": "npm run clean:dist && electron-builder --win --x64 --ia32 -p never -c.win.certificateSubjectName=\"8bit Solutions LLC\"",
"pack:win:ci": "npm run clean:dist && build --win --x64 --ia32 -p never", "pack:win:ci": "npm run clean:dist && electron-builder --win --x64 --ia32 -p never",
"pack:cli": "npm run pack:cli:win | npm run pack:cli:mac | npm run pack:cli:lin", "pack:cli": "npm run pack:cli:win | npm run pack:cli:mac | npm run pack:cli:lin",
"pack:cli:win": "pkg . --targets win-x64 --output ./dist-cli/windows/bwdc.exe", "pack:cli:win": "pkg . --targets win-x64 --output ./dist-cli/windows/bwdc.exe",
"pack:cli:mac": "pkg . --targets macos-x64 --output ./dist-cli/macos/bwdc", "pack:cli:mac": "pkg . --targets macos-x64 --output ./dist-cli/macos/bwdc",
@@ -54,9 +55,9 @@
"dist:cli:win": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:win", "dist:cli:win": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:win",
"dist:cli:mac": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:mac", "dist:cli:mac": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:mac",
"dist:cli:lin": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:lin", "dist:cli:lin": "npm run build:cli:prod && npm run clean:dist:cli && npm run pack:cli:lin",
"publish:lin": "npm run build:dist && npm run clean:dist && build --linux --x64 -p always", "publish:lin": "npm run build:dist && npm run clean:dist && electron-builder --linux --x64 -p always",
"publish:mac": "npm run build:dist && npm run clean:dist && build --mac -p always", "publish:mac": "npm run build:dist && npm run clean:dist && electron-builder --mac -p always",
"publish:win": "npm run build:dist && npm run clean:dist && build --win --x64 --ia32 -p always -c.win.certificateSubjectName=\"8bit Solutions LLC\"" "publish:win": "npm run build:dist && npm run clean:dist && electron-builder --win --x64 --ia32 -p always -c.win.certificateSubjectName=\"8bit Solutions LLC\""
}, },
"build": { "build": {
"appId": "com.bitwarden.directory-connector", "appId": "com.bitwarden.directory-connector",
@@ -66,8 +67,13 @@
"output": "dist", "output": "dist",
"app": "build" "app": "build"
}, },
"afterSign": "scripts/notarize.js",
"mac": { "mac": {
"category": "public.app-category.productivity", "category": "public.app-category.productivity",
"gatekeeperAssess": false,
"hardenedRuntime": true,
"entitlements": "resources/entitlements.mac.plist",
"entitlementsInherit": "resources/entitlements.mac.plist",
"target": [ "target": [
"dmg", "dmg",
"zip" "zip"
@@ -153,10 +159,11 @@
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"css-loader": "^1.0.0", "css-loader": "^1.0.0",
"del": "^3.0.0", "del": "^3.0.0",
"electron": "3.0.14", "electron": "5.0.8",
"electron-builder": "20.38.5", "electron-builder": "21.1.5",
"electron-rebuild": "^1.8.2", "electron-notarize": "^0.1.1",
"electron-reload": "^1.4.0", "electron-rebuild": "^1.8.5",
"electron-reload": "^1.4.1",
"extract-text-webpack-plugin": "next", "extract-text-webpack-plugin": "next",
"file-loader": "^2.0.0", "file-loader": "^2.0.0",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
@@ -164,7 +171,7 @@
"gulp-google-webfonts": "^2.0.0", "gulp-google-webfonts": "^2.0.0",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"node-abi": "^2.5.1", "node-abi": "^2.9.0",
"node-loader": "^0.6.0", "node-loader": "^0.6.0",
"node-sass": "^4.11.0", "node-sass": "^4.11.0",
"pkg": "4.3.4", "pkg": "4.3.4",
@@ -202,11 +209,12 @@
"duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git",
"electron-log": "2.2.17", "electron-log": "2.2.17",
"electron-store": "1.3.0", "electron-store": "1.3.0",
"electron-updater": "4.0.6", "electron-updater": "4.1.2",
"form-data": "2.3.2", "form-data": "2.3.2",
"googleapis": "33.0.0", "googleapis": "33.0.0",
"https-proxy-agent": "2.2.1",
"inquirer": "6.2.0", "inquirer": "6.2.0",
"keytar": "4.4.1", "keytar": "4.13.0",
"ldapjs": "git+https://git@github.com/kspearrin/node-ldapjs.git", "ldapjs": "git+https://git@github.com/kspearrin/node-ldapjs.git",
"lowdb": "1.0.0", "lowdb": "1.0.0",
"lunr": "2.3.3", "lunr": "2.3.3",

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

17
scripts/notarize.js Normal file
View File

@@ -0,0 +1,17 @@
require('dotenv').config();
const { notarize } = require('electron-notarize');
exports.default = async function notarizing(context) {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
const appleId = process.env.APPLEID;
const appName = context.packager.appInfo.productFilename;
return await notarize({
appBundleId: 'com.bitwarden.directory-connector',
appPath: `${appOutDir}/${appName}.app`,
appleId: appleId,
appleIdPassword: `@keychain:AC_PASSWORD`,
});
};

View File

@@ -11,6 +11,7 @@ import { EnvironmentComponent } from './environment.component';
import { AuthService } from 'jslib/abstractions/auth.service'; import { AuthService } from 'jslib/abstractions/auth.service';
import { I18nService } from 'jslib/abstractions/i18n.service'; import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service'; import { StorageService } from 'jslib/abstractions/storage.service';
import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component'; import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component';
@@ -25,8 +26,9 @@ export class LoginComponent extends BaseLoginComponent {
constructor(authService: AuthService, router: Router, constructor(authService: AuthService, router: Router,
i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver, i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
storageService: StorageService, platformUtilsService: PlatformUtilsService) { storageService: StorageService, platformUtilsService: PlatformUtilsService,
super(authService, router, platformUtilsService, i18nService, storageService); stateService: StateService) {
super(authService, router, platformUtilsService, i18nService, storageService, stateService);
super.successRoute = '/tabs/dashboard'; super.successRoute = '/tabs/dashboard';
} }

View File

@@ -16,6 +16,8 @@ import { AuthService } from 'jslib/abstractions/auth.service';
import { EnvironmentService } from 'jslib/abstractions/environment.service'; import { EnvironmentService } from 'jslib/abstractions/environment.service';
import { I18nService } from 'jslib/abstractions/i18n.service'; import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { StateService } from 'jslib/abstractions/state.service';
import { StorageService } from 'jslib/abstractions/storage.service';
import { ModalComponent } from 'jslib/angular/components/modal.component'; import { ModalComponent } from 'jslib/angular/components/modal.component';
import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component'; import { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component';
@@ -30,8 +32,10 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
constructor(authService: AuthService, router: Router, constructor(authService: AuthService, router: Router,
i18nService: I18nService, apiService: ApiService, i18nService: I18nService, apiService: ApiService,
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService, platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
private componentFactoryResolver: ComponentFactoryResolver) { private componentFactoryResolver: ComponentFactoryResolver, stateService: StateService,
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService); storageService: StorageService) {
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
stateService, storageService);
super.successRoute = '/tabs/dashboard'; super.successRoute = '/tabs/dashboard';
} }

View File

@@ -25,6 +25,8 @@ import { NoopMessagingService } from 'jslib/services/noopMessaging.service';
import { TokenService } from 'jslib/services/token.service'; import { TokenService } from 'jslib/services/token.service';
import { UserService } from 'jslib/services/user.service'; import { UserService } from 'jslib/services/user.service';
import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service';
import { Program } from './program'; import { Program } from './program';
// tslint:disable-next-line // tslint:disable-next-line
@@ -35,7 +37,7 @@ export class Main {
logService: ConsoleLogService; logService: ConsoleLogService;
messagingService: NoopMessagingService; messagingService: NoopMessagingService;
storageService: LowdbStorageService; storageService: LowdbStorageService;
secureStorageService: KeytarSecureStorageService; secureStorageService: StorageServiceAbstraction;
i18nService: I18nService; i18nService: I18nService;
platformUtilsService: CliPlatformUtilsService; platformUtilsService: CliPlatformUtilsService;
constantsService: ConstantsService; constantsService: ConstantsService;
@@ -70,13 +72,15 @@ export class Main {
this.dataFilePath = path.join(process.env.HOME, '.config/' + applicationName); this.dataFilePath = path.join(process.env.HOME, '.config/' + applicationName);
} }
const plaintextSecrets = process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS === 'true';
this.i18nService = new I18nService('en', './locales'); this.i18nService = new I18nService('en', './locales');
this.platformUtilsService = new CliPlatformUtilsService('connector', packageJson); this.platformUtilsService = new CliPlatformUtilsService('connector', packageJson);
this.logService = new ConsoleLogService(this.platformUtilsService.isDev(), this.logService = new ConsoleLogService(this.platformUtilsService.isDev(),
(level) => process.env.BWCLI_DEBUG !== 'true' && level <= LogLevelType.Info); (level) => process.env.BITWARDENCLI_CONNECTOR_DEBUG !== 'true' && level <= LogLevelType.Info);
this.cryptoFunctionService = new NodeCryptoFunctionService(); this.cryptoFunctionService = new NodeCryptoFunctionService();
this.storageService = new LowdbStorageService(null, this.dataFilePath, true); this.storageService = new LowdbStorageService(null, this.dataFilePath, true);
this.secureStorageService = new KeytarSecureStorageService(applicationName); this.secureStorageService = plaintextSecrets ?
this.storageService : new KeytarSecureStorageService(applicationName);
this.cryptoService = new CryptoService(this.storageService, this.secureStorageService, this.cryptoService = new CryptoService(this.storageService, this.secureStorageService,
this.cryptoFunctionService); this.cryptoFunctionService);
this.appIdService = new AppIdService(this.storageService); this.appIdService = new AppIdService(this.storageService);
@@ -89,7 +93,8 @@ export class Main {
this.containerService = new ContainerService(this.cryptoService); this.containerService = new ContainerService(this.cryptoService);
this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService, this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService,
this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, true); this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, true);
this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService); this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true');
this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService, this.syncService = new SyncService(this.configurationService, this.logService, this.cryptoFunctionService,
this.apiService, this.messagingService, this.i18nService); this.apiService, this.messagingService, this.i18nService);
this.program = new Program(this); this.program = new Program(this);

View File

@@ -2,7 +2,7 @@
"name": "bitwarden-directory-connector", "name": "bitwarden-directory-connector",
"productName": "Bitwarden Directory Connector", "productName": "Bitwarden Directory Connector",
"description": "Sync your user directory to your Bitwarden organization.", "description": "Sync your user directory to your Bitwarden organization.",
"version": "2.6.1", "version": "2.6.2",
"author": "8bit Solutions LLC <hello@bitwarden.com> (https://bitwarden.com)", "author": "8bit Solutions LLC <hello@bitwarden.com> (https://bitwarden.com)",
"homepage": "https://bitwarden.com", "homepage": "https://bitwarden.com",
"license": "GPL-3.0", "license": "GPL-3.0",
@@ -14,7 +14,7 @@
"dependencies": { "dependencies": {
"electron-log": "2.2.17", "electron-log": "2.2.17",
"electron-store": "1.3.0", "electron-store": "1.3.0",
"electron-updater": "4.0.6", "electron-updater": "4.1.2",
"keytar": "4.4.1" "keytar": "4.13.0"
} }
} }

View File

@@ -25,7 +25,8 @@ const Keys = {
}; };
export class ConfigurationService { export class ConfigurationService {
constructor(private storageService: StorageService, private secureStorageService: StorageService) { } constructor(private storageService: StorageService, private secureStorageService: StorageService,
private useSecureStorageForSecrets = true) { }
async getDirectory<T>(type: DirectoryType): Promise<T> { async getDirectory<T>(type: DirectoryType): Promise<T> {
const config = await this.storageService.get<T>(Keys.directoryConfigPrefix + type); const config = await this.storageService.get<T>(Keys.directoryConfigPrefix + type);
@@ -33,19 +34,21 @@ export class ConfigurationService {
return config; return config;
} }
switch (type) { if (this.useSecureStorageForSecrets) {
case DirectoryType.Ldap: switch (type) {
(config as any).password = await this.secureStorageService.get<string>(Keys.ldap); case DirectoryType.Ldap:
break; (config as any).password = await this.secureStorageService.get<string>(Keys.ldap);
case DirectoryType.AzureActiveDirectory: break;
(config as any).key = await this.secureStorageService.get<string>(Keys.azure); case DirectoryType.AzureActiveDirectory:
break; (config as any).key = await this.secureStorageService.get<string>(Keys.azure);
case DirectoryType.Okta: break;
(config as any).token = await this.secureStorageService.get<string>(Keys.okta); case DirectoryType.Okta:
break; (config as any).token = await this.secureStorageService.get<string>(Keys.okta);
case DirectoryType.GSuite: break;
(config as any).privateKey = await this.secureStorageService.get<string>(Keys.gsuite); case DirectoryType.GSuite:
break; (config as any).privateKey = await this.secureStorageService.get<string>(Keys.gsuite);
break;
}
} }
return config; return config;
} }
@@ -53,41 +56,43 @@ export class ConfigurationService {
async saveDirectory(type: DirectoryType, async saveDirectory(type: DirectoryType,
config: LdapConfiguration | GSuiteConfiguration | AzureConfiguration | OktaConfiguration): Promise<any> { config: LdapConfiguration | GSuiteConfiguration | AzureConfiguration | OktaConfiguration): Promise<any> {
const savedConfig: any = Object.assign({}, config); const savedConfig: any = Object.assign({}, config);
switch (type) { if (this.useSecureStorageForSecrets) {
case DirectoryType.Ldap: switch (type) {
if (savedConfig.password == null) { case DirectoryType.Ldap:
await this.secureStorageService.remove(Keys.ldap); if (savedConfig.password == null) {
} else { await this.secureStorageService.remove(Keys.ldap);
await this.secureStorageService.save(Keys.ldap, savedConfig.password); } else {
savedConfig.password = StoredSecurely; await this.secureStorageService.save(Keys.ldap, savedConfig.password);
} savedConfig.password = StoredSecurely;
break; }
case DirectoryType.AzureActiveDirectory: break;
if (savedConfig.key == null) { case DirectoryType.AzureActiveDirectory:
await this.secureStorageService.remove(Keys.azure); if (savedConfig.key == null) {
} else { await this.secureStorageService.remove(Keys.azure);
await this.secureStorageService.save(Keys.azure, savedConfig.key); } else {
savedConfig.key = StoredSecurely; await this.secureStorageService.save(Keys.azure, savedConfig.key);
} savedConfig.key = StoredSecurely;
break; }
case DirectoryType.Okta: break;
if (savedConfig.token == null) { case DirectoryType.Okta:
await this.secureStorageService.remove(Keys.okta); if (savedConfig.token == null) {
} else { await this.secureStorageService.remove(Keys.okta);
await this.secureStorageService.save(Keys.okta, savedConfig.token); } else {
savedConfig.token = StoredSecurely; await this.secureStorageService.save(Keys.okta, savedConfig.token);
} savedConfig.token = StoredSecurely;
break; }
case DirectoryType.GSuite: break;
if (savedConfig.privateKey == null) { case DirectoryType.GSuite:
await this.secureStorageService.remove(Keys.gsuite); if (savedConfig.privateKey == null) {
} else { await this.secureStorageService.remove(Keys.gsuite);
(config as GSuiteConfiguration).privateKey = savedConfig.privateKey = } else {
savedConfig.privateKey.replace(/\\n/g, '\n'); (config as GSuiteConfiguration).privateKey = savedConfig.privateKey =
await this.secureStorageService.save(Keys.gsuite, savedConfig.privateKey); savedConfig.privateKey.replace(/\\n/g, '\n');
savedConfig.privateKey = StoredSecurely; await this.secureStorageService.save(Keys.gsuite, savedConfig.privateKey);
} savedConfig.privateKey = StoredSecurely;
break; }
break;
}
} }
await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig); await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig);
} }