mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-15 07:43:27 +00:00
Compare commits
49 Commits
v2024.10.0
...
feat/disab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d35783fad3 | ||
|
|
cb099f902b | ||
|
|
cf54858cc5 | ||
|
|
6cc022b135 | ||
|
|
a8a4390624 | ||
|
|
f9d817f0b1 | ||
|
|
112bda1137 | ||
|
|
e92cb355bd | ||
|
|
23713d92fa | ||
|
|
6ebc9631aa | ||
|
|
e8579f11d3 | ||
|
|
6b2c7a5f00 | ||
|
|
2a1a5bf064 | ||
|
|
1464d72b27 | ||
|
|
f5cbd8f03d | ||
|
|
fdbbef68c1 | ||
|
|
efb412684d | ||
|
|
79f7a2b495 | ||
|
|
4342734412 | ||
|
|
62f14e5043 | ||
|
|
c2b22518fe | ||
|
|
37c992f16b | ||
|
|
69156677ac | ||
|
|
aaed7b13ea | ||
|
|
096d2a03ab | ||
|
|
bd5bcbebd9 | ||
|
|
bb9ece6078 | ||
|
|
40de47e6e3 | ||
|
|
094ed57e03 | ||
|
|
96a38e2d76 | ||
|
|
9e200c8705 | ||
|
|
ca945318ed | ||
|
|
04abed9251 | ||
|
|
9b08ca6db8 | ||
|
|
0cbe6e9d33 | ||
|
|
dda6dd99ed | ||
|
|
5492466276 | ||
|
|
ef571ec0c3 | ||
|
|
f2bea1b6d7 | ||
|
|
07a1ae6dea | ||
|
|
f23997dd72 | ||
|
|
18547d6eaa | ||
|
|
c3a4f25160 | ||
|
|
e57a52e483 | ||
|
|
ff1380ee67 | ||
|
|
2269b82e7e | ||
|
|
8ab3516377 | ||
|
|
91dfd7e0b7 | ||
|
|
6db28408e6 |
70
.github/workflows/build.yml
vendored
70
.github/workflows/build.yml
vendored
@@ -5,6 +5,8 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
|
- "rc"
|
||||||
|
- "hotfix-rc"
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -13,7 +15,7 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up CLOC
|
- name: Set up CLOC
|
||||||
run: |
|
run: |
|
||||||
@@ -31,7 +33,7 @@ jobs:
|
|||||||
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
package_version: ${{ steps.retrieve-version.outputs.package_version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Get Package Version
|
- name: Get Package Version
|
||||||
id: retrieve-version
|
id: retrieve-version
|
||||||
@@ -50,10 +52,10 @@ jobs:
|
|||||||
_PKG_FETCH_VERSION: 3.4
|
_PKG_FETCH_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -121,14 +123,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Linux Zip to GitHub
|
- name: Upload Linux Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Linux checksum to GitHub
|
- name: Upload Linux checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -145,10 +147,10 @@ jobs:
|
|||||||
_PKG_FETCH_VERSION: 3.4
|
_PKG_FETCH_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -209,14 +211,14 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload Mac Zip to GitHub
|
- name: Upload Mac Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Mac checksum to GitHub
|
- name: Upload Mac checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -232,7 +234,7 @@ jobs:
|
|||||||
_WIN_PKG_VERSION: 3.4
|
_WIN_PKG_VERSION: 3.4
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Setup Windows builder
|
- name: Setup Windows builder
|
||||||
run: |
|
run: |
|
||||||
@@ -240,7 +242,7 @@ jobs:
|
|||||||
choco install reshack --no-progress
|
choco install reshack --no-progress
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -353,14 +355,14 @@ jobs:
|
|||||||
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
-t sha256 | Out-File ./dist-cli/bwdc-windows-sha256-${env:_PACKAGE_VERSION}.txt
|
||||||
|
|
||||||
- name: Upload Windows Zip to GitHub
|
- name: Upload Windows Zip to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
name: bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Windows checksum to GitHub
|
- name: Upload Windows checksum to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
|
||||||
@@ -377,10 +379,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -413,28 +415,28 @@ jobs:
|
|||||||
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
SIGNING_CERT_NAME: ${{ secrets.SIGNING_CERT_NAME }}
|
||||||
|
|
||||||
- name: Upload Portable Executable to GitHub
|
- name: Upload Portable Executable to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Installer Executable to GitHub
|
- name: Upload Installer Executable to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload Installer Executable Blockmap to GitHub
|
- name: Upload Installer Executable Blockmap to GitHub
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||||
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: latest.yml
|
name: latest.yml
|
||||||
path: ./dist/latest.yml
|
path: ./dist/latest.yml
|
||||||
@@ -451,10 +453,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -481,14 +483,14 @@ jobs:
|
|||||||
run: npm run dist:lin
|
run: npm run dist:lin
|
||||||
|
|
||||||
- name: Upload AppImage
|
- name: Upload AppImage
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: latest-linux.yml
|
name: latest-linux.yml
|
||||||
path: ./dist/latest-linux.yml
|
path: ./dist/latest-linux.yml
|
||||||
@@ -505,10 +507,10 @@ jobs:
|
|||||||
HUSKY: 0
|
HUSKY: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -575,7 +577,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Install Node dependencies
|
- name: Install Node dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Set up private auth key
|
- name: Set up private auth key
|
||||||
run: |
|
run: |
|
||||||
mkdir ~/private_keys
|
mkdir ~/private_keys
|
||||||
@@ -592,28 +594,28 @@ jobs:
|
|||||||
CSC_FOR_PULL_REQUEST: true
|
CSC_FOR_PULL_REQUEST: true
|
||||||
|
|
||||||
- name: Upload .zip artifact
|
- name: Upload .zip artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload .dmg artifact
|
- name: Upload .dmg artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload .dmg Blockmap artifact
|
- name: Upload .dmg Blockmap artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||||
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
- name: Upload latest auto-update artifact
|
- name: Upload latest auto-update artifact
|
||||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||||
with:
|
with:
|
||||||
name: latest-mac.yml
|
name: latest-mac.yml
|
||||||
path: ./dist/latest-mac.yml
|
path: ./dist/latest-mac.yml
|
||||||
@@ -634,7 +636,11 @@ jobs:
|
|||||||
- macos-gui
|
- macos-gui
|
||||||
steps:
|
steps:
|
||||||
- name: Check if any job failed
|
- name: Check if any job failed
|
||||||
if: github.ref == 'refs/heads/main' && contains(needs.*.result, 'failure')
|
if: |
|
||||||
|
(github.ref == 'refs/heads/main'
|
||||||
|
|| github.ref == 'refs/heads/rc'
|
||||||
|
|| github.ref == 'refs/heads/hotfix-rc')
|
||||||
|
&& contains(needs.*.result, 'failure')
|
||||||
run: exit 1
|
run: exit 1
|
||||||
|
|
||||||
- name: Login to Azure - CI subscription
|
- name: Login to Azure - CI subscription
|
||||||
|
|||||||
11
.github/workflows/integration-test.yml
vendored
11
.github/workflows/integration-test.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repo
|
- name: Check out repo
|
||||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Get Node version
|
- name: Get Node version
|
||||||
id: retrieve-node-version
|
id: retrieve-node-version
|
||||||
@@ -58,7 +58,7 @@ jobs:
|
|||||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -88,13 +88,10 @@ jobs:
|
|||||||
fail-on-error: true
|
fail-on-error: true
|
||||||
|
|
||||||
- name: Upload coverage to codecov.io
|
- name: Upload coverage to codecov.io
|
||||||
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
- name: Upload results to codecov.io
|
- name: Upload results to codecov.io
|
||||||
uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
|
uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|||||||
22
.github/workflows/release.yml
vendored
22
.github/workflows/release.yml
vendored
@@ -18,17 +18,17 @@ jobs:
|
|||||||
name: Setup
|
name: Setup
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
outputs:
|
outputs:
|
||||||
release-version: ${{ steps.version.outputs.version }}
|
release_version: ${{ steps.version.outputs.version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Branch check
|
- name: Branch check
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then
|
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
echo "[!] Can only release from the 'main' branch"
|
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
|
||||||
echo "==================================="
|
echo "==================================="
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@main
|
uses: bitwarden/gh-actions/release-version-check@main
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ inputs.release_type }}
|
||||||
project-type: ts
|
project-type: ts
|
||||||
file: package.json
|
file: package.json
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
needs: setup
|
needs: setup
|
||||||
steps:
|
steps:
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@main
|
uses: bitwarden/gh-actions/download-artifacts@main
|
||||||
with:
|
with:
|
||||||
workflow: build.yml
|
workflow: build.yml
|
||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
branch: ${{ github.ref_name }}
|
branch: ${{ github.ref_name }}
|
||||||
|
|
||||||
- name: Dry Run - Download all artifacts
|
- name: Dry Run - Download all artifacts
|
||||||
if: ${{ github.event.inputs.release_type == 'Dry Run' }}
|
if: ${{ inputs.release_type == 'Dry Run' }}
|
||||||
uses: bitwarden/gh-actions/download-artifacts@main
|
uses: bitwarden/gh-actions/download-artifacts@main
|
||||||
with:
|
with:
|
||||||
workflow: build.yml
|
workflow: build.yml
|
||||||
@@ -63,10 +63,10 @@ jobs:
|
|||||||
branch: main
|
branch: main
|
||||||
|
|
||||||
- name: Create release
|
- name: Create release
|
||||||
if: ${{ github.event.inputs.release_type != 'Dry Run' }}
|
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||||
uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0
|
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
|
||||||
env:
|
env:
|
||||||
PKG_VERSION: ${{ needs.setup.outputs.release-version }}
|
PKG_VERSION: ${{ needs.setup.outputs.release_version }}
|
||||||
with:
|
with:
|
||||||
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
|
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
|
||||||
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
|
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
|
||||||
|
|||||||
11
.github/workflows/scan.yml
vendored
11
.github/workflows/scan.yml
vendored
@@ -24,12 +24,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repo
|
- name: Check out repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: Scan with Checkmarx
|
- name: Scan with Checkmarx
|
||||||
uses: checkmarx/ast-github-action@ed196cdaec9cd1bc5aacac4ca2010dd773b20893 # 2.0.35
|
uses: checkmarx/ast-github-action@184bf2f64f55d1c93fd6636d539edf274703e434 # 2.0.41
|
||||||
env:
|
env:
|
||||||
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
|
INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}"
|
||||||
with:
|
with:
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
--output-path . ${{ env.INCREMENTAL }}
|
--output-path . ${{ env.INCREMENTAL }}
|
||||||
|
|
||||||
- name: Upload Checkmarx results to GitHub
|
- name: Upload Checkmarx results to GitHub
|
||||||
uses: github/codeql-action/upload-sarif@e2b3eafc8d227b0241d48be5f425d47c2d750a13 # v3.26.10
|
uses: github/codeql-action/upload-sarif@dd196fa9ce80b6bacc74ca1c32bd5b0ba22efca7 # v3.28.3
|
||||||
with:
|
with:
|
||||||
sarif_file: cx_result.sarif
|
sarif_file: cx_result.sarif
|
||||||
|
|
||||||
@@ -58,16 +58,15 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repo
|
- name: Check out repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
- name: Scan with SonarCloud
|
- name: Scan with SonarCloud
|
||||||
uses: sonarsource/sonarcloud-github-action@eb211723266fe8e83102bac7361f0a05c3ac1d1b # v3.0.0
|
uses: sonarsource/sonarqube-scan-action@bfd4e558cda28cda6b5defafb9232d191be8c203 # v4.2.1
|
||||||
env:
|
env:
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
with:
|
||||||
args: >
|
args: >
|
||||||
-Dsonar.organization=${{ github.repository_owner }}
|
-Dsonar.organization=${{ github.repository_owner }}
|
||||||
|
|||||||
13
.github/workflows/test.yml
vendored
13
.github/workflows/test.yml
vendored
@@ -5,6 +5,8 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "main"
|
||||||
|
- "rc"
|
||||||
|
- "hotfix-rc"
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -38,7 +40,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repo
|
- name: Check out repo
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Get Node version
|
- name: Get Node version
|
||||||
id: retrieve-node-version
|
id: retrieve-node-version
|
||||||
@@ -48,7 +50,7 @@ jobs:
|
|||||||
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
echo "node_version=$NODE_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Node
|
- name: Set up Node
|
||||||
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: '**/package-lock.json'
|
cache-dependency-path: '**/package-lock.json'
|
||||||
@@ -76,13 +78,10 @@ jobs:
|
|||||||
fail-on-error: true
|
fail-on-error: true
|
||||||
|
|
||||||
- name: Upload coverage to codecov.io
|
- name: Upload coverage to codecov.io
|
||||||
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
|
uses: codecov/codecov-action@5a605bd92782ce0810fa3b8acc235c921b497052 # v5.2.0
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
- name: Upload results to codecov.io
|
- name: Upload results to codecov.io
|
||||||
uses: codecov/test-results-action@1b5b448b98e58ba90d1a1a1d9fcb72ca2263be46 # v1.0.0
|
uses: codecov/test-results-action@4e79e65778be1cecd5df25e14af1eafb6df80ea9 # v1.0.2
|
||||||
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
if: ${{ needs.check-test-secrets.outputs.available == 'true' }}
|
||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|||||||
112
.github/workflows/version-bump.yml
vendored
112
.github/workflows/version-bump.yml
vendored
@@ -7,17 +7,11 @@ on:
|
|||||||
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
|
description: "New version override (leave blank for automatic calculation, example: '2024.1.0')"
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
enable_slack_notification:
|
|
||||||
description: "Enable Slack notifications for upcoming release?"
|
|
||||||
default: false
|
|
||||||
type: boolean
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
bump_version:
|
bump_version:
|
||||||
name: Bump Version
|
name: Bump Version
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
outputs:
|
|
||||||
version: ${{ steps.set-final-version-output.outputs.version }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Validate version input
|
- name: Validate version input
|
||||||
if: ${{ inputs.version_number_override != '' }}
|
if: ${{ inputs.version_number_override != '' }}
|
||||||
@@ -25,49 +19,22 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
version: ${{ inputs.version_number_override }}
|
version: ${{ inputs.version_number_override }}
|
||||||
|
|
||||||
- name: Slack Notification Check
|
- name: Generate GH App token
|
||||||
run: |
|
uses: actions/create-github-app-token@c1a285145b9d317df6ced56c09f525b5c2b6f755 # v1.11.1
|
||||||
if [[ "${{ inputs.enable_slack_notification }}" == true ]]; then
|
id: app-token
|
||||||
echo "Slack notifications enabled."
|
with:
|
||||||
else
|
app-id: ${{ secrets.BW_GHAPP_ID }}
|
||||||
echo "Slack notifications disabled."
|
private-key: ${{ secrets.BW_GHAPP_KEY }}
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Checkout Branch
|
- name: Checkout Branch
|
||||||
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
|
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: Login to Azure - CI Subscription
|
|
||||||
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
|
|
||||||
with:
|
with:
|
||||||
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
token: ${{ steps.app-token.outputs.token }}
|
||||||
|
|
||||||
- name: Retrieve secrets
|
|
||||||
id: retrieve-secrets
|
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
|
||||||
with:
|
|
||||||
keyvault: "bitwarden-ci"
|
|
||||||
secrets: "github-gpg-private-key,
|
|
||||||
github-gpg-private-key-passphrase"
|
|
||||||
|
|
||||||
- name: Import GPG key
|
|
||||||
uses: crazy-max/ghaction-import-gpg@01dd5d3ca463c7f10f7f4f7b4f177225ac661ee4 # v6.1.0
|
|
||||||
with:
|
|
||||||
gpg_private_key: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key }}
|
|
||||||
passphrase: ${{ steps.retrieve-secrets.outputs.github-gpg-private-key-passphrase }}
|
|
||||||
git_user_signingkey: true
|
|
||||||
git_commit_gpgsign: true
|
|
||||||
|
|
||||||
- name: Setup git
|
- name: Setup git
|
||||||
run: |
|
run: |
|
||||||
git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
|
git config user.name github-actions
|
||||||
git config --local user.name "bitwarden-devops-bot"
|
git config user.email github-actions@github.com
|
||||||
|
|
||||||
- name: Create Version Branch
|
|
||||||
id: create-branch
|
|
||||||
run: |
|
|
||||||
NAME=version_bump_${{ github.ref_name }}_$(date +"%Y-%m-%d")
|
|
||||||
git switch -c $NAME
|
|
||||||
echo "name=$NAME" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Get current version
|
- name: Get current version
|
||||||
id: current-version
|
id: current-version
|
||||||
@@ -144,61 +111,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Push changes
|
- name: Push changes
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
||||||
env:
|
run: git push
|
||||||
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
|
|
||||||
run: git push -u origin $PR_BRANCH
|
|
||||||
|
|
||||||
- name: Generate GH App token
|
|
||||||
uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
|
|
||||||
id: app-token
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.BW_GHAPP_ID }}
|
|
||||||
private-key: ${{ secrets.BW_GHAPP_KEY }}
|
|
||||||
owner: ${{ github.repository_owner }}
|
|
||||||
|
|
||||||
- name: Create Version PR
|
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
|
||||||
id: create-pr
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
||||||
PR_BRANCH: ${{ steps.create-branch.outputs.name }}
|
|
||||||
TITLE: "Bump version to ${{ steps.set-final-version-output.outputs.version }}"
|
|
||||||
run: |
|
|
||||||
PR_URL=$(gh pr create --title "$TITLE" \
|
|
||||||
--base "main" \
|
|
||||||
--head "$PR_BRANCH" \
|
|
||||||
--label "version update" \
|
|
||||||
--label "automated pr" \
|
|
||||||
--body "
|
|
||||||
## Type of change
|
|
||||||
- [ ] Bug fix
|
|
||||||
- [ ] New feature development
|
|
||||||
- [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc)
|
|
||||||
- [ ] Build/deploy pipeline (DevOps)
|
|
||||||
- [X] Other
|
|
||||||
|
|
||||||
## Objective
|
|
||||||
Automated version bump to ${{ steps.set-final-version-output.outputs.version }}")
|
|
||||||
echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Approve PR
|
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
|
||||||
run: gh pr review $PR_NUMBER --approve
|
|
||||||
|
|
||||||
- name: Merge PR
|
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }}
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
||||||
PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }}
|
|
||||||
run: gh pr merge $PR_NUMBER --squash --auto --delete-branch
|
|
||||||
|
|
||||||
- name: Report upcoming release version to Slack
|
|
||||||
if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' && inputs.enable_slack_notification == true }}
|
|
||||||
uses: bitwarden/gh-actions/report-upcoming-release-version@main
|
|
||||||
with:
|
|
||||||
version: ${{ steps.set-final-version-output.outputs.version }}
|
|
||||||
project: ${{ github.repository }}
|
|
||||||
AZURE_KV_CI_SERVICE_PRINCIPAL: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# Bitwarden Directory Connector
|
# Bitwarden Directory Connector
|
||||||
|
|
||||||
The Bitwarden Directory Connector is a a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups.
|
The Bitwarden Directory Connector is a desktop application used to sync your Bitwarden enterprise organization to an existing directory of users and groups.
|
||||||
|
|
||||||
Supported directories:
|
Supported directories:
|
||||||
|
|
||||||
|
|||||||
1190
package-lock.json
generated
1190
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
69
package.json
69
package.json
@@ -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": "2024.10.0",
|
"version": "2025.1.1",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"bitwarden",
|
"bitwarden",
|
||||||
"password",
|
"password",
|
||||||
@@ -73,68 +73,67 @@
|
|||||||
"test:types": "npx tsc --noEmit"
|
"test:types": "npx tsc --noEmit"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "17.3.10",
|
"@angular-devkit/build-angular": "17.3.11",
|
||||||
"@angular-eslint/eslint-plugin-template": "17.5.3",
|
"@angular-eslint/eslint-plugin-template": "17.5.3",
|
||||||
"@angular-eslint/template-parser": "17.5.3",
|
"@angular-eslint/template-parser": "17.5.3",
|
||||||
"@angular/compiler-cli": "17.3.12",
|
"@angular/compiler-cli": "17.3.12",
|
||||||
"@electron/notarize": "2.2.1",
|
"@electron/notarize": "2.5.0",
|
||||||
"@electron/rebuild": "3.6.0",
|
"@electron/rebuild": "3.7.1",
|
||||||
"@fluffy-spoon/substitute": "1.208.0",
|
"@fluffy-spoon/substitute": "1.208.0",
|
||||||
"@microsoft/microsoft-graph-types": "2.40.0",
|
"@microsoft/microsoft-graph-types": "2.40.0",
|
||||||
"@ngtools/webpack": "17.3.10",
|
"@ngtools/webpack": "17.3.11",
|
||||||
"@types/inquirer": "8.2.10",
|
"@types/inquirer": "8.2.10",
|
||||||
"@types/jest": "29.5.13",
|
"@types/jest": "29.5.14",
|
||||||
"@types/ldapjs": "2.2.5",
|
|
||||||
"@types/lowdb": "1.0.15",
|
"@types/lowdb": "1.0.15",
|
||||||
"@types/node": "20.16.10",
|
"@types/node": "20.17.14",
|
||||||
"@types/node-fetch": "2.6.11",
|
"@types/node-fetch": "2.6.12",
|
||||||
"@types/node-forge": "1.3.11",
|
"@types/node-forge": "1.3.11",
|
||||||
"@types/proper-lockfile": "4.1.4",
|
"@types/proper-lockfile": "4.1.4",
|
||||||
"@types/tldjs": "2.3.4",
|
"@types/tldjs": "2.3.4",
|
||||||
"@typescript-eslint/eslint-plugin": "5.62.0",
|
"@typescript-eslint/eslint-plugin": "8.19.0",
|
||||||
"@typescript-eslint/parser": "5.62.0",
|
"@typescript-eslint/parser": "8.19.0",
|
||||||
"clean-webpack-plugin": "4.0.0",
|
"clean-webpack-plugin": "4.0.0",
|
||||||
"concurrently": "9.0.1",
|
"concurrently": "9.1.0",
|
||||||
"copy-webpack-plugin": "12.0.2",
|
"copy-webpack-plugin": "12.0.2",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"css-loader": "7.1.2",
|
"css-loader": "7.1.2",
|
||||||
"dotenv": "16.4.5",
|
"dotenv": "16.4.7",
|
||||||
"electron": "28.3.3",
|
"electron": "32.1.1",
|
||||||
"electron-builder": "24.13.3",
|
"electron-builder": "24.13.3",
|
||||||
"electron-log": "5.2.0",
|
"electron-log": "5.2.4",
|
||||||
"electron-reload": "2.0.0-alpha.1",
|
"electron-reload": "2.0.0-alpha.1",
|
||||||
"electron-store": "8.2.0",
|
"electron-store": "8.2.0",
|
||||||
"electron-updater": "6.3.4",
|
"electron-updater": "6.3.9",
|
||||||
"eslint": "8.57.1",
|
"eslint": "8.57.1",
|
||||||
"eslint-config-prettier": "9.1.0",
|
"eslint-config-prettier": "9.1.0",
|
||||||
"eslint-import-resolver-typescript": "3.6.3",
|
"eslint-import-resolver-typescript": "3.7.0",
|
||||||
"eslint-plugin-import": "2.30.0",
|
"eslint-plugin-import": "2.31.0",
|
||||||
"eslint-plugin-rxjs": "5.0.3",
|
"eslint-plugin-rxjs": "5.0.3",
|
||||||
"eslint-plugin-rxjs-angular": "2.0.1",
|
"eslint-plugin-rxjs-angular": "2.0.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.1",
|
||||||
"html-loader": "5.1.0",
|
"html-loader": "5.1.0",
|
||||||
"html-webpack-plugin": "5.6.0",
|
"html-webpack-plugin": "5.6.3",
|
||||||
"husky": "9.1.6",
|
"husky": "9.1.7",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-junit": "16.0.0",
|
"jest-junit": "16.0.0",
|
||||||
"jest-mock-extended": "3.0.7",
|
"jest-mock-extended": "3.0.7",
|
||||||
"jest-preset-angular": "14.2.4",
|
"jest-preset-angular": "14.5.0",
|
||||||
"lint-staged": "15.2.10",
|
"lint-staged": "15.4.1",
|
||||||
"mini-css-extract-plugin": "2.9.1",
|
"mini-css-extract-plugin": "2.9.2",
|
||||||
"node-forge": "1.3.1",
|
"node-forge": "1.3.1",
|
||||||
"node-loader": "2.0.0",
|
"node-loader": "2.1.0",
|
||||||
"pkg": "5.8.1",
|
"pkg": "5.8.1",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.4.2",
|
||||||
"rimraf": "5.0.10",
|
"rimraf": "6.0.1",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"sass": "1.79.4",
|
"sass": "1.79.4",
|
||||||
"sass-loader": "16.0.2",
|
"sass-loader": "16.0.4",
|
||||||
"ts-jest": "29.2.5",
|
"ts-jest": "29.2.5",
|
||||||
"ts-loader": "9.5.1",
|
"ts-loader": "9.5.1",
|
||||||
"tsconfig-paths-webpack-plugin": "4.1.0",
|
"tsconfig-paths-webpack-plugin": "4.2.0",
|
||||||
"type-fest": "4.26.1",
|
"type-fest": "4.32.0",
|
||||||
"typescript": "5.4.5",
|
"typescript": "5.4.5",
|
||||||
"typescript-transform-paths": "3.5.1",
|
"typescript-transform-paths": "3.5.2",
|
||||||
"webpack": "5.95.0",
|
"webpack": "5.95.0",
|
||||||
"webpack-cli": "5.1.4",
|
"webpack-cli": "5.1.4",
|
||||||
"webpack-merge": "6.0.1",
|
"webpack-merge": "6.0.1",
|
||||||
@@ -158,15 +157,15 @@
|
|||||||
"chalk": "4.1.2",
|
"chalk": "4.1.2",
|
||||||
"commander": "12.1.0",
|
"commander": "12.1.0",
|
||||||
"core-js": "3.38.1",
|
"core-js": "3.38.1",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.1",
|
||||||
"google-auth-library": "7.14.1",
|
"google-auth-library": "7.14.1",
|
||||||
"googleapis": "73.0.0",
|
"googleapis": "73.0.0",
|
||||||
"https-proxy-agent": "7.0.5",
|
"https-proxy-agent": "7.0.6",
|
||||||
"inquirer": "8.2.6",
|
"inquirer": "8.2.6",
|
||||||
"keytar": "7.9.0",
|
"keytar": "7.9.0",
|
||||||
"ldapjs": "2.3.3",
|
"ldapts": "7.3.1",
|
||||||
"lowdb": "1.0.0",
|
"lowdb": "1.0.0",
|
||||||
"ngx-toastr": "17.0.2",
|
"ngx-toastr": "19.0.0",
|
||||||
"node-fetch": "2.7.0",
|
"node-fetch": "2.7.0",
|
||||||
"proper-lockfile": "4.1.2",
|
"proper-lockfile": "4.1.2",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ export class GSuiteDirectoryService extends BaseDirectoryService implements IDir
|
|||||||
entry.referenceId = user.id;
|
entry.referenceId = user.id;
|
||||||
entry.externalId = user.id;
|
entry.externalId = user.id;
|
||||||
entry.email = user.primaryEmail != null ? user.primaryEmail.trim().toLowerCase() : null;
|
entry.email = user.primaryEmail != null ? user.primaryEmail.trim().toLowerCase() : null;
|
||||||
entry.disabled = user.suspended || false;
|
entry.disabled = user.suspended || user.archived || false;
|
||||||
entry.deleted = deleted;
|
entry.deleted = deleted;
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { checkServerIdentity, PeerCertificate } from "tls";
|
import * as tls from "tls";
|
||||||
|
|
||||||
import * as ldap from "ldapjs";
|
import * as ldapts from "ldapts";
|
||||||
|
|
||||||
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
|
||||||
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
import { LogService } from "@/jslib/common/src/abstractions/log.service";
|
||||||
@@ -18,8 +18,13 @@ import { IDirectoryService } from "./directory.service";
|
|||||||
|
|
||||||
const UserControlAccountDisabled = 2;
|
const UserControlAccountDisabled = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attribute name for the unique identifier used by Active Directory.
|
||||||
|
*/
|
||||||
|
const ActiveDirectoryExternalId = "objectGUID";
|
||||||
|
|
||||||
export class LdapDirectoryService implements IDirectoryService {
|
export class LdapDirectoryService implements IDirectoryService {
|
||||||
private client: ldap.Client;
|
private client: ldapts.Client;
|
||||||
private dirConfig: LdapConfiguration;
|
private dirConfig: LdapConfiguration;
|
||||||
private syncConfig: SyncConfiguration;
|
private syncConfig: SyncConfiguration;
|
||||||
|
|
||||||
@@ -48,21 +53,25 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
await this.bind();
|
await this.bind();
|
||||||
|
|
||||||
let users: UserEntry[];
|
let users: UserEntry[];
|
||||||
if (this.syncConfig.users) {
|
|
||||||
users = await this.getUsers(force, test);
|
|
||||||
}
|
|
||||||
|
|
||||||
let groups: GroupEntry[];
|
let groups: GroupEntry[];
|
||||||
if (this.syncConfig.groups) {
|
|
||||||
let groupForce = force;
|
try {
|
||||||
if (!groupForce && users != null) {
|
if (this.syncConfig.users) {
|
||||||
const activeUsers = users.filter((u) => !u.deleted && !u.disabled);
|
users = await this.getUsers(force, test);
|
||||||
groupForce = activeUsers.length > 0;
|
|
||||||
}
|
}
|
||||||
groups = await this.getGroups(groupForce);
|
|
||||||
|
if (this.syncConfig.groups) {
|
||||||
|
let groupForce = force;
|
||||||
|
if (!groupForce && users != null) {
|
||||||
|
const activeUsers = users.filter((u) => !u.deleted && !u.disabled);
|
||||||
|
groupForce = activeUsers.length > 0;
|
||||||
|
}
|
||||||
|
groups = await this.getGroups(groupForce);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await this.client.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.unbind();
|
|
||||||
return [groups, users];
|
return [groups, users];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,10 +110,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
const deletedPath = this.makeSearchPath("CN=Deleted Objects");
|
const deletedPath = this.makeSearchPath("CN=Deleted Objects");
|
||||||
this.logService.info("Deleted user search: " + deletedPath + " => " + deletedFilter);
|
this.logService.info("Deleted user search: " + deletedPath + " => " + deletedFilter);
|
||||||
|
|
||||||
const delControl = new (ldap as any).Control({
|
const delControl = new ldapts.Control("1.2.840.113556.1.4.417", { critical: true });
|
||||||
type: "1.2.840.113556.1.4.417",
|
|
||||||
criticality: true,
|
|
||||||
});
|
|
||||||
const deletedUsers = await this.search<UserEntry>(
|
const deletedUsers = await this.search<UserEntry>(
|
||||||
deletedPath,
|
deletedPath,
|
||||||
deletedFilter,
|
deletedFilter,
|
||||||
@@ -120,7 +126,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
|
|
||||||
private buildUser(searchEntry: any, deleted: boolean): UserEntry {
|
private buildUser(searchEntry: any, deleted: boolean): UserEntry {
|
||||||
const user = new UserEntry();
|
const user = new UserEntry();
|
||||||
user.referenceId = searchEntry.objectName;
|
user.referenceId = this.getReferenceId(searchEntry);
|
||||||
user.deleted = deleted;
|
user.deleted = deleted;
|
||||||
|
|
||||||
if (user.referenceId == null) {
|
if (user.referenceId == null) {
|
||||||
@@ -172,7 +178,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
let groupSearchEntries: any[] = [];
|
let groupSearchEntries: any[] = [];
|
||||||
const initialSearchGroupIds = await this.search<string>(path, filter, (se: any) => {
|
const initialSearchGroupIds = await this.search<string>(path, filter, (se: any) => {
|
||||||
groupSearchEntries.push(se);
|
groupSearchEntries.push(se);
|
||||||
return se.objectName;
|
return this.getReferenceId(se);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (searchSinceRevision && initialSearchGroupIds.length === 0) {
|
if (searchSinceRevision && initialSearchGroupIds.length === 0) {
|
||||||
@@ -188,7 +194,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
const userPath = this.makeSearchPath(this.syncConfig.userPath);
|
const userPath = this.makeSearchPath(this.syncConfig.userPath);
|
||||||
const userIdMap = new Map<string, string>();
|
const userIdMap = new Map<string, string>();
|
||||||
await this.search<string>(userPath, userFilter, (se: any) => {
|
await this.search<string>(userPath, userFilter, (se: any) => {
|
||||||
userIdMap.set(se.objectName, this.getExternalId(se, se.objectName));
|
userIdMap.set(this.getReferenceId(se), this.getExternalId(se, this.getReferenceId(se)));
|
||||||
return se;
|
return se;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -204,7 +210,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
|
|
||||||
private buildGroup(searchEntry: any, userMap: Map<string, string>) {
|
private buildGroup(searchEntry: any, userMap: Map<string, string>) {
|
||||||
const group = new GroupEntry();
|
const group = new GroupEntry();
|
||||||
group.referenceId = searchEntry.objectName;
|
group.referenceId = this.getReferenceId(searchEntry);
|
||||||
if (group.referenceId == null) {
|
if (group.referenceId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -220,7 +226,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const members = this.getAttrVals(searchEntry, this.syncConfig.memberAttribute);
|
const members = this.getAttrVals<string>(searchEntry, this.syncConfig.memberAttribute);
|
||||||
if (members != null) {
|
if (members != null) {
|
||||||
for (const memDn of members) {
|
for (const memDn of members) {
|
||||||
if (userMap.has(memDn) && !group.userMemberExternalIds.has(userMap.get(memDn))) {
|
if (userMap.has(memDn) && !group.userMemberExternalIds.has(userMap.get(memDn))) {
|
||||||
@@ -234,15 +240,26 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getExternalId(searchEntry: any, referenceId: string) {
|
/**
|
||||||
const attrObj = this.getAttrObj(searchEntry, "objectGUID");
|
* The externalId is the "objectGUID" property if present (a unique identifier used by Active Directory),
|
||||||
if (attrObj != null && attrObj._vals != null && attrObj._vals.length > 0) {
|
* otherwise it falls back to the provided referenceId.
|
||||||
return this.bufToGuid(attrObj._vals[0]);
|
*/
|
||||||
|
private getExternalId(searchEntry: ldapts.Entry, referenceId: string) {
|
||||||
|
const attr = this.getAttr<Buffer>(searchEntry, ActiveDirectoryExternalId);
|
||||||
|
if (attr != null) {
|
||||||
|
return this.bufToGuid(attr);
|
||||||
} else {
|
} else {
|
||||||
return referenceId;
|
return referenceId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the object's reference id (dn)
|
||||||
|
*/
|
||||||
|
private getReferenceId(entry: ldapts.Entry): string {
|
||||||
|
return entry.dn;
|
||||||
|
}
|
||||||
|
|
||||||
private buildBaseFilter(objectClass: string, subFilter: string): string {
|
private buildBaseFilter(objectClass: string, subFilter: string): string {
|
||||||
let filter = this.buildObjectClassFilter(objectClass);
|
let filter = this.buildObjectClassFilter(objectClass);
|
||||||
if (subFilter != null && subFilter.trim() !== "") {
|
if (subFilter != null && subFilter.trim() !== "") {
|
||||||
@@ -281,42 +298,48 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAttrObj(searchEntry: any, attr: string): any {
|
/**
|
||||||
if (searchEntry == null || searchEntry.attributes == null) {
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all values for an ldap attribute
|
||||||
|
* @param searchEntry The ldap entry
|
||||||
|
* @param attr An attribute name on the ldap entry
|
||||||
|
* @returns An array containing all values of the attribute, or null if there are no values
|
||||||
|
*/
|
||||||
|
private getAttrVals<T extends string | Buffer>(
|
||||||
|
searchEntry: ldapts.Entry,
|
||||||
|
attr: string,
|
||||||
|
): T[] | null {
|
||||||
|
if (searchEntry == null || searchEntry[attr] == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const attrs = searchEntry.attributes.filter((a: any) => a.type === attr);
|
const vals = searchEntry[attr];
|
||||||
if (
|
if (!Array.isArray(vals)) {
|
||||||
attrs == null ||
|
return [vals] as T[];
|
||||||
attrs.length === 0 ||
|
|
||||||
attrs[0].vals == null ||
|
|
||||||
attrs[0].vals.length === 0
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return attrs[0];
|
return vals as T[];
|
||||||
}
|
}
|
||||||
|
|
||||||
private getAttrVals(searchEntry: any, attr: string): string[] {
|
/**
|
||||||
const obj = this.getAttrObj(searchEntry, attr);
|
* Get the first value for an ldap attribute
|
||||||
if (obj == null) {
|
* @param searchEntry The ldap entry
|
||||||
return null;
|
* @param attr An attribute name on the ldap entry
|
||||||
}
|
* @returns The first value of the attribute, or null if there is not at least 1 value
|
||||||
return obj.vals;
|
*/
|
||||||
}
|
private getAttr<T extends string | Buffer>(searchEntry: ldapts.Entry, attr: string): T {
|
||||||
|
|
||||||
private getAttr(searchEntry: any, attr: string): string {
|
|
||||||
const vals = this.getAttrVals(searchEntry, attr);
|
const vals = this.getAttrVals(searchEntry, attr);
|
||||||
if (vals == null) {
|
if (vals == null || vals.length < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return vals[0];
|
|
||||||
|
return vals[0] as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
private entryDisabled(searchEntry: any): boolean {
|
private entryDisabled(searchEntry: any): boolean {
|
||||||
const c = this.getAttr(searchEntry, "userAccountControl");
|
const c = this.getAttr<string>(searchEntry, "userAccountControl");
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
try {
|
try {
|
||||||
const control = parseInt(c, null);
|
const control = parseInt(c, null);
|
||||||
@@ -333,145 +356,106 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
private async search<T>(
|
private async search<T>(
|
||||||
path: string,
|
path: string,
|
||||||
filter: string,
|
filter: string,
|
||||||
processEntry: (searchEntry: any) => T,
|
processEntry: (searchEntry: ldapts.Entry) => T,
|
||||||
controls: ldap.Control[] = [],
|
controls: ldapts.Control[] = [],
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
const options: ldap.SearchOptions = {
|
const options: ldapts.SearchOptions = {
|
||||||
filter: filter,
|
filter: filter,
|
||||||
scope: "sub",
|
scope: "sub",
|
||||||
paged: this.dirConfig.pagedSearch,
|
paged: this.dirConfig.pagedSearch,
|
||||||
|
// We need to expressly tell ldapts what attributes to return as Buffer objects,
|
||||||
|
// otherwise they are returned as strings
|
||||||
|
explicitBufferAttributes: [ActiveDirectoryExternalId],
|
||||||
};
|
};
|
||||||
const entries: T[] = [];
|
const { searchEntries } = await this.client.search(path, options, controls);
|
||||||
return new Promise<T[]>((resolve, reject) => {
|
return searchEntries.map((e) => processEntry(e)).filter((e) => e != null);
|
||||||
this.client.search(path, options, controls, (err, res) => {
|
|
||||||
if (err != null) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.on("error", (resErr) => {
|
|
||||||
reject(resErr);
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("searchEntry", (entry) => {
|
|
||||||
const e = processEntry(entry);
|
|
||||||
if (e != null) {
|
|
||||||
entries.push(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
res.on("end", (result) => {
|
|
||||||
resolve(entries);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async bind(): Promise<any> {
|
private async bind(): Promise<any> {
|
||||||
return new Promise<void>((resolve, reject) => {
|
if (this.dirConfig.hostname == null || this.dirConfig.port == null) {
|
||||||
if (this.dirConfig.hostname == null || this.dirConfig.port == null) {
|
throw new Error(this.i18nService.t("dirConfigIncomplete"));
|
||||||
reject(this.i18nService.t("dirConfigIncomplete"));
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
const protocol = "ldap" + (this.dirConfig.ssl && !this.dirConfig.startTls ? "s" : "");
|
|
||||||
const url = protocol + "://" + this.dirConfig.hostname + ":" + this.dirConfig.port;
|
|
||||||
const options: ldap.ClientOptions = {
|
|
||||||
url: url.trim().toLowerCase(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const tlsOptions: any = {};
|
const protocol = this.dirConfig.ssl && !this.dirConfig.startTls ? "ldaps" : "ldap";
|
||||||
if (this.dirConfig.ssl) {
|
|
||||||
if (this.dirConfig.sslAllowUnauthorized) {
|
|
||||||
tlsOptions.rejectUnauthorized = !this.dirConfig.sslAllowUnauthorized;
|
|
||||||
}
|
|
||||||
if (!this.dirConfig.startTls) {
|
|
||||||
if (
|
|
||||||
this.dirConfig.sslCaPath != null &&
|
|
||||||
this.dirConfig.sslCaPath !== "" &&
|
|
||||||
fs.existsSync(this.dirConfig.sslCaPath)
|
|
||||||
) {
|
|
||||||
tlsOptions.ca = [fs.readFileSync(this.dirConfig.sslCaPath)];
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
this.dirConfig.sslCertPath != null &&
|
|
||||||
this.dirConfig.sslCertPath !== "" &&
|
|
||||||
fs.existsSync(this.dirConfig.sslCertPath)
|
|
||||||
) {
|
|
||||||
tlsOptions.cert = fs.readFileSync(this.dirConfig.sslCertPath);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
this.dirConfig.sslKeyPath != null &&
|
|
||||||
this.dirConfig.sslKeyPath !== "" &&
|
|
||||||
fs.existsSync(this.dirConfig.sslKeyPath)
|
|
||||||
) {
|
|
||||||
tlsOptions.key = fs.readFileSync(this.dirConfig.sslKeyPath);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
this.dirConfig.tlsCaPath != null &&
|
|
||||||
this.dirConfig.tlsCaPath !== "" &&
|
|
||||||
fs.existsSync(this.dirConfig.tlsCaPath)
|
|
||||||
) {
|
|
||||||
tlsOptions.ca = [fs.readFileSync(this.dirConfig.tlsCaPath)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsOptions.checkServerIdentity = this.checkServerIdentityAltNames;
|
const url = protocol + "://" + this.dirConfig.hostname + ":" + this.dirConfig.port;
|
||||||
options.tlsOptions = tlsOptions;
|
const options: ldapts.ClientOptions = {
|
||||||
|
url: url.trim().toLowerCase(),
|
||||||
|
};
|
||||||
|
|
||||||
this.client = ldap.createClient(options);
|
// If using ldaps, TLS options are given to the client constructor
|
||||||
|
if (protocol === "ldaps") {
|
||||||
|
options.tlsOptions = this.buildTlsOptions();
|
||||||
|
}
|
||||||
|
|
||||||
const user =
|
this.client = new ldapts.Client(options);
|
||||||
this.dirConfig.username == null || this.dirConfig.username.trim() === ""
|
|
||||||
? null
|
|
||||||
: this.dirConfig.username;
|
|
||||||
const pass =
|
|
||||||
this.dirConfig.password == null || this.dirConfig.password.trim() === ""
|
|
||||||
? null
|
|
||||||
: this.dirConfig.password;
|
|
||||||
|
|
||||||
if (user == null || pass == null) {
|
const user =
|
||||||
reject(this.i18nService.t("usernamePasswordNotConfigured"));
|
this.dirConfig.username == null || this.dirConfig.username.trim() === ""
|
||||||
return;
|
? null
|
||||||
}
|
: this.dirConfig.username;
|
||||||
|
const pass =
|
||||||
|
this.dirConfig.password == null || this.dirConfig.password.trim() === ""
|
||||||
|
? null
|
||||||
|
: this.dirConfig.password;
|
||||||
|
|
||||||
if (this.dirConfig.startTls && this.dirConfig.ssl) {
|
if (user == null || pass == null) {
|
||||||
this.client.starttls(options.tlsOptions, undefined, (err, res) => {
|
throw new Error(this.i18nService.t("usernamePasswordNotConfigured"));
|
||||||
if (err != null) {
|
}
|
||||||
reject(err.message);
|
|
||||||
} else {
|
// If using StartTLS, TLS options are given to the StartTLS call
|
||||||
this.client.bind(user, pass, (err2) => {
|
if (this.dirConfig.startTls && this.dirConfig.ssl) {
|
||||||
if (err2 != null) {
|
await this.client.startTLS(this.buildTlsOptions());
|
||||||
reject(err2.message);
|
}
|
||||||
} else {
|
|
||||||
resolve();
|
try {
|
||||||
}
|
await this.client.bind(user, pass);
|
||||||
});
|
} catch {
|
||||||
}
|
await this.client.unbind();
|
||||||
});
|
}
|
||||||
} else {
|
|
||||||
this.client.bind(user, pass, (err) => {
|
|
||||||
if (err != null) {
|
|
||||||
reject(err.message);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async unbind(): Promise<void> {
|
private buildTlsOptions(): tls.ConnectionOptions {
|
||||||
return new Promise((resolve, reject) => {
|
const tlsOptions: tls.ConnectionOptions = {};
|
||||||
this.client.unbind((err) => {
|
|
||||||
if (err != null) {
|
if (this.dirConfig.sslAllowUnauthorized) {
|
||||||
reject(err);
|
tlsOptions.rejectUnauthorized = !this.dirConfig.sslAllowUnauthorized;
|
||||||
} else {
|
}
|
||||||
resolve();
|
if (!this.dirConfig.startTls) {
|
||||||
}
|
if (
|
||||||
});
|
this.dirConfig.sslCaPath != null &&
|
||||||
});
|
this.dirConfig.sslCaPath !== "" &&
|
||||||
|
fs.existsSync(this.dirConfig.sslCaPath)
|
||||||
|
) {
|
||||||
|
tlsOptions.ca = [fs.readFileSync(this.dirConfig.sslCaPath)];
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.dirConfig.sslCertPath != null &&
|
||||||
|
this.dirConfig.sslCertPath !== "" &&
|
||||||
|
fs.existsSync(this.dirConfig.sslCertPath)
|
||||||
|
) {
|
||||||
|
tlsOptions.cert = fs.readFileSync(this.dirConfig.sslCertPath);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.dirConfig.sslKeyPath != null &&
|
||||||
|
this.dirConfig.sslKeyPath !== "" &&
|
||||||
|
fs.existsSync(this.dirConfig.sslKeyPath)
|
||||||
|
) {
|
||||||
|
tlsOptions.key = fs.readFileSync(this.dirConfig.sslKeyPath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
this.dirConfig.tlsCaPath != null &&
|
||||||
|
this.dirConfig.tlsCaPath !== "" &&
|
||||||
|
fs.existsSync(this.dirConfig.tlsCaPath)
|
||||||
|
) {
|
||||||
|
tlsOptions.ca = [fs.readFileSync(this.dirConfig.tlsCaPath)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsOptions.checkServerIdentity = this.checkServerIdentityAltNames;
|
||||||
|
|
||||||
|
return tlsOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bufToGuid(buf: Buffer) {
|
private bufToGuid(buf: Buffer) {
|
||||||
@@ -494,7 +478,7 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
return guid.toLowerCase();
|
return guid.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkServerIdentityAltNames(host: string, cert: PeerCertificate) {
|
private checkServerIdentityAltNames(host: string, cert: tls.PeerCertificate) {
|
||||||
// Fixes the cert representation when subject is empty and altNames are present
|
// Fixes the cert representation when subject is empty and altNames are present
|
||||||
// Required for node versions < 12.14.1 (which could be used for bwdc cli)
|
// Required for node versions < 12.14.1 (which could be used for bwdc cli)
|
||||||
// Adapted from: https://github.com/auth0/ad-ldap-connector/commit/1f4dd2be6ed93dda591dd31ed5483a9b452a8d2a
|
// Adapted from: https://github.com/auth0/ad-ldap-connector/commit/1f4dd2be6ed93dda591dd31ed5483a9b452a8d2a
|
||||||
@@ -510,6 +494,6 @@ export class LdapDirectoryService implements IDirectoryService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkServerIdentity(host, cert);
|
return tls.checkServerIdentity(host, cert);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user