mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-15 15:53:41 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a16b8cb0e | ||
|
|
2583068dbd | ||
|
|
e5d0b3a372 | ||
|
|
9a1caf1e7e | ||
|
|
af0e41e26c | ||
|
|
d3049164a9 | ||
|
|
bdfda6775d | ||
|
|
72e6e74a42 | ||
|
|
75832fbed9 | ||
|
|
811b3adb51 | ||
|
|
e710df3ba7 | ||
|
|
4ee0c3ccba | ||
|
|
036b934119 | ||
|
|
4bfd43bf4c | ||
|
|
55722d3c04 | ||
|
|
77043d8d66 | ||
|
|
002117a6e5 | ||
|
|
5aa8097cfd | ||
|
|
5848553a4b | ||
|
|
3840bce6d7 |
29
.github/scripts/decrypt-secret.ps1
vendored
Normal file
29
.github/scripts/decrypt-secret.ps1
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string] $filename,
|
||||||
|
[string] $output
|
||||||
|
)
|
||||||
|
|
||||||
|
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path
|
||||||
|
$rootPath = $env:GITHUB_WORKSPACE
|
||||||
|
|
||||||
|
$secretInputPath = $rootPath + "/.github/secrets"
|
||||||
|
$input = $secretInputPath + "/" + $filename
|
||||||
|
|
||||||
|
$passphrase = $env:DECRYPT_FILE_PASSWORD
|
||||||
|
$secretOutputPath = $homePath + "/secrets"
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($output)) {
|
||||||
|
if ($filename.EndsWith(".gpg")) {
|
||||||
|
$output = $secretOutputPath + "/" + $filename.TrimEnd(".gpg")
|
||||||
|
} else {
|
||||||
|
$output = $secretOutputPath + "/" + $filename + ".plaintext"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path -Path $secretOutputPath))
|
||||||
|
{
|
||||||
|
New-Item -ItemType Directory -Path $secretOutputPath
|
||||||
|
}
|
||||||
|
|
||||||
|
gpg --quiet --batch --yes --decrypt --passphrase="$passphrase" --output $output $input
|
||||||
5
.github/scripts/load-version.ps1
vendored
Normal file
5
.github/scripts/load-version.ps1
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
$rootPath = $env:GITHUB_WORKSPACE;
|
||||||
|
$packageVersion = (Get-Content -Raw -Path $rootPath\src\package.json | ConvertFrom-Json).version;
|
||||||
|
|
||||||
|
Write-Output "Setting package version to $packageVersion";
|
||||||
|
Write-Output "PACKAGE_VERSION=$packageVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append;
|
||||||
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
Normal file
7
.github/scripts/macos/decrypt-secrets.ps1
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
$rootPath = $env:GITHUB_WORKSPACE;
|
||||||
|
|
||||||
|
$decryptSecretPath = $($rootPath + "/.github/scripts/decrypt-secret.ps1");
|
||||||
|
|
||||||
|
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-app-cert.p12.gpg"
|
||||||
|
Invoke-Expression "& `"$decryptSecretPath`" -filename devid-installer-cert.p12.gpg"
|
||||||
|
Invoke-Expression "& `"$decryptSecretPath`" -filename macdev-cert.p12.gpg"
|
||||||
15
.github/scripts/macos/setup-keychain.ps1
vendored
Normal file
15
.github/scripts/macos/setup-keychain.ps1
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
$homePath = Resolve-Path "~" | Select-Object -ExpandProperty Path;
|
||||||
|
$secretsPath = $homePath + "/secrets"
|
||||||
|
|
||||||
|
$devidAppCertPath = $($secretsPath + "/devid-app-cert.p12");
|
||||||
|
$devidInstallerCertPath = $($secretsPath + "/devid-installer-cert.p12");
|
||||||
|
$macdevCertPath = $($secretsPath + "/macdev-cert.p12");
|
||||||
|
|
||||||
|
security create-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
||||||
|
security default-keychain -s build.keychain
|
||||||
|
security unlock-keychain -p $env:KEYCHAIN_PASSWORD build.keychain
|
||||||
|
security set-keychain-settings -lut 1200 build.keychain
|
||||||
|
security import $devidAppCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security import $devidInstallerCertPath -k build.keychain -P $env:DEVID_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security import $macdevCertPath -k build.keychain -P $env:MACDEV_CERT_PASSWORD -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
|
||||||
|
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $env:KEYCHAIN_PASSWORD build.keychain
|
||||||
BIN
.github/secrets/devid-app-cert.p12.gpg
vendored
Normal file
BIN
.github/secrets/devid-app-cert.p12.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/devid-installer-cert.p12.gpg
vendored
Normal file
BIN
.github/secrets/devid-installer-cert.p12.gpg
vendored
Normal file
Binary file not shown.
BIN
.github/secrets/macdev-cert.p12.gpg
vendored
Normal file
BIN
.github/secrets/macdev-cert.p12.gpg
vendored
Normal file
Binary file not shown.
390
.github/workflows/build.yml
vendored
Normal file
390
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'l10n_master'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cloc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up cloc
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt -y install cloc
|
||||||
|
- name: Print lines of code
|
||||||
|
run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
|
||||||
|
|
||||||
|
|
||||||
|
setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
package_version: ${{ steps.get_version.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Get Package Version
|
||||||
|
id: get_version
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
||||||
|
echo "::set-output name=PACKAGE_VERSION::$env:pkgVersion"
|
||||||
|
|
||||||
|
|
||||||
|
cli:
|
||||||
|
runs-on: windows-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Windows builder
|
||||||
|
run: |
|
||||||
|
choco install checksum --no-progress
|
||||||
|
choco install reshack --no-progress
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Setting WIN_PKG
|
||||||
|
run: |
|
||||||
|
echo "WIN_PKG=$env:WIN_PKG" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
echo "version: $env:pkgVersion"
|
||||||
|
env:
|
||||||
|
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v2.5\fetched-v10.4.1-win-x64
|
||||||
|
|
||||||
|
- name: get pkg-fetch
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
cd $HOME
|
||||||
|
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v2.5/uploaded-v2.5-node-v10.4.1-win-x64"
|
||||||
|
|
||||||
|
New-Item -ItemType directory -Path ./.pkg-cache
|
||||||
|
New-Item -ItemType directory -Path ./.pkg-cache/v2.5
|
||||||
|
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v2.5/fetched-v10.4.1-win-x64"
|
||||||
|
env:
|
||||||
|
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v2.5\fetched-v10.4.1-win-x64
|
||||||
|
|
||||||
|
- name: Keytar
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$keytarVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).dependencies.keytar
|
||||||
|
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
||||||
|
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
||||||
|
$keytarTarGz = "${keytarTar}.gz"
|
||||||
|
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
||||||
|
|
||||||
|
New-Item -ItemType directory -Path ./keytar/macos | Out-Null
|
||||||
|
New-Item -ItemType directory -Path ./keytar/linux | Out-Null
|
||||||
|
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
|
||||||
|
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile "./keytar/macos/$($keytarTarGz -f "darwin")"
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile "./keytar/linux/$($keytarTarGz -f "linux")"
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
|
||||||
|
|
||||||
|
7z e "./keytar/macos/$($keytarTarGz -f "darwin")" -o"./keytar/macos"
|
||||||
|
7z e "./keytar/linux/$($keytarTarGz -f "linux")" -o"./keytar/linux"
|
||||||
|
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
|
||||||
|
|
||||||
|
7z e "./keytar/macos/$($keytarTar -f "darwin")" -o"./keytar/macos"
|
||||||
|
7z e "./keytar/linux/$($keytarTar -f "linux")" -o"./keytar/linux"
|
||||||
|
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
|
||||||
|
|
||||||
|
- name: Setup Version Info
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/make-versioninfo.ps1
|
||||||
|
|
||||||
|
- name: Resource Hacker
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
||||||
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
||||||
|
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
||||||
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Package CLI
|
||||||
|
run: npm run dist:cli
|
||||||
|
|
||||||
|
- name: Zip
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
||||||
|
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
||||||
|
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
||||||
|
|
||||||
|
- name: Version Test
|
||||||
|
run: |
|
||||||
|
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
||||||
|
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
||||||
|
echo "version: $env:PACKAGE_VERSION"
|
||||||
|
echo "testVersion: $testVersion"
|
||||||
|
if($testVersion -ne $env:PACKAGE_VERSION) {
|
||||||
|
Throw "Version test failed."
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Create checksums
|
||||||
|
run: |
|
||||||
|
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
|
||||||
|
- name: Upload windows zip to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
|
||||||
|
- name: Upload mac zip to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
|
||||||
|
- name: Upload linux zip to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
|
||||||
|
- name: Upload windows checksum to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
|
||||||
|
- name: Upload mac checksum to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
|
||||||
|
- name: Upload linux checksum to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
|
||||||
|
|
||||||
|
windows_gui:
|
||||||
|
runs-on: windows-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up dotnet
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: "3.1.x"
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: Print environment
|
||||||
|
run: |
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
dotnet --version
|
||||||
|
|
||||||
|
- name: Install AST
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
cd $HOME
|
||||||
|
|
||||||
|
git clone https://github.com/vcsjones/AzureSignTool.git
|
||||||
|
cd AzureSignTool
|
||||||
|
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
||||||
|
$latest_version = "0.0.0-g$latest_head"
|
||||||
|
|
||||||
|
Write-Host "--------"
|
||||||
|
Write-Host "git commit - $(git rev-parse HEAD)"
|
||||||
|
Write-Host "latest_head - $latest_head"
|
||||||
|
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
||||||
|
Write-Host "--------"
|
||||||
|
|
||||||
|
dotnet restore
|
||||||
|
dotnet pack --output ./nupkg
|
||||||
|
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Node dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Run linter
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Build & Sign
|
||||||
|
run: npm run dist:win
|
||||||
|
env:
|
||||||
|
ELECTRON_BUILDER_SIGN: 1
|
||||||
|
SIGNING_VAULT_URL: ${{ secrets.SIGNING_VAULT_URL }}
|
||||||
|
SIGNING_CLIENT_ID: ${{ secrets.SIGNING_CLIENT_ID }}
|
||||||
|
SIGNING_TENANT_ID: ${{ secrets.SIGNING_TENANT_ID }}
|
||||||
|
SIGNING_CLIENT_SECRET: ${{ secrets.SIGNING_CLIENT_SECRET }}
|
||||||
|
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||||
|
|
||||||
|
- name: List Dist
|
||||||
|
run: dir ./dist
|
||||||
|
|
||||||
|
- name: Publish Portable Exe to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
||||||
|
path: ./dist/Bitwarden-Connector-Portable-${{ env.PACKAGE_VERSION }}.exe
|
||||||
|
|
||||||
|
- name: Publish Installer Exe to GitHub
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
||||||
|
path: ./dist/Bitwarden-Connector-Installer-${{ env.PACKAGE_VERSION }}.exe
|
||||||
|
|
||||||
|
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set up environment
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||||
|
sudo apt-get -y install rpm
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: npm install
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: npm rebuild
|
||||||
|
run: npm run rebuild
|
||||||
|
|
||||||
|
- name: npm package
|
||||||
|
run: npm run dist:lin
|
||||||
|
|
||||||
|
- name: Publish AppImage
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
|
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
|
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Print environment
|
||||||
|
run: |
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
Write-Output "GitHub ref: $env:GITHUB_REF"
|
||||||
|
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
GITHUB_REF: ${{ github.ref }}
|
||||||
|
GITHUB_EVENT: ${{ github.event_name }}
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Decrypt secrets
|
||||||
|
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Set up keychain
|
||||||
|
run: ./.github/scripts/macos/setup-keychain.ps1
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
|
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
||||||
|
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Load package version
|
||||||
|
run: ./.github/scripts/load-version.ps1
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: Install Node dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Run linter
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Build application (dev)
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Build application (dist)
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
run: npm run dist:mac
|
||||||
|
env:
|
||||||
|
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||||
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Upload .zip artifact
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
||||||
|
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}-mac.zip
|
||||||
|
|
||||||
|
- name: Upload .dmg artifact
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
||||||
|
path: ./dist/Bitwarden-Connector-${{ env.PACKAGE_VERSION }}.dmg
|
||||||
392
.github/workflows/release.yml
vendored
Normal file
392
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_tag_name_input:
|
||||||
|
description: "Release Tag Name <X.X.X>"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
setup:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
package_version: ${{ steps.create_tags.outputs.package_version }}
|
||||||
|
tag_version: ${{ steps.create_tags.outputs.tag_version }}
|
||||||
|
release_upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Create Release Vars
|
||||||
|
id: create_tags
|
||||||
|
run: |
|
||||||
|
case "${RELEASE_TAG_NAME_INPUT:0:1}" in
|
||||||
|
v)
|
||||||
|
echo "RELEASE_NAME=${RELEASE_TAG_NAME_INPUT:1}" >> $GITHUB_ENV
|
||||||
|
echo "RELEASE_TAG_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||||
|
echo "::set-output name=package_version::${RELEASE_TAG_NAME_INPUT:1}"
|
||||||
|
echo "::set-output name=tag_version::$RELEASE_TAG_NAME_INPUT"
|
||||||
|
;;
|
||||||
|
[0-9])
|
||||||
|
echo "RELEASE_NAME=$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||||
|
echo "RELEASE_TAG_NAME=v$RELEASE_TAG_NAME_INPUT" >> $GITHUB_ENV
|
||||||
|
echo "::set-output name=package_version::$RELEASE_TAG_NAME_INPUT"
|
||||||
|
echo "::set-output name=tag_version::v$RELEASE_TAG_NAME_INPUT"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
env:
|
||||||
|
RELEASE_TAG_NAME_INPUT: ${{ github.event.inputs.release_tag_name_input }}
|
||||||
|
|
||||||
|
- name: Create Draft Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
tag_name: ${{ env.RELEASE_TAG_NAME }}
|
||||||
|
release_name: ${{ env.RELEASE_NAME }}
|
||||||
|
draft: true
|
||||||
|
prerelease: false
|
||||||
|
|
||||||
|
|
||||||
|
cli:
|
||||||
|
runs-on: windows-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Windows builder
|
||||||
|
run: |
|
||||||
|
choco install checksum --no-progress
|
||||||
|
choco install reshack --no-progress
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set VER_INFO
|
||||||
|
run: |
|
||||||
|
echo "WIN_PKG=$env:WIN_PKG" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
env:
|
||||||
|
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v2.5\fetched-v10.4.1-win-x64
|
||||||
|
|
||||||
|
- name: get pkg-fetch
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
cd $HOME
|
||||||
|
$fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v2.5/uploaded-v2.5-node-v10.4.1-win-x64"
|
||||||
|
|
||||||
|
New-Item -ItemType directory -Path ./.pkg-cache
|
||||||
|
New-Item -ItemType directory -Path ./.pkg-cache/v2.5
|
||||||
|
Invoke-RestMethod -Uri $fetchedUrl -OutFile "./.pkg-cache/v2.5/fetched-v10.4.1-win-x64"
|
||||||
|
env:
|
||||||
|
WIN_PKG: C:\Users\runneradmin\.pkg-cache\v2.5\fetched-v10.4.1-win-x64
|
||||||
|
|
||||||
|
- name: Keytar
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$keytarVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).dependencies.keytar
|
||||||
|
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
||||||
|
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
||||||
|
$keytarTarGz = "${keytarTar}.gz"
|
||||||
|
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
||||||
|
|
||||||
|
New-Item -ItemType directory -Path ./keytar/macos | Out-Null
|
||||||
|
New-Item -ItemType directory -Path ./keytar/linux | Out-Null
|
||||||
|
New-Item -ItemType directory -Path ./keytar/windows | Out-Null
|
||||||
|
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile "./keytar/macos/$($keytarTarGz -f "darwin")"
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile "./keytar/linux/$($keytarTarGz -f "linux")"
|
||||||
|
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile "./keytar/windows/$($keytarTarGz -f "win32")"
|
||||||
|
|
||||||
|
7z e "./keytar/macos/$($keytarTarGz -f "darwin")" -o"./keytar/macos"
|
||||||
|
7z e "./keytar/linux/$($keytarTarGz -f "linux")" -o"./keytar/linux"
|
||||||
|
7z e "./keytar/windows/$($keytarTarGz -f "win32")" -o"./keytar/windows"
|
||||||
|
|
||||||
|
7z e "./keytar/macos/$($keytarTar -f "darwin")" -o"./keytar/macos"
|
||||||
|
7z e "./keytar/linux/$($keytarTar -f "linux")" -o"./keytar/linux"
|
||||||
|
7z e "./keytar/windows/$($keytarTar -f "win32")" -o"./keytar/windows"
|
||||||
|
|
||||||
|
- name: Setup Version Info
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/make-versioninfo.ps1
|
||||||
|
|
||||||
|
- name: Resource Hacker
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker
|
||||||
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
||||||
|
ResourceHacker -open version-info.rc -save version-info.res -action compile
|
||||||
|
ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Package CLI
|
||||||
|
run: npm run dist:cli
|
||||||
|
|
||||||
|
- name: Zip
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
||||||
|
7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
||||||
|
7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
||||||
|
|
||||||
|
- name: Version Test
|
||||||
|
run: |
|
||||||
|
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
||||||
|
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
||||||
|
echo "version: $env:PACKAGE_VERSION"
|
||||||
|
echo "testVersion: $testVersion"
|
||||||
|
if($testVersion -ne $env:PACKAGE_VERSION) {
|
||||||
|
Throw "Version test failed."
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: Create checksums
|
||||||
|
run: |
|
||||||
|
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
||||||
|
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
||||||
|
|
||||||
|
- name: upload windows zip release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_name: bwdc-windows-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: upload macos zip release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_name: bwdc-macos-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: upload linux zip release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_name: bwdc-linux-${{ env.PACKAGE_VERSION }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: upload windows checksum release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_name: bwdc-windows-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_content_type: text/plain
|
||||||
|
|
||||||
|
- name: upload macos checksum release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_name: bwdc-macos-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_content_type: text/plain
|
||||||
|
|
||||||
|
- name: upload linux checksum release asset
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ needs.setup.outputs.release_upload_url }}
|
||||||
|
asset_path: ./dist-cli/bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_name: bwdc-linux-sha256-${{ env.PACKAGE_VERSION }}.txt
|
||||||
|
asset_content_type: text/plain
|
||||||
|
|
||||||
|
|
||||||
|
windows-gui:
|
||||||
|
runs-on: windows-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up dotnet
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: "3.1.x"
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: Print environment
|
||||||
|
run: |
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
dotnet --version
|
||||||
|
|
||||||
|
- name: Install AST
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
cd $HOME
|
||||||
|
git clone https://github.com/vcsjones/AzureSignTool.git
|
||||||
|
cd AzureSignTool
|
||||||
|
$latest_head = $(git rev-parse HEAD)[0..9] -join ""
|
||||||
|
$latest_version = "0.0.0-g$latest_head"
|
||||||
|
Write-Host "--------"
|
||||||
|
Write-Host "git commit - $(git rev-parse HEAD)"
|
||||||
|
Write-Host "latest_head - $latest_head"
|
||||||
|
Write-Host "PACKAGE VERSION TO BUILD - $latest_version"
|
||||||
|
Write-Host "--------"
|
||||||
|
dotnet restore
|
||||||
|
dotnet pack --output ./nupkg
|
||||||
|
dotnet tool install --global --ignore-failed-sources --add-source ./nupkg --version $latest_version azuresigntool
|
||||||
|
cd $HOME
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Node dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Run linter
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: npm rebuild
|
||||||
|
run: npm run rebuild
|
||||||
|
|
||||||
|
- name: Build & Sign
|
||||||
|
run: |
|
||||||
|
npm run publish:win
|
||||||
|
env:
|
||||||
|
ELECTRON_BUILDER_SIGN: 1
|
||||||
|
SIGNING_VAULT_URL: ${{ secrets.SIGNING_VAULT_URL }}
|
||||||
|
SIGNING_CLIENT_ID: ${{ secrets.SIGNING_CLIENT_ID }}
|
||||||
|
SIGNING_TENANT_ID: ${{ secrets.SIGNING_TENANT_ID }}
|
||||||
|
SIGNING_CLIENT_SECRET: ${{ secrets.SIGNING_CLIENT_SECRET }}
|
||||||
|
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Set up environment
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev
|
||||||
|
sudo apt-get -y install rpm
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set PACKAGE_VERSION
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$env:pkgVersion = (Get-Content -Raw -Path ./src/package.json | ConvertFrom-Json).version
|
||||||
|
echo "PACKAGE_VERSION=$env:pkgVersion" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||||
|
echo "version: $env:pkgVersion"
|
||||||
|
|
||||||
|
- name: npm install
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: npm rebuild
|
||||||
|
run: npm run rebuild
|
||||||
|
|
||||||
|
- name: npm package
|
||||||
|
run: npm run publish:lin
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
needs: setup
|
||||||
|
env:
|
||||||
|
PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
|
||||||
|
steps:
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '10.x'
|
||||||
|
|
||||||
|
- name: Set Node options
|
||||||
|
run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Print environment
|
||||||
|
run: |
|
||||||
|
node --version
|
||||||
|
npm --version
|
||||||
|
Write-Output "GitHub ref: $env:GITHUB_REF"
|
||||||
|
Write-Output "GitHub event: $env:GITHUB_EVENT"
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
GITHUB_REF: ${{ github.ref }}
|
||||||
|
GITHUB_EVENT: ${{ github.event_name }}
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Decrypt secrets
|
||||||
|
run: ./.github/scripts/macos/decrypt-secrets.ps1
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Set up keychain
|
||||||
|
run: ./.github/scripts/macos/setup-keychain.ps1
|
||||||
|
shell: pwsh
|
||||||
|
env:
|
||||||
|
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
||||||
|
DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }}
|
||||||
|
MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Load package version
|
||||||
|
run: ./.github/scripts/load-version.ps1
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
- name: Install Node dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Run linter
|
||||||
|
run: npm run lint
|
||||||
|
|
||||||
|
- name: Build application (dist)
|
||||||
|
run: npm run publish:mac
|
||||||
|
env:
|
||||||
|
APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }}
|
||||||
|
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
11
.vscode/launch.json
vendored
11
.vscode/launch.json
vendored
@@ -23,6 +23,17 @@
|
|||||||
"port": 9223,
|
"port": 9223,
|
||||||
"webRoot": "${workspaceFolder}/build",
|
"webRoot": "${workspaceFolder}/build",
|
||||||
"sourceMaps": true
|
"sourceMaps": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug CLI",
|
||||||
|
"protocol": "inspector",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"program": "${workspaceFolder}/build-cli/bwdc.js",
|
||||||
|
"args": [
|
||||||
|
"sync"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"compounds": [
|
"compounds": [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[](https://ci.appveyor.com/project/bitwarden/directory-connector)
|

|
||||||
[](https://gitter.im/bitwarden/Lobby)
|
[](https://gitter.im/bitwarden/Lobby)
|
||||||
|
|
||||||
# Bitwarden Directory Connector
|
# Bitwarden Directory Connector
|
||||||
|
|||||||
162
appveyor.yml
162
appveyor.yml
@@ -1,162 +0,0 @@
|
|||||||
image:
|
|
||||||
- Visual Studio 2017
|
|
||||||
- Ubuntu1804
|
|
||||||
|
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- l10n_master
|
|
||||||
|
|
||||||
environment:
|
|
||||||
WIN_PKG: C:\Users\appveyor\.pkg-cache\v2.5\fetched-v10.4.1-win-x64
|
|
||||||
|
|
||||||
stack: node 10
|
|
||||||
|
|
||||||
init:
|
|
||||||
- ps: |
|
|
||||||
if($isWindows -and $env:DEBUG_RDP -eq "true") {
|
|
||||||
iex ((new-object net.webclient).DownloadString(`
|
|
||||||
'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
|
||||||
}
|
|
||||||
- sh: sudo apt-get update
|
|
||||||
- sh: sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev rpm
|
|
||||||
- ps: |
|
|
||||||
if($isWindows) {
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
||||||
Install-Product node 10
|
|
||||||
$env:PATH = "C:\Program Files (x86)\Resource Hacker;${env:PATH}"
|
|
||||||
}
|
|
||||||
if($env:APPVEYOR_REPO_TAG -eq "true") {
|
|
||||||
$env:RELEASE_NAME = $env:APPVEYOR_REPO_TAG_NAME.TrimStart("v")
|
|
||||||
}
|
|
||||||
|
|
||||||
install:
|
|
||||||
- ps: |
|
|
||||||
$env:PACKAGE_VERSION = (Get-Content -Raw -Path .\src\package.json | ConvertFrom-Json).version
|
|
||||||
$env:PROD_DEPLOY = "false"
|
|
||||||
if($env:APPVEYOR_REPO_TAG -eq "true" -and $env:APPVEYOR_RE_BUILD -eq "True") {
|
|
||||||
$env:PROD_DEPLOY = "true"
|
|
||||||
echo "This is a production deployment."
|
|
||||||
}
|
|
||||||
if($isWindows) {
|
|
||||||
if(Test-Path -Path $env:WIN_PKG) {
|
|
||||||
$env:VER_INFO = "true"
|
|
||||||
}
|
|
||||||
choco install reshack --no-progress
|
|
||||||
choco install cloc --no-progress
|
|
||||||
choco install checksum --no-progress
|
|
||||||
cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git
|
|
||||||
.\make-versioninfo.ps1
|
|
||||||
}
|
|
||||||
- ps: |
|
|
||||||
if($isWindows) {
|
|
||||||
$keytarVersion = (Get-Content -Raw -Path .\src\package.json | ConvertFrom-Json).dependencies.keytar
|
|
||||||
$nodeModVersion = node -e "console.log(process.config.variables.node_module_version)"
|
|
||||||
$keytarTar = "keytar-v${keytarVersion}-node-v${nodeModVersion}-{0}-x64.tar"
|
|
||||||
$keytarTarGz = "${keytarTar}.gz"
|
|
||||||
$keytarUrl = "https://github.com/atom/node-keytar/releases/download/v${keytarVersion}/${keytarTarGz}"
|
|
||||||
|
|
||||||
New-Item -ItemType directory -Path .\keytar\macos | Out-Null
|
|
||||||
New-Item -ItemType directory -Path .\keytar\linux | Out-Null
|
|
||||||
New-Item -ItemType directory -Path .\keytar\windows | Out-Null
|
|
||||||
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "darwin") -OutFile ".\keytar\macos\$($keytarTarGz -f "darwin")"
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "linux") -OutFile ".\keytar\linux\$($keytarTarGz -f "linux")"
|
|
||||||
Invoke-RestMethod -Uri $($keytarUrl -f "win32") -OutFile ".\keytar\windows\$($keytarTarGz -f "win32")"
|
|
||||||
|
|
||||||
7z e ".\keytar\macos\$($keytarTarGz -f "darwin")" -o".\keytar\macos"
|
|
||||||
7z e ".\keytar\linux\$($keytarTarGz -f "linux")" -o".\keytar\linux"
|
|
||||||
7z e ".\keytar\windows\$($keytarTarGz -f "win32")" -o".\keytar\windows"
|
|
||||||
|
|
||||||
7z e ".\keytar\macos\$($keytarTar -f "darwin")" -o".\keytar\macos"
|
|
||||||
7z e ".\keytar\linux\$($keytarTar -f "linux")" -o".\keytar\linux"
|
|
||||||
7z e ".\keytar\windows\$($keytarTar -f "win32")" -o".\keytar\windows"
|
|
||||||
}
|
|
||||||
|
|
||||||
before_build:
|
|
||||||
- node --version
|
|
||||||
- npm --version
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- cmd: |
|
|
||||||
if defined VER_INFO ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action delete -mask ICONGROUP,1,
|
|
||||||
if defined VER_INFO ResourceHacker -open version-info.rc -save version-info.res -action compile
|
|
||||||
if defined VER_INFO ResourceHacker -open %WIN_PKG% -save %WIN_PKG% -action addoverwrite -resource version-info.res
|
|
||||||
- sh: npm install
|
|
||||||
- sh: npm run rebuild
|
|
||||||
- sh: npm run dist:lin
|
|
||||||
- cmd: npm install
|
|
||||||
- cmd: npm run rebuild
|
|
||||||
- cmd: npm run dist:win:ci
|
|
||||||
- cmd: npm run reset
|
|
||||||
- cmd: npm run dist:cli
|
|
||||||
- cmd: 7z a ./dist-cli/bwdc-windows-%PACKAGE_VERSION%.zip ./dist-cli/windows/bwdc.exe ./keytar/windows/keytar.node
|
|
||||||
- cmd: 7z a ./dist-cli/bwdc-macos-%PACKAGE_VERSION%.zip ./dist-cli/macos/bwdc ./keytar/macos/keytar.node
|
|
||||||
- cmd: 7z a ./dist-cli/bwdc-linux-%PACKAGE_VERSION%.zip ./dist-cli/linux/bwdc ./keytar/linux/keytar.node
|
|
||||||
- ps: |
|
|
||||||
if($isWindows) {
|
|
||||||
Expand-Archive -Path "./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" -DestinationPath "./test/windows"
|
|
||||||
$testVersion = Invoke-Expression '& ./test/windows/bwdc.exe -v'
|
|
||||||
if($testVersion -ne $env:PACKAGE_VERSION) {
|
|
||||||
Throw "Version test failed."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- ps: |
|
|
||||||
if($isWindows) {
|
|
||||||
checksum -f="./dist-cli/bwdc-windows-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
checksum -f="./dist-cli/bwdc-macos-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
checksum -f="./dist-cli/bwdc-linux-${env:PACKAGE_VERSION}.zip" `
|
|
||||||
-t sha256 | Out-File ./dist-cli/bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
}
|
|
||||||
- ps: |
|
|
||||||
if($isLinux) {
|
|
||||||
Push-AppveyorArtifact ./dist/Bitwarden-Connector-${env:PACKAGE_VERSION}-x86_64.AppImage
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Push-AppveyorArtifact .\dist\Bitwarden-Connector-Portable-${env:PACKAGE_VERSION}.exe
|
|
||||||
Push-AppveyorArtifact .\dist\Bitwarden-Connector-Installer-${env:PACKAGE_VERSION}.exe
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-windows-${env:PACKAGE_VERSION}.zip
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-macos-${env:PACKAGE_VERSION}.zip
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-linux-${env:PACKAGE_VERSION}.zip
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-windows-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-macos-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
Push-AppveyorArtifact .\dist-cli\bwdc-linux-sha256-${env:PACKAGE_VERSION}.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
on_finish:
|
|
||||||
- ps: |
|
|
||||||
if($isWindows -and $env:DEBUG_RDP -eq "true") {
|
|
||||||
$blockRdp = $true
|
|
||||||
iex ((new-object net.webclient).DownloadString(`
|
|
||||||
'https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
|
||||||
}
|
|
||||||
|
|
||||||
for:
|
|
||||||
-
|
|
||||||
matrix:
|
|
||||||
only:
|
|
||||||
- image: Visual Studio 2017
|
|
||||||
cache:
|
|
||||||
- '%LOCALAPPDATA%\electron'
|
|
||||||
- '%LOCALAPPDATA%\electron-builder'
|
|
||||||
- 'C:\Users\appveyor\.pkg-cache\'
|
|
||||||
|
|
||||||
-
|
|
||||||
matrix:
|
|
||||||
only:
|
|
||||||
- image: Ubuntu1804
|
|
||||||
cache:
|
|
||||||
- '/home/appveyor/.cache/electron'
|
|
||||||
- '/home/appveyor/.cache/electron-builder'
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
tag: $(APPVEYOR_REPO_TAG_NAME)
|
|
||||||
release: $(RELEASE_NAME)
|
|
||||||
provider: GitHub
|
|
||||||
auth_token: $(GH_TOKEN)
|
|
||||||
artifact: /.*\.(zip|txt)/,
|
|
||||||
force_update: true
|
|
||||||
on:
|
|
||||||
branch: master
|
|
||||||
APPVEYOR_REPO_TAG: true
|
|
||||||
2
jslib
2
jslib
Submodule jslib updated: abb54f0073...fc1275aeb2
3489
package-lock.json
generated
3489
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
@@ -27,8 +27,8 @@
|
|||||||
"symlink:lin": "rm -rf ./jslib && ln -s ../jslib ./jslib",
|
"symlink:lin": "rm -rf ./jslib && ln -s ../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",
|
||||||
"lint:fix": "tslint src/**/*.ts --fix",
|
"lint:fix": "tslint 'src/**/*.ts' --fix",
|
||||||
"build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"",
|
"build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"",
|
||||||
"build:main": "webpack --config webpack.main.js",
|
"build:main": "webpack --config webpack.main.js",
|
||||||
"build:renderer": "gulp prebuild:renderer && webpack --config webpack.renderer.js",
|
"build:renderer": "gulp prebuild:renderer && webpack --config webpack.renderer.js",
|
||||||
@@ -46,9 +46,9 @@
|
|||||||
"pack:win": "npm run clean:dist && electron-builder --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 && electron-builder --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 ./src-cli --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 ./src-cli --targets macos-x64 --output ./dist-cli/macos/bwdc",
|
||||||
"pack:cli:lin": "pkg . --targets linux-x64 --output ./dist-cli/linux/bwdc",
|
"pack:cli:lin": "pkg ./src-cli --targets linux-x64 --output ./dist-cli/linux/bwdc",
|
||||||
"dist:lin": "npm run build:dist && npm run pack:lin",
|
"dist:lin": "npm run build:dist && npm run pack:lin",
|
||||||
"dist:mac": "npm run build:dist && npm run pack:mac",
|
"dist:mac": "npm run build:dist && npm run pack:mac",
|
||||||
"dist:win": "npm run build:dist && npm run pack:win",
|
"dist:win": "npm run build:dist && npm run pack:win",
|
||||||
@@ -85,7 +85,8 @@
|
|||||||
"target": [
|
"target": [
|
||||||
"portable",
|
"portable",
|
||||||
"nsis"
|
"nsis"
|
||||||
]
|
],
|
||||||
|
"sign": "scripts/sign.js"
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"category": "Utility",
|
"category": "Utility",
|
||||||
@@ -130,12 +131,6 @@
|
|||||||
"artifactName": "Bitwarden-Connector-${version}-${arch}.${ext}"
|
"artifactName": "Bitwarden-Connector-${version}-${arch}.${ext}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bin": {
|
|
||||||
"bwdc": "./build-cli/bwdc.js"
|
|
||||||
},
|
|
||||||
"pkg": {
|
|
||||||
"assets": "./build-cli/**/*"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/compiler-cli": "^9.1.12",
|
"@angular/compiler-cli": "^9.1.12",
|
||||||
"@microsoft/microsoft-graph-types": "^1.4.0",
|
"@microsoft/microsoft-graph-types": "^1.4.0",
|
||||||
@@ -150,6 +145,7 @@
|
|||||||
"@types/node-fetch": "^2.1.2",
|
"@types/node-fetch": "^2.1.2",
|
||||||
"@types/node-forge": "^0.7.5",
|
"@types/node-forge": "^0.7.5",
|
||||||
"@types/papaparse": "^4.5.3",
|
"@types/papaparse": "^4.5.3",
|
||||||
|
"@types/proper-lockfile": "^4.1.1",
|
||||||
"@types/semver": "^5.5.0",
|
"@types/semver": "^5.5.0",
|
||||||
"@types/source-map": "0.5.2",
|
"@types/source-map": "0.5.2",
|
||||||
"@types/webcrypto": "^0.0.28",
|
"@types/webcrypto": "^0.0.28",
|
||||||
@@ -161,18 +157,18 @@
|
|||||||
"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": "6.1.7",
|
"electron": "11.1.1",
|
||||||
"electron-builder": "22.4.0",
|
"electron-builder": "22.9.1",
|
||||||
"electron-notarize": "^0.2.1",
|
"electron-notarize": "^1.0.0",
|
||||||
"electron-rebuild": "^1.9.0",
|
"electron-rebuild": "^2.3.4",
|
||||||
"electron-reload": "^1.5.0",
|
"electron-reload": "^1.5.0",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
|
||||||
"file-loader": "^2.0.0",
|
"file-loader": "^2.0.0",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"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",
|
||||||
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"node-abi": "^2.9.0",
|
"node-abi": "^2.9.0",
|
||||||
"node-loader": "^0.6.0",
|
"node-loader": "^0.6.0",
|
||||||
"node-sass": "^4.13.1",
|
"node-sass": "^4.13.1",
|
||||||
@@ -203,24 +199,26 @@
|
|||||||
"angulartics2": "9.1.0",
|
"angulartics2": "9.1.0",
|
||||||
"big-integer": "1.6.36",
|
"big-integer": "1.6.36",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "4.3.1",
|
||||||
|
"browser-hrtime": "^1.1.8",
|
||||||
"chalk": "2.4.1",
|
"chalk": "2.4.1",
|
||||||
"commander": "2.18.0",
|
"commander": "7.0.0",
|
||||||
"core-js": "2.6.2",
|
"core-js": "2.6.2",
|
||||||
"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": "4.3.0",
|
||||||
"electron-store": "1.3.0",
|
"electron-store": "6.0.1",
|
||||||
"electron-updater": "4.2.0",
|
"electron-updater": "4.3.5",
|
||||||
"form-data": "2.3.2",
|
"form-data": "2.3.2",
|
||||||
"googleapis": "43.0.0",
|
"googleapis": "43.0.0",
|
||||||
"https-proxy-agent": "4.0.0",
|
"https-proxy-agent": "5.0.0",
|
||||||
"inquirer": "6.2.0",
|
"inquirer": "6.2.0",
|
||||||
"keytar": "4.13.0",
|
"keytar": "7.3.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",
|
||||||
"node-fetch": "2.2.0",
|
"node-fetch": "2.2.0",
|
||||||
"node-forge": "0.7.6",
|
"node-forge": "0.7.6",
|
||||||
"open": "7.1.0",
|
"open": "7.1.0",
|
||||||
|
"proper-lockfile": "^4.1.2",
|
||||||
"rxjs": "6.6.2",
|
"rxjs": "6.6.2",
|
||||||
"tslib": "^2.0.1",
|
"tslib": "^2.0.1",
|
||||||
"zone.js": "0.10.3",
|
"zone.js": "0.10.3",
|
||||||
|
|||||||
23
scripts/sign.js
Normal file
23
scripts/sign.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
exports.default = async function(configuration) {
|
||||||
|
if (
|
||||||
|
parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 &&
|
||||||
|
configuration.path.slice(-4) == ".exe"
|
||||||
|
) {
|
||||||
|
console.log(`[*] Signing file: ${configuration.path}`)
|
||||||
|
require("child_process").execSync(
|
||||||
|
`azuresigntool sign ` +
|
||||||
|
`-kvu ${process.env.SIGNING_VAULT_URL} ` +
|
||||||
|
`-kvi ${process.env.SIGNING_CLIENT_ID} ` +
|
||||||
|
`-kvt ${process.env.SIGNING_TENANT_ID} ` +
|
||||||
|
`-kvs ${process.env.SIGNING_CLIENT_SECRET} ` +
|
||||||
|
`-kvc ${process.env.SIGNING_CERT_NAME} ` +
|
||||||
|
`-fd ${configuration.hash} ` +
|
||||||
|
`-du ${configuration.site} ` +
|
||||||
|
`-tr http://timestamp.digicert.com ` +
|
||||||
|
`"${configuration.path}"`,
|
||||||
|
{
|
||||||
|
stdio: "inherit"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
24
src-cli/package.json
Normal file
24
src-cli/package.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "bitwarden-directory-connector",
|
||||||
|
"productName": "Bitwarden Directory Connector",
|
||||||
|
"description": "Sync your user directory to your Bitwarden organization.",
|
||||||
|
"version": "2.9.0",
|
||||||
|
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||||
|
"homepage": "https://bitwarden.com",
|
||||||
|
"license": "GPL-3.0",
|
||||||
|
"main": "main.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/bitwarden/directory-connector"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"bwdc": "../build-cli/bwdc.js"
|
||||||
|
},
|
||||||
|
"pkg": {
|
||||||
|
"assets": "../build-cli/**/*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"browser-hrtime": "^1.1.8",
|
||||||
|
"keytar": "7.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,7 +68,7 @@ const platformUtilsService = new ElectronPlatformUtilsService(i18nService, messa
|
|||||||
const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService();
|
const secureStorageService: StorageServiceAbstraction = new ElectronRendererSecureStorageService();
|
||||||
const cryptoFunctionService: CryptoFunctionServiceAbstraction = new NodeCryptoFunctionService();
|
const cryptoFunctionService: CryptoFunctionServiceAbstraction = new NodeCryptoFunctionService();
|
||||||
const cryptoService = new CryptoService(storageService, secureStorageService, cryptoFunctionService,
|
const cryptoService = new CryptoService(storageService, secureStorageService, cryptoFunctionService,
|
||||||
platformUtilsService);
|
platformUtilsService, logService);
|
||||||
const appIdService = new AppIdService(storageService);
|
const appIdService = new AppIdService(storageService);
|
||||||
const tokenService = new TokenService(storageService);
|
const tokenService = new TokenService(storageService);
|
||||||
const apiService = new ApiService(tokenService, platformUtilsService,
|
const apiService = new ApiService(tokenService, platformUtilsService,
|
||||||
@@ -77,7 +77,7 @@ const environmentService = new EnvironmentService(apiService, storageService, nu
|
|||||||
const userService = new UserService(tokenService, storageService);
|
const userService = new UserService(tokenService, storageService);
|
||||||
const containerService = new ContainerService(cryptoService);
|
const containerService = new ContainerService(cryptoService);
|
||||||
const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService,
|
const authService = new AuthService(cryptoService, apiService, userService, tokenService, appIdService,
|
||||||
i18nService, platformUtilsService, messagingService, null, false);
|
i18nService, platformUtilsService, messagingService, null, logService, false);
|
||||||
const configurationService = new ConfigurationService(storageService, secureStorageService);
|
const configurationService = new ConfigurationService(storageService, secureStorageService);
|
||||||
const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService,
|
const syncService = new SyncService(configurationService, logService, cryptoFunctionService, apiService,
|
||||||
messagingService, i18nService);
|
messagingService, i18nService);
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsText(filePicker.files[0], 'utf-8');
|
reader.readAsText(filePicker.files[0], 'utf-8');
|
||||||
reader.onload = (evt) => {
|
reader.onload = evt => {
|
||||||
this.ngZone.run(async () => {
|
this.ngZone.run(async () => {
|
||||||
try {
|
try {
|
||||||
const result = JSON.parse((evt.target as FileReader).result as string);
|
const result = JSON.parse((evt.target as FileReader).result as string);
|
||||||
|
|||||||
13
src/bwdc.ts
13
src/bwdc.ts
@@ -8,6 +8,7 @@ import { AuthService } from 'jslib/services/auth.service';
|
|||||||
import { ConfigurationService } from './services/configuration.service';
|
import { ConfigurationService } from './services/configuration.service';
|
||||||
import { I18nService } from './services/i18n.service';
|
import { I18nService } from './services/i18n.service';
|
||||||
import { KeytarSecureStorageService } from './services/keytarSecureStorage.service';
|
import { KeytarSecureStorageService } from './services/keytarSecureStorage.service';
|
||||||
|
import { LowdbStorageService } from './services/lowdbStorage.service';
|
||||||
import { SyncService } from './services/sync.service';
|
import { SyncService } from './services/sync.service';
|
||||||
|
|
||||||
import { CliPlatformUtilsService } from 'jslib/cli/services/cliPlatformUtils.service';
|
import { CliPlatformUtilsService } from 'jslib/cli/services/cliPlatformUtils.service';
|
||||||
@@ -18,7 +19,6 @@ import { ConstantsService } from 'jslib/services/constants.service';
|
|||||||
import { ContainerService } from 'jslib/services/container.service';
|
import { ContainerService } from 'jslib/services/container.service';
|
||||||
import { CryptoService } from 'jslib/services/crypto.service';
|
import { CryptoService } from 'jslib/services/crypto.service';
|
||||||
import { EnvironmentService } from 'jslib/services/environment.service';
|
import { EnvironmentService } from 'jslib/services/environment.service';
|
||||||
import { LowdbStorageService } from 'jslib/services/lowdbStorage.service';
|
|
||||||
import { NodeApiService } from 'jslib/services/nodeApi.service';
|
import { NodeApiService } from 'jslib/services/nodeApi.service';
|
||||||
import { NodeCryptoFunctionService } from 'jslib/services/nodeCryptoFunction.service';
|
import { NodeCryptoFunctionService } from 'jslib/services/nodeCryptoFunction.service';
|
||||||
import { NoopMessagingService } from 'jslib/services/noopMessaging.service';
|
import { NoopMessagingService } from 'jslib/services/noopMessaging.service';
|
||||||
@@ -78,13 +78,13 @@ export class Main {
|
|||||||
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.BITWARDENCLI_CONNECTOR_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(this.logService, null, this.dataFilePath, true);
|
this.storageService = new LowdbStorageService(this.logService, null, this.dataFilePath, false, true);
|
||||||
this.secureStorageService = plaintextSecrets ?
|
this.secureStorageService = plaintextSecrets ?
|
||||||
this.storageService : new KeytarSecureStorageService(applicationName);
|
this.storageService : new KeytarSecureStorageService(applicationName);
|
||||||
this.cryptoService = new CryptoService(this.storageService, this.secureStorageService,
|
this.cryptoService = new CryptoService(this.storageService, this.secureStorageService,
|
||||||
this.cryptoFunctionService, this.platformUtilsService);
|
this.cryptoFunctionService, this.platformUtilsService, this.logService);
|
||||||
this.appIdService = new AppIdService(this.storageService);
|
this.appIdService = new AppIdService(this.storageService);
|
||||||
this.tokenService = new TokenService(this.storageService);
|
this.tokenService = new TokenService(this.storageService);
|
||||||
this.messagingService = new NoopMessagingService();
|
this.messagingService = new NoopMessagingService();
|
||||||
@@ -94,7 +94,8 @@ export class Main {
|
|||||||
this.userService = new UserService(this.tokenService, this.storageService);
|
this.userService = new UserService(this.tokenService, this.storageService);
|
||||||
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, null, false);
|
this.appIdService, this.i18nService, this.platformUtilsService, this.messagingService, null,
|
||||||
|
this.logService, false);
|
||||||
this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
|
this.configurationService = new ConfigurationService(this.storageService, this.secureStorageService,
|
||||||
process.env.BITWARDENCLI_CONNECTOR_PLAINTEXT_SECRETS !== 'true');
|
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,
|
||||||
@@ -116,7 +117,7 @@ export class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async init() {
|
private async init() {
|
||||||
this.storageService.init();
|
await this.storageService.init();
|
||||||
this.containerService.attachToWindow(global);
|
this.containerService.attachToWindow(global);
|
||||||
await this.environmentService.setUrlsFromStorage();
|
await this.environmentService.setUrlsFromStorage();
|
||||||
// Dev Server URLs. Comment out the line above.
|
// Dev Server URLs. Comment out the line above.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { MessageResponse } from 'jslib/cli/models/response/messageResponse';
|
|||||||
export class ClearCacheCommand {
|
export class ClearCacheCommand {
|
||||||
constructor(private configurationService: ConfigurationService, private i18nService: I18nService) { }
|
constructor(private configurationService: ConfigurationService, private i18nService: I18nService) { }
|
||||||
|
|
||||||
async run(cmd: program.Command): Promise<Response> {
|
async run(cmd: program.OptionValues): Promise<Response> {
|
||||||
try {
|
try {
|
||||||
await this.configurationService.clearStatefulSettings(true);
|
await this.configurationService.clearStatefulSettings(true);
|
||||||
const res = new MessageResponse(this.i18nService.t('syncCacheCleared'), null);
|
const res = new MessageResponse(this.i18nService.t('syncCacheCleared'), null);
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import { SyncConfiguration } from '../models/syncConfiguration';
|
|||||||
|
|
||||||
import { ConnectorUtils } from '../utils';
|
import { ConnectorUtils } from '../utils';
|
||||||
|
|
||||||
|
import { NodeUtils } from 'jslib/misc/nodeUtils';
|
||||||
|
|
||||||
export class ConfigCommand {
|
export class ConfigCommand {
|
||||||
private directory: DirectoryType;
|
private directory: DirectoryType;
|
||||||
private ldap = new LdapConfiguration();
|
private ldap = new LdapConfiguration();
|
||||||
@@ -31,8 +33,15 @@ export class ConfigCommand {
|
|||||||
constructor(private environmentService: EnvironmentService, private i18nService: I18nService,
|
constructor(private environmentService: EnvironmentService, private i18nService: I18nService,
|
||||||
private configurationService: ConfigurationService) { }
|
private configurationService: ConfigurationService) { }
|
||||||
|
|
||||||
async run(setting: string, value: string, cmd: program.Command): Promise<Response> {
|
async run(setting: string, value: string, options: program.OptionValues): Promise<Response> {
|
||||||
setting = setting.toLowerCase();
|
setting = setting.toLowerCase();
|
||||||
|
if (value == null || value === '') {
|
||||||
|
if (options.secretfile) {
|
||||||
|
value = await NodeUtils.readFirstLine(options.secretfile);
|
||||||
|
} else if (options.secretenv && process.env[options.secretenv]) {
|
||||||
|
value = process.env[options.secretenv];
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
switch (setting) {
|
switch (setting) {
|
||||||
case 'server':
|
case 'server':
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { StringResponse } from 'jslib/cli/models/response/stringResponse';
|
|||||||
export class LastSyncCommand {
|
export class LastSyncCommand {
|
||||||
constructor(private configurationService: ConfigurationService) { }
|
constructor(private configurationService: ConfigurationService) { }
|
||||||
|
|
||||||
async run(object: string, cmd: program.Command): Promise<Response> {
|
async run(object: string): Promise<Response> {
|
||||||
try {
|
try {
|
||||||
switch (object.toLowerCase()) {
|
switch (object.toLowerCase()) {
|
||||||
case 'groups':
|
case 'groups':
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { MessageResponse } from 'jslib/cli/models/response/messageResponse';
|
|||||||
export class SyncCommand {
|
export class SyncCommand {
|
||||||
constructor(private syncService: SyncService, private i18nService: I18nService) { }
|
constructor(private syncService: SyncService, private i18nService: I18nService) { }
|
||||||
|
|
||||||
async run(cmd: program.Command): Promise<Response> {
|
async run(): Promise<Response> {
|
||||||
try {
|
try {
|
||||||
const result = await this.syncService.sync(false, false);
|
const result = await this.syncService.sync(false, false);
|
||||||
const groupCount = result[0] != null ? result[0].length : 0;
|
const groupCount = result[0] != null ? result[0].length : 0;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { TestResponse } from '../models/response/testResponse';
|
|||||||
export class TestCommand {
|
export class TestCommand {
|
||||||
constructor(private syncService: SyncService, private i18nService: I18nService) { }
|
constructor(private syncService: SyncService, private i18nService: I18nService) { }
|
||||||
|
|
||||||
async run(cmd: program.Command): Promise<Response> {
|
async run(cmd: program.OptionValues): Promise<Response> {
|
||||||
try {
|
try {
|
||||||
const result = await ConnectorUtils.simulate(this.syncService, this.i18nService, cmd.last || false);
|
const result = await ConnectorUtils.simulate(this.syncService, this.i18nService, cmd.last || false);
|
||||||
const res = new TestResponse(result);
|
const res = new TestResponse(result);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export class Main {
|
|||||||
app.setPath('logs', path.join(app.getPath('userData'), 'logs'));
|
app.setPath('logs', path.join(app.getPath('userData'), 'logs'));
|
||||||
|
|
||||||
const args = process.argv.slice(1);
|
const args = process.argv.slice(1);
|
||||||
const watch = args.some((val) => val === '--watch');
|
const watch = args.some(val => val === '--watch');
|
||||||
|
|
||||||
if (watch) {
|
if (watch) {
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
@@ -52,8 +52,7 @@ export class Main {
|
|||||||
this.i18nService = new I18nService('en', './locales/');
|
this.i18nService = new I18nService('en', './locales/');
|
||||||
this.storageService = new ElectronStorageService(app.getPath('userData'));
|
this.storageService = new ElectronStorageService(app.getPath('userData'));
|
||||||
|
|
||||||
this.windowMain = new WindowMain(this.storageService, false, 800, 600,
|
this.windowMain = new WindowMain(this.storageService, false, 800, 600, arg => this.processDeepLink(arg), null);
|
||||||
(arg) => this.processDeepLink(arg));
|
|
||||||
this.menuMain = new MenuMain(this);
|
this.menuMain = new MenuMain(this);
|
||||||
this.updaterMain = new UpdaterMain(this.i18nService, this.windowMain, 'directory-connector', () => {
|
this.updaterMain = new UpdaterMain(this.i18nService, this.windowMain, 'directory-connector', () => {
|
||||||
this.messagingService.send('checkingForUpdate');
|
this.messagingService.send('checkingForUpdate');
|
||||||
@@ -64,7 +63,7 @@ export class Main {
|
|||||||
}, 'bitwardenDirectoryConnector');
|
}, 'bitwardenDirectoryConnector');
|
||||||
this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.storageService);
|
this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.storageService);
|
||||||
this.messagingMain = new MessagingMain(this.windowMain, this.menuMain, this.updaterMain, this.trayMain);
|
this.messagingMain = new MessagingMain(this.windowMain, this.menuMain, this.updaterMain, this.trayMain);
|
||||||
this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => {
|
this.messagingService = new ElectronMainMessagingService(this.windowMain, message => {
|
||||||
this.messagingMain.onMessage(message);
|
this.messagingMain.onMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@ export class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private processDeepLink(argv: string[]): void {
|
private processDeepLink(argv: string[]): void {
|
||||||
argv.filter((s) => s.indexOf('bwdc://') === 0).forEach((s) => {
|
argv.filter(s => s.indexOf('bwdc://') === 0).forEach(s => {
|
||||||
const url = new URL(s);
|
const url = new URL(s);
|
||||||
const code = url.searchParams.get('code');
|
const code = url.searchParams.get('code');
|
||||||
const receivedState = url.searchParams.get('state');
|
const receivedState = url.searchParams.get('state');
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ export class TestResponse implements BaseResponse {
|
|||||||
|
|
||||||
constructor(result: SimResult) {
|
constructor(result: SimResult) {
|
||||||
this.object = 'test';
|
this.object = 'test';
|
||||||
this.groups = result.groups != null ? result.groups.map((g) => new GroupResponse(g)) : [];
|
this.groups = result.groups != null ? result.groups.map(g => new GroupResponse(g)) : [];
|
||||||
this.enabledUsers = result.enabledUsers != null ? result.enabledUsers.map((u) => new UserResponse(u)) : [];
|
this.enabledUsers = result.enabledUsers != null ? result.enabledUsers.map(u => new UserResponse(u)) : [];
|
||||||
this.disabledUsers = result.disabledUsers != null ? result.disabledUsers.map((u) => new UserResponse(u)) : [];
|
this.disabledUsers = result.disabledUsers != null ? result.disabledUsers.map(u => new UserResponse(u)) : [];
|
||||||
this.deletedUsers = result.deletedUsers != null ? result.deletedUsers.map((u) => new UserResponse(u)) : [];
|
this.deletedUsers = result.deletedUsers != null ? result.deletedUsers.map(u => new UserResponse(u)) : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.8.2",
|
"version": "2.9.0",
|
||||||
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
"author": "Bitwarden Inc. <hello@bitwarden.com> (https://bitwarden.com)",
|
||||||
"homepage": "https://bitwarden.com",
|
"homepage": "https://bitwarden.com",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
@@ -12,9 +12,10 @@
|
|||||||
"url": "https://github.com/bitwarden/directory-connector"
|
"url": "https://github.com/bitwarden/directory-connector"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"electron-log": "2.2.17",
|
"browser-hrtime": "^1.1.8",
|
||||||
"electron-store": "1.3.0",
|
"electron-log": "4.3.0",
|
||||||
"electron-updater": "4.2.0",
|
"electron-store": "6.0.1",
|
||||||
"keytar": "4.13.0"
|
"electron-updater": "4.3.5",
|
||||||
|
"keytar": "7.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ export class Program extends BaseProgram {
|
|||||||
.option('--method <method>', 'Two-step login method.')
|
.option('--method <method>', 'Two-step login method.')
|
||||||
.option('--code <code>', 'Two-step login code.')
|
.option('--code <code>', 'Two-step login code.')
|
||||||
.option('--sso', 'Log in with Single-Sign On.')
|
.option('--sso', 'Log in with Single-Sign On.')
|
||||||
|
.option('--passwordenv <variable-name>', 'Read password from the named environment variable.')
|
||||||
|
.option('--passwordfile <filename>', 'Read password from first line of the named file.')
|
||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Notes:');
|
writeLn('\n Notes:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
@@ -94,18 +96,20 @@ export class Program extends BaseProgram {
|
|||||||
writeLn('');
|
writeLn('');
|
||||||
writeLn(' Examples:');
|
writeLn(' Examples:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
writeLn(' bw login');
|
writeLn(' bwdc login');
|
||||||
writeLn(' bw login john@example.com myPassword321');
|
writeLn(' bwdc login john@example.com myPassword321');
|
||||||
writeLn(' bw login john@example.com myPassword321 --method 1 --code 249213');
|
writeLn(' bwdc login john@example.com myPassword321 --method 1 --code 249213');
|
||||||
writeLn(' bw login --sso');
|
writeLn(' bwdc login john@example.com --passwordfile passwd.txt --method 1 --code 249213');
|
||||||
|
writeLn(' bwdc login john@example.com --passwordenv MY_PASSWD --method 1 --code 249213');
|
||||||
|
writeLn(' bwdc login --sso');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (email: string, password: string, cmd: program.Command) => {
|
.action(async (email: string, password: string, options: program.OptionValues) => {
|
||||||
await this.exitIfAuthed();
|
await this.exitIfAuthed();
|
||||||
const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService,
|
const command = new LoginCommand(this.main.authService, this.main.apiService, this.main.i18nService,
|
||||||
this.main.environmentService, this.main.passwordGenerationService, this.main.cryptoFunctionService,
|
this.main.environmentService, this.main.passwordGenerationService, this.main.cryptoFunctionService,
|
||||||
this.main.platformUtilsService, 'connector');
|
this.main.platformUtilsService, 'connector');
|
||||||
const response = await command.run(email, password, cmd);
|
const response = await command.run(email, password, options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,14 +119,14 @@ export class Program extends BaseProgram {
|
|||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Examples:');
|
writeLn('\n Examples:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
writeLn(' bw logout');
|
writeLn(' bwdc logout');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (cmd) => {
|
.action(async () => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
const command = new LogoutCommand(this.main.authService, this.main.i18nService,
|
const command = new LogoutCommand(this.main.authService, this.main.i18nService,
|
||||||
async () => await this.main.logout());
|
async () => await this.main.logout());
|
||||||
const response = await command.run(cmd);
|
const response = await command.run();
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -137,10 +141,10 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc test --last');
|
writeLn(' bwdc test --last');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (cmd) => {
|
.action(async (options: program.OptionValues) => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
const command = new TestCommand(this.main.syncService, this.main.i18nService);
|
const command = new TestCommand(this.main.syncService, this.main.i18nService);
|
||||||
const response = await command.run(cmd);
|
const response = await command.run(options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,10 +157,10 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc sync');
|
writeLn(' bwdc sync');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (cmd) => {
|
.action(async () => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
const command = new SyncCommand(this.main.syncService, this.main.i18nService);
|
const command = new SyncCommand(this.main.syncService, this.main.i18nService);
|
||||||
const response = await command.run(cmd);
|
const response = await command.run();
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -174,16 +178,18 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc last-sync users');
|
writeLn(' bwdc last-sync users');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (object: string, cmd: program.Command) => {
|
.action(async (object: string) => {
|
||||||
await this.exitIfNotAuthed();
|
await this.exitIfNotAuthed();
|
||||||
const command = new LastSyncCommand(this.main.configurationService);
|
const command = new LastSyncCommand(this.main.configurationService);
|
||||||
const response = await command.run(object, cmd);
|
const response = await command.run(object);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('config <setting> <value>')
|
.command('config <setting> [value]')
|
||||||
.description('Configure settings.')
|
.description('Configure settings.')
|
||||||
|
.option('--secretenv <variable-name>', 'Read secret from the named environment variable.')
|
||||||
|
.option('--secretfile <filename>', 'Read secret from first line of the named file.')
|
||||||
.on('--help', () => {
|
.on('--help', () => {
|
||||||
writeLn('\n Settings:');
|
writeLn('\n Settings:');
|
||||||
writeLn('');
|
writeLn('');
|
||||||
@@ -201,16 +207,17 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc config server bitwarden.com');
|
writeLn(' bwdc config server bitwarden.com');
|
||||||
writeLn(' bwdc config directory 1');
|
writeLn(' bwdc config directory 1');
|
||||||
writeLn(' bwdc config ldap.password <password>');
|
writeLn(' bwdc config ldap.password <password>');
|
||||||
|
writeLn(' bwdc config ldap.password --secretenv LDAP_PWD');
|
||||||
writeLn(' bwdc config azure.key <key>');
|
writeLn(' bwdc config azure.key <key>');
|
||||||
writeLn(' bwdc config gsuite.key <key>');
|
writeLn(' bwdc config gsuite.key <key>');
|
||||||
writeLn(' bwdc config okta.token <token>');
|
writeLn(' bwdc config okta.token <token>');
|
||||||
writeLn(' bwdc config onelogin.secret <secret>');
|
writeLn(' bwdc config onelogin.secret <secret>');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (setting, value, cmd) => {
|
.action(async (setting: string, value: string, options: program.OptionValues) => {
|
||||||
const command = new ConfigCommand(this.main.environmentService, this.main.i18nService,
|
const command = new ConfigCommand(this.main.environmentService, this.main.i18nService,
|
||||||
this.main.configurationService);
|
this.main.configurationService);
|
||||||
const response = await command.run(setting, value, cmd);
|
const response = await command.run(setting, value, options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -237,9 +244,9 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc clear-cache');
|
writeLn(' bwdc clear-cache');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (cmd) => {
|
.action(async (options: program.OptionValues) => {
|
||||||
const command = new ClearCacheCommand(this.main.configurationService, this.main.i18nService);
|
const command = new ClearCacheCommand(this.main.configurationService, this.main.i18nService);
|
||||||
const response = await command.run(cmd);
|
const response = await command.run(options);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -259,10 +266,10 @@ export class Program extends BaseProgram {
|
|||||||
writeLn(' bwdc update --raw');
|
writeLn(' bwdc update --raw');
|
||||||
writeLn('', true);
|
writeLn('', true);
|
||||||
})
|
})
|
||||||
.action(async (cmd) => {
|
.action(async () => {
|
||||||
const command = new UpdateCommand(this.main.platformUtilsService, this.main.i18nService,
|
const command = new UpdateCommand(this.main.platformUtilsService, this.main.i18nService,
|
||||||
'directory-connector', 'bwdc', false);
|
'directory-connector', 'bwdc', false);
|
||||||
const response = await command.run(cmd);
|
const response = await command.run();
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { UserEntry } from '../models/userEntry';
|
|||||||
|
|
||||||
import { BaseDirectoryService } from './baseDirectory.service';
|
import { BaseDirectoryService } from './baseDirectory.service';
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
|
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib/abstractions/log.service';
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
@@ -29,7 +29,7 @@ enum UserSetType {
|
|||||||
ExcludeGroup,
|
ExcludeGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AzureDirectoryService extends BaseDirectoryService implements DirectoryService {
|
export class AzureDirectoryService extends BaseDirectoryService implements IDirectoryService {
|
||||||
private client: graph.Client;
|
private client: graph.Client;
|
||||||
private dirConfig: AzureConfiguration;
|
private dirConfig: AzureConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
@@ -68,7 +68,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
|
|
||||||
let groups: GroupEntry[];
|
let groups: GroupEntry[];
|
||||||
if (this.syncConfig.groups) {
|
if (this.syncConfig.groups) {
|
||||||
const setFilter = this.createCustomSet(this.syncConfig.groupFilter);
|
const setFilter = await this.createAadCustomSet(this.syncConfig.groupFilter);
|
||||||
groups = await this.getGroups(setFilter);
|
groups = await this.getGroups(setFilter);
|
||||||
users = this.filterUsersFromGroupsSet(users, groups, setFilter, this.syncConfig);
|
users = this.filterUsersFromGroupsSet(users, groups, setFilter, this.syncConfig);
|
||||||
}
|
}
|
||||||
@@ -170,6 +170,55 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async createAadCustomSet(filter: string): Promise<[boolean, Set<string>]> {
|
||||||
|
if (filter == null || filter === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mainParts = filter.split('|');
|
||||||
|
if (mainParts.length < 1 || mainParts[0] == null || mainParts[0].trim() === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = mainParts[0].split(':');
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keyword = parts[0].trim().toLowerCase();
|
||||||
|
let exclude = true;
|
||||||
|
if (keyword === 'include') {
|
||||||
|
exclude = false;
|
||||||
|
} else if (keyword === 'exclude') {
|
||||||
|
exclude = true;
|
||||||
|
} else if (keyword === 'excludeadministrativeunit') {
|
||||||
|
exclude = true;
|
||||||
|
} else if (keyword === 'includeadministrativeunit') {
|
||||||
|
exclude = false;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const set = new Set<string>();
|
||||||
|
const pieces = parts[1].split(',');
|
||||||
|
if (keyword === 'excludeadministrativeunit' || keyword === 'includeadministrativeunit') {
|
||||||
|
for (const p of pieces) {
|
||||||
|
const auMembers = await this.client
|
||||||
|
.api(`https://graph.microsoft.com/beta/administrativeUnits/${p}/members`).get();
|
||||||
|
for (const auMember of auMembers.value) {
|
||||||
|
if (auMember['@odata.type'] === '#microsoft.graph.group') {
|
||||||
|
set.add(auMember.displayName.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const p of pieces) {
|
||||||
|
set.add(p.trim().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [exclude, set];
|
||||||
|
}
|
||||||
|
|
||||||
private createCustomUserSet(filter: string): [UserSetType, Set<string>] {
|
private createCustomUserSet(filter: string): [UserSetType, Set<string>] {
|
||||||
if (filter == null || filter === '') {
|
if (filter == null || filter === '') {
|
||||||
return null;
|
return null;
|
||||||
@@ -224,7 +273,6 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
return this.filterOutResult([userSetTypeExclude, setFilter[1]], user.email);
|
return this.filterOutResult([userSetTypeExclude, setFilter[1]], user.email);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
const memberGroups = await this.client.api(`/users/${user.externalId}/checkMemberGroups`).post({
|
const memberGroups = await this.client.api(`/users/${user.externalId}/checkMemberGroups`).post({
|
||||||
groupIds: Array.from(setFilter[1]),
|
groupIds: Array.from(setFilter[1]),
|
||||||
});
|
});
|
||||||
@@ -237,7 +285,6 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
} else if (memberGroups.value.length === 0 && setFilter[0] === UserSetType.ExcludeGroup) {
|
} else if (memberGroups.value.length === 0 && setFilter[0] === UserSetType.ExcludeGroup) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} catch { }
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -331,7 +378,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
this.client = graph.Client.init({
|
this.client = graph.Client.init({
|
||||||
authProvider: (done) => {
|
authProvider: done => {
|
||||||
if (this.dirConfig.applicationId == null || this.dirConfig.key == null ||
|
if (this.dirConfig.applicationId == null || this.dirConfig.key == null ||
|
||||||
this.dirConfig.tenant == null) {
|
this.dirConfig.tenant == null) {
|
||||||
done(this.i18nService.t('dirConfigIncomplete'), null);
|
done(this.i18nService.t('dirConfigIncomplete'), null);
|
||||||
@@ -361,7 +408,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
'Content-Length': Buffer.byteLength(data),
|
'Content-Length': Buffer.byteLength(data),
|
||||||
},
|
},
|
||||||
}, (res) => {
|
}, res => {
|
||||||
res.setEncoding('utf8');
|
res.setEncoding('utf8');
|
||||||
res.on('data', (chunk: string) => {
|
res.on('data', (chunk: string) => {
|
||||||
const d = JSON.parse(chunk);
|
const d = JSON.parse(chunk);
|
||||||
@@ -374,7 +421,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements Direc
|
|||||||
done('Unknown error (' + res.statusCode + ').', null);
|
done('Unknown error (' + res.statusCode + ').', null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).on('error', (err) => {
|
}).on('error', err => {
|
||||||
done(err, null);
|
done(err, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export abstract class BaseDirectoryService {
|
|||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
return users.filter((u) => {
|
return users.filter(u => {
|
||||||
if (u.deleted) {
|
if (u.deleted) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -81,11 +81,11 @@ export abstract class BaseDirectoryService {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return groups.filter((g) => g.userMemberExternalIds.has(u.externalId)).length > 0;
|
return groups.filter(g => g.userMemberExternalIds.has(u.externalId)).length > 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected forceGroup(force: boolean, users: UserEntry[]): boolean {
|
protected forceGroup(force: boolean, users: UserEntry[]): boolean {
|
||||||
return force || (users != null && users.filter((u) => !u.deleted && !u.disabled).length > 0);
|
return force || (users != null && users.filter(u => !u.deleted && !u.disabled).length > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { GroupEntry } from '../models/groupEntry';
|
import { GroupEntry } from '../models/groupEntry';
|
||||||
import { UserEntry } from '../models/userEntry';
|
import { UserEntry } from '../models/userEntry';
|
||||||
|
|
||||||
export interface DirectoryService {
|
export interface IDirectoryService {
|
||||||
getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]>;
|
getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import { UserEntry } from '../models/userEntry';
|
|||||||
|
|
||||||
import { BaseDirectoryService } from './baseDirectory.service';
|
import { BaseDirectoryService } from './baseDirectory.service';
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
|
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib/abstractions/log.service';
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
|
|
||||||
export class GSuiteDirectoryService extends BaseDirectoryService implements DirectoryService {
|
export class GSuiteDirectoryService extends BaseDirectoryService implements IDirectoryService {
|
||||||
private client: JWT;
|
private client: JWT;
|
||||||
private service: admin_directory_v1.Admin;
|
private service: admin_directory_v1.Admin;
|
||||||
private authParams: any;
|
private authParams: any;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class KeytarSecureStorageService implements StorageService {
|
|||||||
constructor(private serviceName: string) { }
|
constructor(private serviceName: string) { }
|
||||||
|
|
||||||
get<T>(key: string): Promise<T> {
|
get<T>(key: string): Promise<T> {
|
||||||
return getPassword(this.serviceName, key).then((val) => {
|
return getPassword(this.serviceName, key).then(val => {
|
||||||
return JSON.parse(val) as T;
|
return JSON.parse(val) as T;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { SyncConfiguration } from '../models/syncConfiguration';
|
|||||||
import { UserEntry } from '../models/userEntry';
|
import { UserEntry } from '../models/userEntry';
|
||||||
|
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
|
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib/abstractions/log.service';
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
@@ -18,7 +18,7 @@ import { Utils } from 'jslib/misc/utils';
|
|||||||
|
|
||||||
const UserControlAccountDisabled = 2;
|
const UserControlAccountDisabled = 2;
|
||||||
|
|
||||||
export class LdapDirectoryService implements DirectoryService {
|
export class LdapDirectoryService implements IDirectoryService {
|
||||||
private client: ldap.Client;
|
private client: ldap.Client;
|
||||||
private dirConfig: LdapConfiguration;
|
private dirConfig: LdapConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
@@ -53,7 +53,7 @@ export class LdapDirectoryService implements DirectoryService {
|
|||||||
if (this.syncConfig.groups) {
|
if (this.syncConfig.groups) {
|
||||||
let groupForce = force;
|
let groupForce = force;
|
||||||
if (!groupForce && users != null) {
|
if (!groupForce && users != null) {
|
||||||
const activeUsers = users.filter((u) => !u.deleted && !u.disabled);
|
const activeUsers = users.filter(u => !u.deleted && !u.disabled);
|
||||||
groupForce = activeUsers.length > 0;
|
groupForce = activeUsers.length > 0;
|
||||||
}
|
}
|
||||||
groups = await this.getGroups(groupForce);
|
groups = await this.getGroups(groupForce);
|
||||||
@@ -303,18 +303,18 @@ export class LdapDirectoryService implements DirectoryService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.on('error', (resErr) => {
|
res.on('error', resErr => {
|
||||||
reject(resErr);
|
reject(resErr);
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('searchEntry', (entry) => {
|
res.on('searchEntry', entry => {
|
||||||
const e = processEntry(entry);
|
const e = processEntry(entry);
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
entries.push(e);
|
entries.push(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('end', (result) => {
|
res.on('end', result => {
|
||||||
resolve(entries);
|
resolve(entries);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -381,7 +381,7 @@ export class LdapDirectoryService implements DirectoryService {
|
|||||||
if (err != null) {
|
if (err != null) {
|
||||||
reject(err.message);
|
reject(err.message);
|
||||||
} else {
|
} else {
|
||||||
this.client.bind(user, pass, (err2) => {
|
this.client.bind(user, pass, err2 => {
|
||||||
if (err2 != null) {
|
if (err2 != null) {
|
||||||
reject(err2.message);
|
reject(err2.message);
|
||||||
} else {
|
} else {
|
||||||
@@ -391,7 +391,7 @@ export class LdapDirectoryService implements DirectoryService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.client.bind(user, pass, (err) => {
|
this.client.bind(user, pass, err => {
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
reject(err.message);
|
reject(err.message);
|
||||||
} else {
|
} else {
|
||||||
@@ -404,7 +404,7 @@ export class LdapDirectoryService implements DirectoryService {
|
|||||||
|
|
||||||
private async unbind(): Promise<any> {
|
private async unbind(): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.client.unbind((err) => {
|
this.client.unbind(err => {
|
||||||
if (err != null) {
|
if (err != null) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
29
src/services/lowdbStorage.service.ts
Normal file
29
src/services/lowdbStorage.service.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import * as lock from 'proper-lockfile';
|
||||||
|
|
||||||
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
|
|
||||||
|
import { LowdbStorageService as LowdbStorageServiceBase } from 'jslib/services/lowdbStorage.service';
|
||||||
|
|
||||||
|
import { Utils } from 'jslib/misc/utils';
|
||||||
|
|
||||||
|
export class LowdbStorageService extends LowdbStorageServiceBase {
|
||||||
|
constructor(logService: LogService, defaults?: any, dir?: string, allowCache = false, private requireLock = false) {
|
||||||
|
super(logService, defaults, dir, allowCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async lockDbFile<T>(action: () => T): Promise<T> {
|
||||||
|
if (this.requireLock && !Utils.isNullOrWhitespace(this.dataFilePath)) {
|
||||||
|
this.logService.info('acquiring db file lock');
|
||||||
|
return await lock.lock(this.dataFilePath, { retries: 3 }).then(release => {
|
||||||
|
try {
|
||||||
|
return action();
|
||||||
|
} finally {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return action();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,14 +7,14 @@ import { UserEntry } from '../models/userEntry';
|
|||||||
|
|
||||||
import { BaseDirectoryService } from './baseDirectory.service';
|
import { BaseDirectoryService } from './baseDirectory.service';
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
|
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib/abstractions/log.service';
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
|
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
|
|
||||||
export class OktaDirectoryService extends BaseDirectoryService implements DirectoryService {
|
export class OktaDirectoryService extends BaseDirectoryService implements IDirectoryService {
|
||||||
private dirConfig: OktaConfiguration;
|
private dirConfig: OktaConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ export class OktaDirectoryService extends BaseDirectoryService implements Direct
|
|||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
}
|
}
|
||||||
// throttle some to avoid rate limiting
|
// throttle some to avoid rate limiting
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return entries;
|
return entries;
|
||||||
@@ -164,7 +164,7 @@ export class OktaDirectoryService extends BaseDirectoryService implements Direct
|
|||||||
|
|
||||||
private async apiGetCall(url: string): Promise<[any, Map<string, string | string[]>]> {
|
private async apiGetCall(url: string): Promise<[any, Map<string, string | string[]>]> {
|
||||||
const u = new URL(url);
|
const u = new URL(url);
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
https.get({
|
https.get({
|
||||||
hostname: u.hostname,
|
hostname: u.hostname,
|
||||||
path: u.pathname + u.search,
|
path: u.pathname + u.search,
|
||||||
@@ -173,10 +173,10 @@ export class OktaDirectoryService extends BaseDirectoryService implements Direct
|
|||||||
Authorization: 'SSWS ' + this.dirConfig.token,
|
Authorization: 'SSWS ' + this.dirConfig.token,
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
},
|
},
|
||||||
}, (res) => {
|
}, res => {
|
||||||
let body = '';
|
let body = '';
|
||||||
|
|
||||||
res.on('data', (chunk) => {
|
res.on('data', chunk => {
|
||||||
body += chunk;
|
body += chunk;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { UserEntry } from '../models/userEntry';
|
|||||||
|
|
||||||
import { BaseDirectoryService } from './baseDirectory.service';
|
import { BaseDirectoryService } from './baseDirectory.service';
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
|
|
||||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||||
import { LogService } from 'jslib/abstractions/log.service';
|
import { LogService } from 'jslib/abstractions/log.service';
|
||||||
@@ -15,7 +15,7 @@ import { LogService } from 'jslib/abstractions/log.service';
|
|||||||
// Basic email validation: something@something.something
|
// Basic email validation: something@something.something
|
||||||
const ValidEmailRegex = /^\S+@\S+\.\S+$/;
|
const ValidEmailRegex = /^\S+@\S+\.\S+$/;
|
||||||
|
|
||||||
export class OneLoginDirectoryService extends BaseDirectoryService implements DirectoryService {
|
export class OneLoginDirectoryService extends BaseDirectoryService implements IDirectoryService {
|
||||||
private dirConfig: OneLoginConfiguration;
|
private dirConfig: OneLoginConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
private accessToken: string;
|
private accessToken: string;
|
||||||
@@ -72,7 +72,7 @@ export class OneLoginDirectoryService extends BaseDirectoryService implements Di
|
|||||||
const setFilter = this.createCustomSet(this.syncConfig.userFilter);
|
const setFilter = this.createCustomSet(this.syncConfig.userFilter);
|
||||||
this.logService.info('Querying users.');
|
this.logService.info('Querying users.');
|
||||||
this.allUsers = await this.apiGetMany('users' + (query != null ? '?' + query : ''));
|
this.allUsers = await this.apiGetMany('users' + (query != null ? '?' + query : ''));
|
||||||
this.allUsers.forEach((user) => {
|
this.allUsers.forEach(user => {
|
||||||
const entry = this.buildUser(user);
|
const entry = this.buildUser(user);
|
||||||
if (entry != null && !this.filterOutResult(setFilter, entry.email)) {
|
if (entry != null && !this.filterOutResult(setFilter, entry.email)) {
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
@@ -109,7 +109,7 @@ export class OneLoginDirectoryService extends BaseDirectoryService implements Di
|
|||||||
const query = this.createDirectoryQuery(this.syncConfig.groupFilter);
|
const query = this.createDirectoryQuery(this.syncConfig.groupFilter);
|
||||||
this.logService.info('Querying groups.');
|
this.logService.info('Querying groups.');
|
||||||
const roles = await this.apiGetMany('roles' + (query != null ? '?' + query : ''));
|
const roles = await this.apiGetMany('roles' + (query != null ? '?' + query : ''));
|
||||||
roles.forEach((role) => {
|
roles.forEach(role => {
|
||||||
const entry = this.buildGroup(role);
|
const entry = this.buildGroup(role);
|
||||||
if (entry != null && !this.filterOutResult(setFilter, entry.name)) {
|
if (entry != null && !this.filterOutResult(setFilter, entry.name)) {
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
@@ -125,7 +125,7 @@ export class OneLoginDirectoryService extends BaseDirectoryService implements Di
|
|||||||
entry.name = group.name;
|
entry.name = group.name;
|
||||||
|
|
||||||
if (this.allUsers != null) {
|
if (this.allUsers != null) {
|
||||||
this.allUsers.forEach((user) => {
|
this.allUsers.forEach(user => {
|
||||||
if (user.role_id != null && user.role_id.indexOf(entry.referenceId) > -1) {
|
if (user.role_id != null && user.role_id.indexOf(entry.referenceId) > -1) {
|
||||||
entry.userMemberExternalIds.add(user.id);
|
entry.userMemberExternalIds.add(user.id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { Utils } from 'jslib/misc/utils';
|
|||||||
|
|
||||||
import { AzureDirectoryService } from './azure-directory.service';
|
import { AzureDirectoryService } from './azure-directory.service';
|
||||||
import { ConfigurationService } from './configuration.service';
|
import { ConfigurationService } from './configuration.service';
|
||||||
import { DirectoryService } from './directory.service';
|
import { IDirectoryService } from './directory.service';
|
||||||
import { GSuiteDirectoryService } from './gsuite-directory.service';
|
import { GSuiteDirectoryService } from './gsuite-directory.service';
|
||||||
import { LdapDirectoryService } from './ldap-directory.service';
|
import { LdapDirectoryService } from './ldap-directory.service';
|
||||||
import { OktaDirectoryService } from './okta-directory.service';
|
import { OktaDirectoryService } from './okta-directory.service';
|
||||||
@@ -104,7 +104,7 @@ export class SyncService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private filterUnsupportedUsers(users: UserEntry[]): UserEntry[] {
|
private filterUnsupportedUsers(users: UserEntry[]): UserEntry[] {
|
||||||
return users == null ? null : users.filter((u) => u.email == null || u.email.length <= 50);
|
return users == null ? null : users.filter(u => u.email == null || u.email.length <= 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
private flattenUsersToGroups(levelGroups: GroupEntry[], allGroups: GroupEntry[]): Set<string> {
|
private flattenUsersToGroups(levelGroups: GroupEntry[], allGroups: GroupEntry[]): Set<string> {
|
||||||
@@ -113,15 +113,15 @@ export class SyncService {
|
|||||||
return allUsers;
|
return allUsers;
|
||||||
}
|
}
|
||||||
for (const group of levelGroups) {
|
for (const group of levelGroups) {
|
||||||
const childGroups = allGroups.filter((g) => group.groupMemberReferenceIds.has(g.referenceId));
|
const childGroups = allGroups.filter(g => group.groupMemberReferenceIds.has(g.referenceId));
|
||||||
const childUsers = this.flattenUsersToGroups(childGroups, allGroups);
|
const childUsers = this.flattenUsersToGroups(childGroups, allGroups);
|
||||||
childUsers.forEach((id) => group.userMemberExternalIds.add(id));
|
childUsers.forEach(id => group.userMemberExternalIds.add(id));
|
||||||
allUsers = new Set([...allUsers, ...group.userMemberExternalIds]);
|
allUsers = new Set([...allUsers, ...group.userMemberExternalIds]);
|
||||||
}
|
}
|
||||||
return allUsers;
|
return allUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDirectoryService(): DirectoryService {
|
private getDirectoryService(): IDirectoryService {
|
||||||
switch (this.dirType) {
|
switch (this.dirType) {
|
||||||
case DirectoryType.GSuite:
|
case DirectoryType.GSuite:
|
||||||
return new GSuiteDirectoryService(this.configurationService, this.logService, this.i18nService);
|
return new GSuiteDirectoryService(this.configurationService, this.logService, this.i18nService);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"target": "ES2016",
|
"target": "ES2016",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
"types": [],
|
"types": [],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
23
tslint.json
23
tslint.json
@@ -49,6 +49,27 @@
|
|||||||
"check-separator",
|
"check-separator",
|
||||||
"check-type"
|
"check-type"
|
||||||
],
|
],
|
||||||
"max-classes-per-file": false
|
"max-classes-per-file": false,
|
||||||
|
"ordered-imports": true,
|
||||||
|
"arrow-parens": [
|
||||||
|
true,
|
||||||
|
"ban-single-arg-parens"
|
||||||
|
],
|
||||||
|
"semicolon": [
|
||||||
|
true,
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"trailing-comma": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"multiline": {
|
||||||
|
"objects": "always",
|
||||||
|
"arrays": "always",
|
||||||
|
"functions": "ignore",
|
||||||
|
"typeLiterals": "ignore"
|
||||||
|
},
|
||||||
|
"singleline": "never"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user