mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-15 15:53:41 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6a5a3c8c1 | ||
|
|
3f3590a223 | ||
|
|
c1f64d7b82 | ||
|
|
f90611c96f | ||
|
|
630e21f7c1 | ||
|
|
2e81642c0e | ||
|
|
39514b9550 | ||
|
|
2da82d5610 | ||
|
|
69f33a08b6 | ||
|
|
a05e9c7746 | ||
|
|
d8031e4f49 | ||
|
|
e6aa07ba5c | ||
|
|
173129014a | ||
|
|
8d4baa6d31 | ||
|
|
20463ce653 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,3 +14,4 @@ yarn-error.log
|
||||
.DS_Store
|
||||
*.nupkg
|
||||
*.provisionprofile
|
||||
*.env
|
||||
|
||||
2
jslib
2
jslib
Submodule jslib updated: 8375f7381a...b74ee7b3ee
2303
package-lock.json
generated
2303
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@@ -22,6 +22,7 @@
|
||||
"sub:pull": "git submodule foreach git pull origin master",
|
||||
"sub:commit": "npm run sub:pull && git commit -am \"update submodule\"",
|
||||
"postinstall": "npm run sub:init",
|
||||
"simlink:win": "rm -rf ./jslib && cmd /c mklink /J .\\jslib ..\\jslib",
|
||||
"rebuild": "./node_modules/.bin/electron-rebuild",
|
||||
"reset": "rimraf ./node_modules/keytar/* && npm install",
|
||||
"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\"",
|
||||
"clean:dist": "rimraf ./dist/*",
|
||||
"clean:dist:cli": "rimraf ./dist-cli/*",
|
||||
"pack:lin": "npm run clean:dist && build --linux --x64 -p never",
|
||||
"pack:mac": "npm run clean:dist && build --mac -p never",
|
||||
"pack:win": "npm run clean:dist && build --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:lin": "npm run clean:dist && electron-builder --linux --x64 -p never",
|
||||
"pack:mac": "npm run clean:dist && electron-builder --mac -p never",
|
||||
"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 && 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:win": "pkg . --targets win-x64 --output ./dist-cli/windows/bwdc.exe",
|
||||
"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: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",
|
||||
"publish:lin": "npm run build:dist && npm run clean:dist && build --linux --x64 -p always",
|
||||
"publish:mac": "npm run build:dist && npm run clean:dist && build --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: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 && electron-builder --mac -p always",
|
||||
"publish:win": "npm run build:dist && npm run clean:dist && electron-builder --win --x64 --ia32 -p always -c.win.certificateSubjectName=\"8bit Solutions LLC\""
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.bitwarden.directory-connector",
|
||||
@@ -66,8 +67,13 @@
|
||||
"output": "dist",
|
||||
"app": "build"
|
||||
},
|
||||
"afterSign": "scripts/notarize.js",
|
||||
"mac": {
|
||||
"category": "public.app-category.productivity",
|
||||
"gatekeeperAssess": false,
|
||||
"hardenedRuntime": true,
|
||||
"entitlements": "resources/entitlements.mac.plist",
|
||||
"entitlementsInherit": "resources/entitlements.mac.plist",
|
||||
"target": [
|
||||
"dmg",
|
||||
"zip"
|
||||
@@ -153,10 +159,11 @@
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^1.0.0",
|
||||
"del": "^3.0.0",
|
||||
"electron": "3.0.14",
|
||||
"electron-builder": "20.38.5",
|
||||
"electron-rebuild": "^1.8.2",
|
||||
"electron-reload": "^1.4.0",
|
||||
"electron": "5.0.8",
|
||||
"electron-builder": "21.1.5",
|
||||
"electron-notarize": "^0.1.1",
|
||||
"electron-rebuild": "^1.8.5",
|
||||
"electron-reload": "^1.4.1",
|
||||
"extract-text-webpack-plugin": "next",
|
||||
"file-loader": "^2.0.0",
|
||||
"font-awesome": "4.7.0",
|
||||
@@ -164,7 +171,7 @@
|
||||
"gulp-google-webfonts": "^2.0.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"node-abi": "^2.5.1",
|
||||
"node-abi": "^2.9.0",
|
||||
"node-loader": "^0.6.0",
|
||||
"node-sass": "^4.11.0",
|
||||
"pkg": "4.3.4",
|
||||
@@ -202,11 +209,12 @@
|
||||
"duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git",
|
||||
"electron-log": "2.2.17",
|
||||
"electron-store": "1.3.0",
|
||||
"electron-updater": "4.0.6",
|
||||
"electron-updater": "4.1.2",
|
||||
"form-data": "2.3.2",
|
||||
"googleapis": "33.0.0",
|
||||
"https-proxy-agent": "2.2.1",
|
||||
"inquirer": "6.2.0",
|
||||
"keytar": "4.4.1",
|
||||
"keytar": "4.13.0",
|
||||
"ldapjs": "git+https://git@github.com/kspearrin/node-ldapjs.git",
|
||||
"lowdb": "1.0.0",
|
||||
"lunr": "2.3.3",
|
||||
|
||||
10
resources/entitlements.mac.plist
Normal file
10
resources/entitlements.mac.plist
Normal 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
17
scripts/notarize.js
Normal 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`,
|
||||
});
|
||||
};
|
||||
@@ -11,6 +11,7 @@ import { EnvironmentComponent } from './environment.component';
|
||||
import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
|
||||
import { StateService } from 'jslib/abstractions/state.service';
|
||||
import { StorageService } from 'jslib/abstractions/storage.service';
|
||||
|
||||
import { LoginComponent as BaseLoginComponent } from 'jslib/angular/components/login.component';
|
||||
@@ -25,8 +26,9 @@ export class LoginComponent extends BaseLoginComponent {
|
||||
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, private componentFactoryResolver: ComponentFactoryResolver,
|
||||
storageService: StorageService, platformUtilsService: PlatformUtilsService) {
|
||||
super(authService, router, platformUtilsService, i18nService, storageService);
|
||||
storageService: StorageService, platformUtilsService: PlatformUtilsService,
|
||||
stateService: StateService) {
|
||||
super(authService, router, platformUtilsService, i18nService, storageService, stateService);
|
||||
super.successRoute = '/tabs/dashboard';
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ import { AuthService } from 'jslib/abstractions/auth.service';
|
||||
import { EnvironmentService } from 'jslib/abstractions/environment.service';
|
||||
import { I18nService } from 'jslib/abstractions/i18n.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 { TwoFactorComponent as BaseTwoFactorComponent } from 'jslib/angular/components/two-factor.component';
|
||||
@@ -30,8 +32,10 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
|
||||
constructor(authService: AuthService, router: Router,
|
||||
i18nService: I18nService, apiService: ApiService,
|
||||
platformUtilsService: PlatformUtilsService, environmentService: EnvironmentService,
|
||||
private componentFactoryResolver: ComponentFactoryResolver) {
|
||||
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService);
|
||||
private componentFactoryResolver: ComponentFactoryResolver, stateService: StateService,
|
||||
storageService: StorageService) {
|
||||
super(authService, router, i18nService, apiService, platformUtilsService, window, environmentService,
|
||||
stateService, storageService);
|
||||
super.successRoute = '/tabs/dashboard';
|
||||
}
|
||||
|
||||
|
||||
13
src/bwdc.ts
13
src/bwdc.ts
@@ -25,6 +25,8 @@ import { NoopMessagingService } from 'jslib/services/noopMessaging.service';
|
||||
import { TokenService } from 'jslib/services/token.service';
|
||||
import { UserService } from 'jslib/services/user.service';
|
||||
|
||||
import { StorageService as StorageServiceAbstraction } from 'jslib/abstractions/storage.service';
|
||||
|
||||
import { Program } from './program';
|
||||
|
||||
// tslint:disable-next-line
|
||||
@@ -35,7 +37,7 @@ export class Main {
|
||||
logService: ConsoleLogService;
|
||||
messagingService: NoopMessagingService;
|
||||
storageService: LowdbStorageService;
|
||||
secureStorageService: KeytarSecureStorageService;
|
||||
secureStorageService: StorageServiceAbstraction;
|
||||
i18nService: I18nService;
|
||||
platformUtilsService: CliPlatformUtilsService;
|
||||
constantsService: ConstantsService;
|
||||
@@ -70,13 +72,15 @@ export class Main {
|
||||
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.platformUtilsService = new CliPlatformUtilsService('connector', packageJson);
|
||||
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.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.cryptoFunctionService);
|
||||
this.appIdService = new AppIdService(this.storageService);
|
||||
@@ -89,7 +93,8 @@ export class Main {
|
||||
this.containerService = new ContainerService(this.cryptoService);
|
||||
this.authService = new AuthService(this.cryptoService, this.apiService, this.userService, this.tokenService,
|
||||
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.apiService, this.messagingService, this.i18nService);
|
||||
this.program = new Program(this);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "bitwarden-directory-connector",
|
||||
"productName": "Bitwarden Directory Connector",
|
||||
"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)",
|
||||
"homepage": "https://bitwarden.com",
|
||||
"license": "GPL-3.0",
|
||||
@@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"electron-log": "2.2.17",
|
||||
"electron-store": "1.3.0",
|
||||
"electron-updater": "4.0.6",
|
||||
"keytar": "4.4.1"
|
||||
"electron-updater": "4.1.2",
|
||||
"keytar": "4.13.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@ const Keys = {
|
||||
};
|
||||
|
||||
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> {
|
||||
const config = await this.storageService.get<T>(Keys.directoryConfigPrefix + type);
|
||||
@@ -33,19 +34,21 @@ export class ConfigurationService {
|
||||
return config;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case DirectoryType.Ldap:
|
||||
(config as any).password = await this.secureStorageService.get<string>(Keys.ldap);
|
||||
break;
|
||||
case DirectoryType.AzureActiveDirectory:
|
||||
(config as any).key = await this.secureStorageService.get<string>(Keys.azure);
|
||||
break;
|
||||
case DirectoryType.Okta:
|
||||
(config as any).token = await this.secureStorageService.get<string>(Keys.okta);
|
||||
break;
|
||||
case DirectoryType.GSuite:
|
||||
(config as any).privateKey = await this.secureStorageService.get<string>(Keys.gsuite);
|
||||
break;
|
||||
if (this.useSecureStorageForSecrets) {
|
||||
switch (type) {
|
||||
case DirectoryType.Ldap:
|
||||
(config as any).password = await this.secureStorageService.get<string>(Keys.ldap);
|
||||
break;
|
||||
case DirectoryType.AzureActiveDirectory:
|
||||
(config as any).key = await this.secureStorageService.get<string>(Keys.azure);
|
||||
break;
|
||||
case DirectoryType.Okta:
|
||||
(config as any).token = await this.secureStorageService.get<string>(Keys.okta);
|
||||
break;
|
||||
case DirectoryType.GSuite:
|
||||
(config as any).privateKey = await this.secureStorageService.get<string>(Keys.gsuite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
@@ -53,41 +56,43 @@ export class ConfigurationService {
|
||||
async saveDirectory(type: DirectoryType,
|
||||
config: LdapConfiguration | GSuiteConfiguration | AzureConfiguration | OktaConfiguration): Promise<any> {
|
||||
const savedConfig: any = Object.assign({}, config);
|
||||
switch (type) {
|
||||
case DirectoryType.Ldap:
|
||||
if (savedConfig.password == null) {
|
||||
await this.secureStorageService.remove(Keys.ldap);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.ldap, savedConfig.password);
|
||||
savedConfig.password = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.AzureActiveDirectory:
|
||||
if (savedConfig.key == null) {
|
||||
await this.secureStorageService.remove(Keys.azure);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.azure, savedConfig.key);
|
||||
savedConfig.key = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.Okta:
|
||||
if (savedConfig.token == null) {
|
||||
await this.secureStorageService.remove(Keys.okta);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.okta, savedConfig.token);
|
||||
savedConfig.token = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.GSuite:
|
||||
if (savedConfig.privateKey == null) {
|
||||
await this.secureStorageService.remove(Keys.gsuite);
|
||||
} else {
|
||||
(config as GSuiteConfiguration).privateKey = savedConfig.privateKey =
|
||||
savedConfig.privateKey.replace(/\\n/g, '\n');
|
||||
await this.secureStorageService.save(Keys.gsuite, savedConfig.privateKey);
|
||||
savedConfig.privateKey = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
if (this.useSecureStorageForSecrets) {
|
||||
switch (type) {
|
||||
case DirectoryType.Ldap:
|
||||
if (savedConfig.password == null) {
|
||||
await this.secureStorageService.remove(Keys.ldap);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.ldap, savedConfig.password);
|
||||
savedConfig.password = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.AzureActiveDirectory:
|
||||
if (savedConfig.key == null) {
|
||||
await this.secureStorageService.remove(Keys.azure);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.azure, savedConfig.key);
|
||||
savedConfig.key = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.Okta:
|
||||
if (savedConfig.token == null) {
|
||||
await this.secureStorageService.remove(Keys.okta);
|
||||
} else {
|
||||
await this.secureStorageService.save(Keys.okta, savedConfig.token);
|
||||
savedConfig.token = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
case DirectoryType.GSuite:
|
||||
if (savedConfig.privateKey == null) {
|
||||
await this.secureStorageService.remove(Keys.gsuite);
|
||||
} else {
|
||||
(config as GSuiteConfiguration).privateKey = savedConfig.privateKey =
|
||||
savedConfig.privateKey.replace(/\\n/g, '\n');
|
||||
await this.secureStorageService.save(Keys.gsuite, savedConfig.privateKey);
|
||||
savedConfig.privateKey = StoredSecurely;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
await this.storageService.save(Keys.directoryConfigPrefix + type, savedConfig);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user