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

Compare commits

...

31 Commits

Author SHA1 Message Date
Thomas Rittson
e2bf699573 Split build and release workflows for gui and cli 2025-07-08 12:22:14 +10:00
Jared McCannon
284206b735 [PM-32177] - Fixing Backward Compatibility with Azure AD (#813)
* Updating the fetching of the config and key to check entra and check azure afterwards.

* Making this camelCase to match other values.
2025-07-02 08:20:56 -05:00
renovate[bot]
51042857c9 [deps]: Update lint-staged to v16 (#789)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 22:24:34 -05:00
renovate[bot]
a462ae7457 [deps]: Update commander to v14 (#786)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:55:43 -05:00
renovate[bot]
5dfd60d25c [deps]: Update jest-mock-extended to v4 (#810)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:42:59 -05:00
renovate[bot]
19937fcbe9 [deps]: Update ldapts to v8 (#788)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:33:32 -05:00
renovate[bot]
46405ad75c [deps]: Update jest-preset-angular to v14.6.0 (#800)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:28:43 -05:00
renovate[bot]
04ee7533e4 [deps]: Update core-js to v3.43.0 (#799)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:26:43 -05:00
renovate[bot]
02aa653a48 [deps]: Update typescript-eslint monorepo to v8.35.0 (#802)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:24:36 -05:00
renovate[bot]
921466677e [deps]: Update parse5 to v7.3.0 (#801)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 21:21:11 -05:00
renovate[bot]
e8f0d17944 [deps]: Update electron to v34.5.8 (#750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-02 09:30:01 +10:00
renovate[bot]
2cc2292ed6 [deps]: Update webpack to v5.99.9 (#762)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 13:58:12 +10:00
renovate[bot]
c96e0bb147 [deps]: Update copy-webpack-plugin to v13 (#766)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 13:47:54 +10:00
renovate[bot]
6964a7db49 [deps]: Update bootstrap to v5.3.7 (#743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 12:05:17 +10:00
renovate[bot]
32e3327974 [deps]: Update sass to v1.89.2 (#646)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-01 11:48:05 +10:00
Vincent Salucci
3a46e1781e chore: bump version to v2025.6.1 (#812) 2025-06-30 14:08:03 -05:00
Jared McCannon
dc64f7191e [PM-21187] Rename Azure AD to Entra ID (#797)
* Changed label to entraID

* Performed rename of Azure AD to Entra ID

* Added check to maintain backward compatibility.

* Swapping Azure for Entra

* one last spot

* Adding property for the data.json for backward compatibility.

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>

* Removing unneeded setting using the old azure property.

* Accidentally removed. Adding entra back in.

* Adding backward compatibility comment. Added here because it's required for SecureStorageKeys

* Adding backward compatibility comments.

* Fixing comment

* Removing unused fields.

---------

Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2025-06-27 08:28:04 -05:00
renovate[bot]
570bcf1581 [deps]: Update ts-jest to v29.4.0 (#759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-26 14:49:56 +01:00
renovate[bot]
fc06bf401a [deps]: Update electron-log to v5.4.1 (#751)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-26 14:41:01 +01:00
Andy Pixley
61d7c996c1 [BRE-848] Adding Workflow Permissions (#798) 2025-06-23 11:14:00 -05:00
renovate[bot]
71a19fecaa [deps]: Update sass-loader to v16.0.5 (#747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:51:51 +01:00
renovate[bot]
ae37cea276 [deps]: Update form-data to v4.0.3 (#744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:47:48 +01:00
renovate[bot]
09f1f6981c [deps]: Update @electron/rebuild to v3.7.2 (#741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:43:57 +01:00
Vince Grassia
ceff0559f2 Remove checksum assets from releases (#795) 2025-06-12 12:06:11 -04:00
Matt Andreko
4d55bf0527 Added explicit permissions to check-run (#794) 2025-06-09 14:55:48 -04:00
renovate[bot]
7347c1992f [deps]: Update sonarsource/sonarqube-scan-action action to v5 (#790)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 14:29:32 -04:00
Brandon Treston
46d2797d8c Lock file maintenance (#791)
* [deps]: Lock file maintenance

* wip deps

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 10:04:15 -04:00
Vincent Salucci
ed58d7c758 chore: bump verstion to v2025.6.0 (#793) 2025-06-02 11:17:31 -05:00
renovate[bot]
cd6bbd792a [deps]: Update node-abi to v3.75.0 (#779)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 09:52:51 -05:00
Rui Tomé
3b3ea8ac47 [PM-15456] Update AzureDirectoryService to dynamically select Graph API endpoint based on identity authority (public or government) (#777)
Co-authored-by: bnagawiecki <107435978+bnagawiecki@users.noreply.github.com>
2025-06-02 14:00:07 +01:00
Matt Andreko
5f9adf9ab7 fix: update scan workflow (#792) 2025-06-02 08:28:33 -04:00
21 changed files with 1773 additions and 1475 deletions

View File

@@ -1,4 +1,4 @@
name: Build
name: Build CLI
on:
pull_request: {}
@@ -9,6 +9,9 @@ on:
- "hotfix-rc"
workflow_dispatch: {}
permissions:
contents: read
jobs:
cloc:
name: CLOC
@@ -95,11 +98,6 @@ jobs:
- name: Zip
run: zip -j dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip dist-cli/linux/bwdc keytar/linux/build/Release/keytar.node
- name: Create checksums
run: |
shasum -a 256 dist-cli/bwdc-linux-$_PACKAGE_VERSION.zip | \
cut -d " " -f 1 > dist-cli/bwdc-linux-sha256-$_PACKAGE_VERSION.txt
- name: Version Test
run: |
sudo apt-get update
@@ -129,13 +127,6 @@ jobs:
path: ./dist-cli/bwdc-linux-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Linux checksum to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-linux-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
macos-cli:
name: Build Mac CLI
@@ -190,11 +181,6 @@ jobs:
- name: Zip
run: zip -j dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip dist-cli/macos/bwdc keytar/macos/build/Release/keytar.node
- name: Create checksums
run: |
shasum -a 256 dist-cli/bwdc-macos-$_PACKAGE_VERSION.zip | \
cut -d " " -f 1 > dist-cli/bwdc-macos-sha256-$_PACKAGE_VERSION.txt
- name: Version Test
run: |
mkdir -p test/macos
@@ -217,12 +203,6 @@ jobs:
path: ./dist-cli/bwdc-macos-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Mac checksum to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-macos-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
windows-cli:
name: Build Windows CLI
@@ -349,11 +329,6 @@ jobs:
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
- name: Upload Windows Zip to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
@@ -361,283 +336,6 @@ jobs:
path: ./dist-cli/bwdc-windows-${{ env._PACKAGE_VERSION }}.zip
if-no-files-found: error
- name: Upload Windows checksum to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
path: ./dist-cli/bwdc-windows-sha256-${{ env._PACKAGE_VERSION }}.txt
if-no-files-found: error
windows-gui:
name: Build Windows GUI
runs-on: windows-2022
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
- name: Install AST
run: dotnet tool install --global AzureSignTool --version 4.0.1
- name: Install Node dependencies
run: npm install
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "code-signing-vault-url,
code-signing-client-id,
code-signing-tenant-id,
code-signing-client-secret,
code-signing-cert-name"
- name: Build & Sign
run: npm run dist:win
env:
ELECTRON_BUILDER_SIGN: 1
SIGNING_VAULT_URL: ${{ steps.retrieve-secrets.outputs.code-signing-vault-url }}
SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-client-id }}
SIGNING_TENANT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-tenant-id }}
SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets.outputs.code-signing-client-secret }}
SIGNING_CERT_NAME: ${{ steps.retrieve-secrets.outputs.code-signing-cert-name }}
- name: Upload Portable Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable Blockmap to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest.yml
path: ./dist/latest.yml
if-no-files-found: error
linux-gui:
name: Build Linux GUI
runs-on: ubuntu-24.04
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- 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: NPM Install
run: npm install
- name: NPM Rebuild
run: npm run rebuild
- name: NPM Package
run: npm run dist:lin
- name: Upload AppImage
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-linux.yml
path: ./dist/latest-linux.yml
if-no-files-found: error
macos-gui:
name: Build MacOS GUI
runs-on: macos-13
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Get certificates
run: |
mkdir -p $HOME/certificates
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Load package version
run: |
$rootPath = $env:GITHUB_WORKSPACE;
$packageVersion = (Get-Content -Raw -Path $rootPath\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;
shell: pwsh
- name: Install Node dependencies
run: npm install
- name: Set up private auth key
run: |
mkdir ~/private_keys
cat << EOF > ~/private_keys/AuthKey_UFD296548T.p8
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
EOF
- name: Build application
run: npm run dist:mac
env:
APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
APP_STORE_CONNECT_AUTH_KEY: UFD296548T
APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_UFD296548T.p8
CSC_FOR_PULL_REQUEST: true
- name: Upload .zip artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
if-no-files-found: error
- name: Upload .dmg artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
if-no-files-found: error
- name: Upload .dmg Blockmap artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-mac.yml
path: ./dist/latest-mac.yml
if-no-files-found: error
check-failures:
name: Check for failures
runs-on: ubuntu-24.04
@@ -647,9 +345,6 @@ jobs:
- linux-cli
- macos-cli
- windows-cli
- windows-gui
- linux-gui
- macos-gui
steps:
- name: Check if any job failed
if: |

354
.github/workflows/build-gui.yml vendored Normal file
View File

@@ -0,0 +1,354 @@
name: Build GUI
on:
pull_request: {}
push:
branches:
- "main"
- "rc"
- "hotfix-rc"
workflow_dispatch: {}
permissions:
contents: read
jobs:
cloc:
name: CLOC
runs-on: ubuntu-24.04
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- 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:
name: Setup
runs-on: ubuntu-24.04
outputs:
package_version: ${{ steps.retrieve-version.outputs.package_version }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Get Package Version
id: retrieve-version
run: |
PKG_VERSION=$(jq -r .version package.json)
echo "package_version=$PKG_VERSION" >> $GITHUB_OUTPUT
windows-gui:
name: Build Windows GUI
runs-on: windows-2022
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
- name: Install AST
run: dotnet tool install --global AzureSignTool --version 4.0.1
- name: Install Node dependencies
run: npm install
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
with:
keyvault: "bitwarden-ci"
secrets: "code-signing-vault-url,
code-signing-client-id,
code-signing-tenant-id,
code-signing-client-secret,
code-signing-cert-name"
- name: Build & Sign
run: npm run dist:win
env:
ELECTRON_BUILDER_SIGN: 1
SIGNING_VAULT_URL: ${{ steps.retrieve-secrets.outputs.code-signing-vault-url }}
SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-client-id }}
SIGNING_TENANT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-tenant-id }}
SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets.outputs.code-signing-client-secret }}
SIGNING_CERT_NAME: ${{ steps.retrieve-secrets.outputs.code-signing-cert-name }}
- name: Upload Portable Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Portable-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe
if-no-files-found: error
- name: Upload Installer Executable Blockmap to GitHub
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
path: ./dist/Bitwarden-Connector-Installer-${{ env._PACKAGE_VERSION }}.exe.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest.yml
path: ./dist/latest.yml
if-no-files-found: error
linux-gui:
name: Build Linux GUI
runs-on: ubuntu-24.04
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- 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: NPM Install
run: npm install
- name: NPM Rebuild
run: npm run rebuild
- name: NPM Package
run: npm run dist:lin
- name: Upload AppImage
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-x86_64.AppImage
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-linux.yml
path: ./dist/latest-linux.yml
if-no-files-found: error
macos-gui:
name: Build MacOS GUI
runs-on: macos-13
needs: setup
env:
NODE_OPTIONS: --max_old_space_size=4096
_PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }}
HUSKY: 0
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
node-version: '18'
- name: Update NPM
run: |
npm install -g node-gyp
node-gyp install $(node -v)
- name: Print environment
run: |
node --version
npm --version
echo "GitHub ref: $GITHUB_REF"
echo "GitHub event: $GITHUB_EVENT"
- name: Login to Azure
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Get certificates
run: |
mkdir -p $HOME/certificates
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-app-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-app-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/devid-installer-cert |
jq -r .value | base64 -d > $HOME/certificates/devid-installer-cert.p12
az keyvault secret show --id https://bitwarden-ci.vault.azure.net/certificates/macdev-cert |
jq -r .value | base64 -d > $HOME/certificates/macdev-cert.p12
- name: Set up keychain
env:
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
security create-keychain -p $KEYCHAIN_PASSWORD build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain
security set-keychain-settings -lut 1200 build.keychain
security import "$HOME/certificates/devid-app-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/devid-installer-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security import "$HOME/certificates/macdev-cert.p12" -k build.keychain -P "" \
-T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain
- name: Load package version
run: |
$rootPath = $env:GITHUB_WORKSPACE;
$packageVersion = (Get-Content -Raw -Path $rootPath\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;
shell: pwsh
- name: Install Node dependencies
run: npm install
- name: Set up private auth key
run: |
mkdir ~/private_keys
cat << EOF > ~/private_keys/AuthKey_UFD296548T.p8
${{ secrets.APP_STORE_CONNECT_AUTH_KEY }}
EOF
- name: Build application
run: npm run dist:mac
env:
APP_STORE_CONNECT_TEAM_ISSUER: ${{ secrets.APP_STORE_CONNECT_TEAM_ISSUER }}
APP_STORE_CONNECT_AUTH_KEY: UFD296548T
APP_STORE_CONNECT_AUTH_KEY_PATH: ~/private_keys/AuthKey_UFD296548T.p8
CSC_FOR_PULL_REQUEST: true
- name: Upload .zip artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}-mac.zip
if-no-files-found: error
- name: Upload .dmg artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg
if-no-files-found: error
- name: Upload .dmg Blockmap artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
path: ./dist/Bitwarden-Connector-${{ env._PACKAGE_VERSION }}.dmg.blockmap
if-no-files-found: error
- name: Upload latest auto-update artifact
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
name: latest-mac.yml
path: ./dist/latest-mac.yml
if-no-files-found: error
check-failures:
name: Check for failures
runs-on: ubuntu-24.04
needs:
- cloc
- setup
- windows-gui
- linux-gui
- macos-gui
steps:
- name: Check if any job failed
if: |
(github.ref == 'refs/heads/main'
|| github.ref == 'refs/heads/rc'
|| github.ref == 'refs/heads/hotfix-rc')
&& contains(needs.*.result, 'failure')
run: exit 1
- name: Login to Azure - CI subscription
uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0
if: failure()
with:
creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }}
- name: Retrieve secrets
id: retrieve-secrets
uses: bitwarden/gh-actions/get-keyvault-secrets@main
if: failure()
with:
keyvault: "bitwarden-ci"
secrets: "devops-alerts-slack-webhook-url"
- name: Notify Slack on failure
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
if: failure()
env:
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
with:
status: ${{ job.status }}

View File

@@ -3,6 +3,9 @@ name: Enforce PR labels
on:
pull_request:
types: [labeled, unlabeled, opened, edited, synchronize]
permissions:
contents: read
pull-requests: read
jobs:
enforce-label:
name: EnforceLabel

83
.github/workflows/release-cli.yml vendored Normal file
View File

@@ -0,0 +1,83 @@
name: Release
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release Options'
required: true
default: 'Initial Release'
type: choice
options:
- Initial Release
- Redeploy
- Dry Run
permissions:
contents: read
jobs:
setup:
name: Setup
runs-on: ubuntu-24.04
outputs:
release_version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Branch check
if: ${{ inputs.release_type != 'Dry Run' }}
run: |
if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then
echo "==================================="
echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches"
echo "==================================="
exit 1
fi
- name: Check Release Version
id: version
uses: bitwarden/gh-actions/release-version-check@main
with:
release-type: ${{ inputs.release_type }}
project-type: ts
file: package.json
release:
name: Release
runs-on: ubuntu-24.04
needs: setup
steps:
- name: Download all artifacts
if: ${{ inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build-cli.yml
workflow_conclusion: success
branch: ${{ github.ref_name }}
- name: Dry Run - Download all artifacts
if: ${{ inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build-cli.yml
workflow_conclusion: success
branch: main
- name: Create release
if: ${{ inputs.release_type != 'Dry Run' }}
uses: ncipollo/release-action@cdcc88a9acf3ca41c16c37bb7d21b9ad48560d87 # v1.15.0
env:
PKG_VERSION: ${{ needs.setup.outputs.release_version }}
with:
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
./bwdc-linux-${{ env.PKG_VERSION }}.zip"
commit: ${{ github.sha }}
tag: v${{ env.PKG_VERSION }}
name: Version ${{ env.PKG_VERSION }}
body: "<insert release notes here>"
token: ${{ secrets.GITHUB_TOKEN }}
draft: true

View File

@@ -1,4 +1,4 @@
name: Release
name: Release GUI
on:
workflow_dispatch:
@@ -13,6 +13,9 @@ on:
- Redeploy
- Dry Run
permissions:
contents: read
jobs:
setup:
name: Setup
@@ -50,7 +53,7 @@ jobs:
if: ${{ inputs.release_type != 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build.yml
workflow: build-gui.yml
workflow_conclusion: success
branch: ${{ github.ref_name }}
@@ -58,7 +61,7 @@ jobs:
if: ${{ inputs.release_type == 'Dry Run' }}
uses: bitwarden/gh-actions/download-artifacts@main
with:
workflow: build.yml
workflow: build-gui.yml
workflow_conclusion: success
branch: main
@@ -68,13 +71,7 @@ jobs:
env:
PKG_VERSION: ${{ needs.setup.outputs.release_version }}
with:
artifacts: "./bwdc-windows-${{ env.PKG_VERSION }}.zip,
./bwdc-macos-${{ env.PKG_VERSION }}.zip,
./bwdc-linux-${{ env.PKG_VERSION }}.zip,
./bwdc-windows-sha256-${{ env.PKG_VERSION }}.txt,
./bwdc-macos-sha256-${{ env.PKG_VERSION }}.txt,
./bwdc-linux-sha256-${{ env.PKG_VERSION }}.txt,
./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe,
artifacts: " ./Bitwarden-Connector-Portable-${{ env.PKG_VERSION }}.exe,
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe,
./Bitwarden-Connector-Installer-${{ env.PKG_VERSION }}.exe.blockmap,
./Bitwarden-Connector-${{ env.PKG_VERSION }}-x86_64.AppImage,

View File

@@ -5,13 +5,23 @@ on:
push:
branches:
- "main"
pull_request:
types: [opened, synchronize, reopened]
branches-ignore:
- main
pull_request_target:
types: [opened, synchronize]
types: [opened, synchronize, reopened]
branches:
- "main"
permissions: {}
jobs:
check-run:
name: Check PR run
uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
permissions:
contents: read
sast:
name: SAST scan
@@ -66,7 +76,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}
- name: Scan with SonarCloud
uses: sonarsource/sonarqube-scan-action@bfd4e558cda28cda6b5defafb9232d191be8c203 # v4.2.1
uses: sonarsource/sonarqube-scan-action@2500896589ef8f7247069a56136f8dc177c27ccf # v5.2.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:

View File

@@ -9,7 +9,7 @@ Supported directories:
- Active Directory
- Any other LDAP-based directory
- Azure Active Directory
- Microsoft Entra ID
- G Suite (Google)
- Okta

2220
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
"name": "@bitwarden/directory-connector",
"productName": "Bitwarden Directory Connector",
"description": "Sync your user directory to your Bitwarden organization.",
"version": "2025.5.0",
"version": "2025.6.1",
"keywords": [
"bitwarden",
"password",
@@ -78,7 +78,7 @@
"@angular-eslint/template-parser": "17.5.3",
"@angular/compiler-cli": "17.3.12",
"@electron/notarize": "2.5.0",
"@electron/rebuild": "3.7.1",
"@electron/rebuild": "3.7.2",
"@fluffy-spoon/substitute": "1.208.0",
"@microsoft/microsoft-graph-types": "2.40.0",
"@ngtools/webpack": "17.3.17",
@@ -90,17 +90,17 @@
"@types/node-forge": "1.3.11",
"@types/proper-lockfile": "4.1.4",
"@types/tldjs": "2.3.4",
"@typescript-eslint/eslint-plugin": "8.32.1",
"@typescript-eslint/parser": "8.32.1",
"@typescript-eslint/eslint-plugin": "8.35.0",
"@typescript-eslint/parser": "8.35.0",
"clean-webpack-plugin": "4.0.0",
"concurrently": "9.1.2",
"copy-webpack-plugin": "12.0.2",
"copy-webpack-plugin": "13.0.0",
"cross-env": "7.0.3",
"css-loader": "7.1.2",
"dotenv": "16.5.0",
"electron": "34.1.1",
"electron": "34.5.8",
"electron-builder": "24.13.3",
"electron-log": "5.2.4",
"electron-log": "5.4.1",
"electron-reload": "2.0.0-alpha.1",
"electron-store": "8.2.0",
"electron-updater": "6.6.2",
@@ -110,31 +110,31 @@
"eslint-plugin-import": "2.31.0",
"eslint-plugin-rxjs": "5.0.3",
"eslint-plugin-rxjs-angular": "2.0.1",
"form-data": "4.0.1",
"form-data": "4.0.3",
"html-loader": "5.1.0",
"html-webpack-plugin": "5.6.3",
"husky": "9.1.7",
"jest": "29.7.0",
"jest-junit": "16.0.0",
"jest-mock-extended": "3.0.7",
"jest-preset-angular": "14.5.5",
"lint-staged": "15.5.2",
"jest-mock-extended": "4.0.0",
"jest-preset-angular": "14.6.0",
"lint-staged": "16.1.2",
"mini-css-extract-plugin": "2.9.2",
"node-abi": "3.74.0",
"node-abi": "3.75.0",
"node-forge": "1.3.1",
"node-loader": "2.1.0",
"pkg": "5.8.1",
"prettier": "3.5.3",
"rimraf": "6.0.1",
"rxjs": "7.8.2",
"sass": "1.79.4",
"sass-loader": "16.0.4",
"ts-jest": "29.2.5",
"sass": "1.89.2",
"sass-loader": "16.0.5",
"ts-jest": "29.4.0",
"ts-loader": "9.5.2",
"tsconfig-paths-webpack-plugin": "4.2.0",
"type-fest": "4.41.0",
"typescript": "5.4.5",
"webpack": "5.97.1",
"webpack": "5.99.9",
"webpack-cli": "6.0.1",
"webpack-merge": "6.0.1",
"webpack-node-externals": "3.0.0",
@@ -152,25 +152,26 @@
"@angular/router": "17.3.12",
"@microsoft/microsoft-graph-client": "3.0.7",
"big-integer": "1.6.52",
"bootstrap": "5.3.3",
"bootstrap": "5.3.7",
"browser-hrtime": "1.1.8",
"chalk": "4.1.2",
"commander": "13.1.0",
"core-js": "3.42.0",
"form-data": "4.0.1",
"commander": "14.0.0",
"core-js": "3.43.0",
"form-data": "4.0.3",
"google-auth-library": "9.15.1",
"googleapis": "144.0.0",
"https-proxy-agent": "7.0.6",
"inquirer": "8.2.6",
"keytar": "7.9.0",
"ldapts": "7.4.0",
"ldapts": "8.0.1",
"lowdb": "1.0.0",
"ngx-toastr": "19.0.0",
"node-fetch": "2.7.0",
"proper-lockfile": "4.1.2",
"rxjs": "7.8.2",
"tldjs": "2.3.1",
"zone.js": "0.14.10"
"zone.js": "0.14.10",
"parse5": "7.3.0"
},
"engines": {
"node": "~22.13.0",

View File

@@ -3,7 +3,7 @@ import { StorageOptions } from "@/jslib/common/src/models/domain/storageOptions"
import { DirectoryType } from "@/src/enums/directoryType";
import { Account } from "@/src/models/account";
import { AzureConfiguration } from "@/src/models/azureConfiguration";
import { EntraIdConfiguration } from "@/src/models/entraIdConfiguration";
import { GSuiteConfiguration } from "@/src/models/gsuiteConfiguration";
import { LdapConfiguration } from "@/src/models/ldapConfiguration";
import { OktaConfiguration } from "@/src/models/oktaConfiguration";
@@ -17,7 +17,7 @@ export abstract class StateService extends BaseStateServiceAbstraction<Account>
config:
| LdapConfiguration
| GSuiteConfiguration
| AzureConfiguration
| EntraIdConfiguration
| OktaConfiguration
| OneLoginConfiguration,
) => Promise<any>;
@@ -25,8 +25,8 @@ export abstract class StateService extends BaseStateServiceAbstraction<Account>
setLdapConfiguration: (value: LdapConfiguration, options?: StorageOptions) => Promise<void>;
getGsuiteConfiguration: (options?: StorageOptions) => Promise<GSuiteConfiguration>;
setGsuiteConfiguration: (value: GSuiteConfiguration, options?: StorageOptions) => Promise<void>;
getAzureConfiguration: (options?: StorageOptions) => Promise<AzureConfiguration>;
setAzureConfiguration: (value: AzureConfiguration, options?: StorageOptions) => Promise<void>;
getEntraConfiguration: (options?: StorageOptions) => Promise<EntraIdConfiguration>;
setEntraConfiguration: (value: EntraIdConfiguration, options?: StorageOptions) => Promise<void>;
getOktaConfiguration: (options?: StorageOptions) => Promise<OktaConfiguration>;
setOktaConfiguration: (value: OktaConfiguration, options?: StorageOptions) => Promise<void>;
getOneLoginConfiguration: (options?: StorageOptions) => Promise<OneLoginConfiguration>;

View File

@@ -242,7 +242,7 @@
</div>
</div>
</div>
<div [hidden]="directory != directoryType.AzureActiveDirectory">
<div [hidden]="directory != directoryType.EntraID">
<div class="mb-3">
<label for="identityAuthority" class="form-label">{{
"identityAuthority" | i18n
@@ -251,10 +251,10 @@
class="form-select"
id="identityAuthority"
name="IdentityAuthority"
[(ngModel)]="azure.identityAuthority"
[(ngModel)]="entra.identityAuthority"
>
<option value="login.microsoftonline.com">Azure AD Public</option>
<option value="login.microsoftonline.us">Azure AD Government</option>
<option value="login.microsoftonline.com">Entra Id Public</option>
<option value="login.microsoftonline.us">Entra Id Government</option>
</select>
</div>
<div class="mb-3">
@@ -264,7 +264,7 @@
class="form-control"
id="tenant"
name="Tenant"
[(ngModel)]="azure.tenant"
[(ngModel)]="entra.tenant"
/>
<div class="form-text">{{ "ex" | i18n }} companyad.onmicrosoft.com</div>
</div>
@@ -275,29 +275,29 @@
class="form-control"
id="applicationId"
name="ApplicationId"
[(ngModel)]="azure.applicationId"
[(ngModel)]="entra.applicationId"
/>
</div>
<div class="mb-3">
<label for="secretKey" class="form-label">{{ "secretKey" | i18n }}</label>
<div class="input-group">
<input
type="{{ showAzureKey ? 'text' : 'password' }}"
type="{{ showEntraKey ? 'text' : 'password' }}"
class="form-control"
id="secretKey"
name="SecretKey"
[(ngModel)]="azure.key"
[(ngModel)]="entra.key"
/>
<button
type="button"
class="btn btn-outline-secondary"
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
(click)="toggleAzureKey()"
(click)="toggleEntraKey()"
>
<i
class="bwi bwi-lg"
aria-hidden="true"
[ngClass]="showAzureKey ? 'bwi-eye-slash' : 'bwi-eye'"
[ngClass]="showEntraKey ? 'bwi-eye-slash' : 'bwi-eye'"
></i>
</button>
</div>
@@ -607,7 +607,7 @@
<div class="form-text" *ngIf="directory === directoryType.Ldap">
{{ "ex" | i18n }} (&amp;(givenName=John)(|(l=Dallas)(l=Austin)))
</div>
<div class="form-text" *ngIf="directory === directoryType.AzureActiveDirectory">
<div class="form-text" *ngIf="directory === directoryType.EntraID">
{{ "ex" | i18n }} exclude:joe&#64;company.com
</div>
<div class="form-text" *ngIf="directory === directoryType.Okta">
@@ -684,7 +684,7 @@
<div class="form-text" *ngIf="directory === directoryType.Ldap">
{{ "ex" | i18n }} (&amp;(objectClass=group)(!(cn=Sales*))(!(cn=IT*)))
</div>
<div class="form-text" *ngIf="directory === directoryType.AzureActiveDirectory">
<div class="form-text" *ngIf="directory === directoryType.EntraID">
{{ "ex" | i18n }} include:Sales,IT
</div>
<div class="form-text" *ngIf="directory === directoryType.Okta">

View File

@@ -5,7 +5,7 @@ import { LogService } from "@/jslib/common/src/abstractions/log.service";
import { StateService } from "../../abstractions/state.service";
import { DirectoryType } from "../../enums/directoryType";
import { AzureConfiguration } from "../../models/azureConfiguration";
import { EntraIdConfiguration } from "../../models/entraIdConfiguration";
import { GSuiteConfiguration } from "../../models/gsuiteConfiguration";
import { LdapConfiguration } from "../../models/ldapConfiguration";
import { OktaConfiguration } from "../../models/oktaConfiguration";
@@ -22,13 +22,13 @@ export class SettingsComponent implements OnInit, OnDestroy {
directoryType = DirectoryType;
ldap = new LdapConfiguration();
gsuite = new GSuiteConfiguration();
azure = new AzureConfiguration();
entra = new EntraIdConfiguration();
okta = new OktaConfiguration();
oneLogin = new OneLoginConfiguration();
sync = new SyncConfiguration();
directoryOptions: any[];
showLdapPassword = false;
showAzureKey = false;
showEntraKey = false;
showOktaKey = false;
showOneLoginSecret = false;
@@ -42,7 +42,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
this.directoryOptions = [
{ name: this.i18nService.t("select"), value: null },
{ name: "Active Directory / LDAP", value: DirectoryType.Ldap },
{ name: "Azure Active Directory", value: DirectoryType.AzureActiveDirectory },
{ name: "Entra ID", value: DirectoryType.EntraID },
{ name: "G Suite (Google)", value: DirectoryType.GSuite },
{ name: "Okta", value: DirectoryType.Okta },
{ name: "OneLogin", value: DirectoryType.OneLogin },
@@ -56,10 +56,9 @@ export class SettingsComponent implements OnInit, OnDestroy {
this.gsuite =
(await this.stateService.getDirectory<GSuiteConfiguration>(DirectoryType.GSuite)) ||
this.gsuite;
this.azure =
(await this.stateService.getDirectory<AzureConfiguration>(
DirectoryType.AzureActiveDirectory,
)) || this.azure;
this.entra =
(await this.stateService.getDirectory<EntraIdConfiguration>(DirectoryType.EntraID)) ||
this.entra;
this.okta =
(await this.stateService.getDirectory<OktaConfiguration>(DirectoryType.Okta)) || this.okta;
this.oneLogin =
@@ -80,7 +79,7 @@ export class SettingsComponent implements OnInit, OnDestroy {
await this.stateService.setDirectoryType(this.directory);
await this.stateService.setDirectory(DirectoryType.Ldap, this.ldap);
await this.stateService.setDirectory(DirectoryType.GSuite, this.gsuite);
await this.stateService.setDirectory(DirectoryType.AzureActiveDirectory, this.azure);
await this.stateService.setDirectory(DirectoryType.EntraID, this.entra);
await this.stateService.setDirectory(DirectoryType.Okta, this.okta);
await this.stateService.setDirectory(DirectoryType.OneLogin, this.oneLogin);
await this.stateService.setSync(this.sync);
@@ -135,8 +134,8 @@ export class SettingsComponent implements OnInit, OnDestroy {
document.getElementById("password").focus();
}
toggleAzureKey() {
this.showAzureKey = !this.showAzureKey;
toggleEntraKey() {
this.showEntraKey = !this.showEntraKey;
document.getElementById("secretKey").focus();
}

View File

@@ -8,7 +8,7 @@ import { MessageResponse } from "@/jslib/node/src/cli/models/response/messageRes
import { StateService } from "../abstractions/state.service";
import { DirectoryType } from "../enums/directoryType";
import { AzureConfiguration } from "../models/azureConfiguration";
import { EntraIdConfiguration } from "../models/entraIdConfiguration";
import { GSuiteConfiguration } from "../models/gsuiteConfiguration";
import { LdapConfiguration } from "../models/ldapConfiguration";
import { OktaConfiguration } from "../models/oktaConfiguration";
@@ -20,7 +20,7 @@ export class ConfigCommand {
private directory: DirectoryType;
private ldap = new LdapConfiguration();
private gsuite = new GSuiteConfiguration();
private azure = new AzureConfiguration();
private entra = new EntraIdConfiguration();
private okta = new OktaConfiguration();
private oneLogin = new OneLoginConfiguration();
private sync = new SyncConfiguration();
@@ -54,8 +54,11 @@ export class ConfigCommand {
case "gsuite.key":
await this.setGSuiteKey(value);
break;
// Azure Active Directory was renamed to Entra ID, but we've kept the old key name
// to be backwards compatible with existing configurations.
case "azure.key":
await this.setAzureKey(value);
case "entra.key":
await this.setEntraIdKey(value);
break;
case "okta.token":
await this.setOktaToken(value);
@@ -102,9 +105,9 @@ export class ConfigCommand {
await this.saveConfig();
}
private async setAzureKey(key: string) {
private async setEntraIdKey(key: string) {
await this.loadConfig();
this.azure.key = key;
this.entra.key = key;
await this.saveConfig();
}
@@ -127,10 +130,9 @@ export class ConfigCommand {
this.gsuite =
(await this.stateService.getDirectory<GSuiteConfiguration>(DirectoryType.GSuite)) ||
this.gsuite;
this.azure =
(await this.stateService.getDirectory<AzureConfiguration>(
DirectoryType.AzureActiveDirectory,
)) || this.azure;
this.entra =
(await this.stateService.getDirectory<EntraIdConfiguration>(DirectoryType.EntraID)) ||
this.entra;
this.okta =
(await this.stateService.getDirectory<OktaConfiguration>(DirectoryType.Okta)) || this.okta;
this.oneLogin =
@@ -144,7 +146,7 @@ export class ConfigCommand {
await this.stateService.setDirectoryType(this.directory);
await this.stateService.setDirectory(DirectoryType.Ldap, this.ldap);
await this.stateService.setDirectory(DirectoryType.GSuite, this.gsuite);
await this.stateService.setDirectory(DirectoryType.AzureActiveDirectory, this.azure);
await this.stateService.setDirectory(DirectoryType.EntraID, this.entra);
await this.stateService.setDirectory(DirectoryType.Okta, this.okta);
await this.stateService.setDirectory(DirectoryType.OneLogin, this.oneLogin);
await this.stateService.setSync(this.sync);

View File

@@ -1,6 +1,6 @@
export enum DirectoryType {
Ldap = 0,
AzureActiveDirectory = 1,
EntraID = 1,
GSuite = 2,
Okta = 3,
OneLogin = 4,

View File

@@ -2,7 +2,7 @@ import { Account as BaseAccount } from "@/jslib/common/src/models/domain/account
import { DirectoryType } from "@/src/enums/directoryType";
import { AzureConfiguration } from "./azureConfiguration";
import { EntraIdConfiguration } from "./entraIdConfiguration";
import { GSuiteConfiguration } from "./gsuiteConfiguration";
import { LdapConfiguration } from "./ldapConfiguration";
import { OktaConfiguration } from "./oktaConfiguration";
@@ -29,7 +29,10 @@ export class ClientKeys {
export class DirectoryConfigurations {
ldap: LdapConfiguration;
gsuite: GSuiteConfiguration;
azure: AzureConfiguration;
entra: EntraIdConfiguration;
// Azure Active Directory was renamed to Entra ID, but we've kept the old account property name
// to be backwards compatible with existing configurations.
azure: EntraIdConfiguration;
okta: OktaConfiguration;
oneLogin: OneLoginConfiguration;
}

View File

@@ -1,6 +1,6 @@
import { IConfiguration } from "./IConfiguration";
export class AzureConfiguration implements IConfiguration {
export class EntraIdConfiguration implements IConfiguration {
identityAuthority: string;
tenant: string;
applicationId: string;

View File

@@ -190,7 +190,7 @@ export class Program extends BaseProgram {
writeLn(" server - On-premise hosted installation URL.");
writeLn(" directory - The type of directory to use.");
writeLn(" ldap.password - The password for connection to this LDAP server.");
writeLn(" azure.key - The Azure AD secret key.");
writeLn(" entra.key - The Entra Id secret key.");
writeLn(" gsuite.key - The G Suite private key.");
writeLn(" okta.token - The Okta token.");
writeLn(" onelogin.secret - The OneLogin client secret.");
@@ -202,7 +202,7 @@ export class Program extends BaseProgram {
writeLn(" bwdc config directory 1");
writeLn(" bwdc config ldap.password <password>");
writeLn(" bwdc config ldap.password --secretenv LDAP_PWD");
writeLn(" bwdc config azure.key <key>");
writeLn(" bwdc config entra.key <key>");
writeLn(" bwdc config gsuite.key <key>");
writeLn(" bwdc config okta.token <token>");
writeLn(" bwdc config onelogin.secret <secret>");

View File

@@ -5,7 +5,7 @@ import { DirectoryFactoryService } from "../abstractions/directory-factory.servi
import { StateService } from "../abstractions/state.service";
import { DirectoryType } from "../enums/directoryType";
import { AzureDirectoryService } from "./azure-directory.service";
import { EntraIdDirectoryService } from "./entra-id-directory.service";
import { GSuiteDirectoryService } from "./gsuite-directory.service";
import { LdapDirectoryService } from "./ldap-directory.service";
import { OktaDirectoryService } from "./okta-directory.service";
@@ -22,8 +22,8 @@ export class DefaultDirectoryFactoryService implements DirectoryFactoryService {
switch (directoryType) {
case DirectoryType.GSuite:
return new GSuiteDirectoryService(this.logService, this.i18nService, this.stateService);
case DirectoryType.AzureActiveDirectory:
return new AzureDirectoryService(this.logService, this.i18nService, this.stateService);
case DirectoryType.EntraID:
return new EntraIdDirectoryService(this.logService, this.i18nService, this.stateService);
case DirectoryType.Ldap:
return new LdapDirectoryService(this.logService, this.i18nService, this.stateService);
case DirectoryType.Okta:

View File

@@ -9,7 +9,7 @@ import { LogService } from "@/jslib/common/src/abstractions/log.service";
import { StateService } from "../abstractions/state.service";
import { DirectoryType } from "../enums/directoryType";
import { AzureConfiguration } from "../models/azureConfiguration";
import { EntraIdConfiguration } from "../models/entraIdConfiguration";
import { GroupEntry } from "../models/groupEntry";
import { SyncConfiguration } from "../models/syncConfiguration";
import { UserEntry } from "../models/userEntry";
@@ -17,8 +17,10 @@ import { UserEntry } from "../models/userEntry";
import { BaseDirectoryService } from "./baseDirectory.service";
import { IDirectoryService } from "./directory.service";
const AzurePublicIdentityAuhtority = "login.microsoftonline.com";
const AzureGovermentIdentityAuhtority = "login.microsoftonline.us";
const EntraIdPublicIdentityAuthority = "login.microsoftonline.com";
const EntraIdPublicGraphEndpoint = "https://graph.microsoft.com";
const EntraIdGovernmentIdentityAuthority = "login.microsoftonline.us";
const EntraIdGovernmentGraphEndpoint = "https://graph.microsoft.us";
const NextLink = "@odata.nextLink";
const DeltaLink = "@odata.deltaLink";
@@ -32,9 +34,9 @@ enum UserSetType {
ExcludeGroup,
}
export class AzureDirectoryService extends BaseDirectoryService implements IDirectoryService {
export class EntraIdDirectoryService extends BaseDirectoryService implements IDirectoryService {
private client: graph.Client;
private dirConfig: AzureConfiguration;
private dirConfig: EntraIdConfiguration;
private syncConfig: SyncConfiguration;
private accessToken: string;
private accessTokenExpiration: Date;
@@ -50,12 +52,12 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
async getEntries(force: boolean, test: boolean): Promise<[GroupEntry[], UserEntry[]]> {
const type = await this.stateService.getDirectoryType();
if (type !== DirectoryType.AzureActiveDirectory) {
if (type !== DirectoryType.EntraID) {
return;
}
this.dirConfig = await this.stateService.getDirectory<AzureConfiguration>(
DirectoryType.AzureActiveDirectory,
this.dirConfig = await this.stateService.getDirectory<EntraIdConfiguration>(
DirectoryType.EntraID,
);
if (this.dirConfig == null) {
return;
@@ -207,7 +209,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
if (keyword === "excludeadministrativeunit" || keyword === "includeadministrativeunit") {
for (const p of pieces) {
let auMembers = await this.client
.api(`https://graph.microsoft.com/v1.0/directory/administrativeUnits/${p}/members`)
.api(`${this.getGraphApiEndpoint()}/v1.0/directory/administrativeUnits/${p}/members`)
.get();
// eslint-disable-next-line
while (true) {
@@ -457,10 +459,10 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
const identityAuthority =
this.dirConfig.identityAuthority != null
? this.dirConfig.identityAuthority
: AzurePublicIdentityAuhtority;
: EntraIdPublicIdentityAuthority;
if (
identityAuthority !== AzurePublicIdentityAuhtority &&
identityAuthority !== AzureGovermentIdentityAuhtority
identityAuthority !== EntraIdPublicIdentityAuthority &&
identityAuthority !== EntraIdGovernmentIdentityAuthority
) {
done(new Error(this.i18nService.t("dirConfigIncomplete")), null);
return;
@@ -478,7 +480,7 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
client_id: this.dirConfig.applicationId,
client_secret: this.dirConfig.key,
grant_type: "client_credentials",
scope: "https://graph.microsoft.com/.default",
scope: `${this.getGraphApiEndpoint()}/.default`,
});
const req = https
@@ -542,4 +544,10 @@ export class AzureDirectoryService extends BaseDirectoryService implements IDire
exp.setSeconds(exp.getSeconds() + expSeconds);
this.accessTokenExpiration = exp;
}
private getGraphApiEndpoint(): string {
return this.dirConfig.identityAuthority === EntraIdGovernmentIdentityAuthority
? EntraIdGovernmentGraphEndpoint
: EntraIdPublicGraphEndpoint;
}
}

View File

@@ -11,7 +11,7 @@ import { StateService as StateServiceAbstraction } from "@/src/abstractions/stat
import { DirectoryType } from "@/src/enums/directoryType";
import { IConfiguration } from "@/src/models/IConfiguration";
import { Account } from "@/src/models/account";
import { AzureConfiguration } from "@/src/models/azureConfiguration";
import { EntraIdConfiguration } from "@/src/models/entraIdConfiguration";
import { GSuiteConfiguration } from "@/src/models/gsuiteConfiguration";
import { LdapConfiguration } from "@/src/models/ldapConfiguration";
import { OktaConfiguration } from "@/src/models/oktaConfiguration";
@@ -21,7 +21,10 @@ import { SyncConfiguration } from "@/src/models/syncConfiguration";
const SecureStorageKeys = {
ldap: "ldapPassword",
gsuite: "gsuitePrivateKey",
// Azure Active Directory was renamed to Entra ID, but we've kept the old property name
// to be backwards compatible with existing configurations.
azure: "azureKey",
entra: "entraKey",
okta: "oktaToken",
oneLogin: "oneLoginClientSecret",
userDelta: "userDeltaToken",
@@ -68,8 +71,8 @@ export class StateService
case DirectoryType.Ldap:
(configWithSecrets as any).password = await this.getLdapKey();
break;
case DirectoryType.AzureActiveDirectory:
(configWithSecrets as any).key = await this.getAzureKey();
case DirectoryType.EntraID:
(configWithSecrets as any).key = await this.getEntraKey();
break;
case DirectoryType.Okta:
(configWithSecrets as any).token = await this.getOktaKey();
@@ -93,7 +96,7 @@ export class StateService
config:
| LdapConfiguration
| GSuiteConfiguration
| AzureConfiguration
| EntraIdConfiguration
| OktaConfiguration
| OneLoginConfiguration,
): Promise<any> {
@@ -106,11 +109,11 @@ export class StateService
await this.setLdapConfiguration(ldapConfig);
break;
}
case DirectoryType.AzureActiveDirectory: {
const azureConfig = config as AzureConfiguration;
await this.setAzureKey(azureConfig.key);
azureConfig.key = StoredSecurely;
await this.setAzureConfiguration(azureConfig);
case DirectoryType.EntraID: {
const entraConfig = config as EntraIdConfiguration;
await this.setEntraKey(entraConfig.key);
entraConfig.key = StoredSecurely;
await this.setEntraConfiguration(entraConfig);
break;
}
case DirectoryType.Okta: {
@@ -187,23 +190,32 @@ export class StateService
);
}
private async getAzureKey(options?: StorageOptions): Promise<string> {
private async getEntraKey(options?: StorageOptions): Promise<string> {
options = this.reconcileOptions(options, await this.defaultSecureStorageOptions());
if (options?.userId == null) {
return null;
}
const entraKey = await this.secureStorageService.get<string>(
`${options.userId}_${SecureStorageKeys.entra}`,
);
if (entraKey != null) {
return entraKey;
}
return await this.secureStorageService.get<string>(
`${options.userId}_${SecureStorageKeys.azure}`,
);
}
private async setAzureKey(value: string, options?: StorageOptions): Promise<void> {
private async setEntraKey(value: string, options?: StorageOptions): Promise<void> {
options = this.reconcileOptions(options, await this.defaultSecureStorageOptions());
if (options?.userId == null) {
return;
}
await this.secureStorageService.save(
`${options.userId}_${SecureStorageKeys.azure}`,
`${options.userId}_${SecureStorageKeys.entra}`,
value,
options,
);
@@ -259,8 +271,8 @@ export class StateService
return await this.getLdapConfiguration();
case DirectoryType.GSuite:
return await this.getGsuiteConfiguration();
case DirectoryType.AzureActiveDirectory:
return await this.getAzureConfiguration();
case DirectoryType.EntraID:
return await this.getEntraConfiguration();
case DirectoryType.Okta:
return await this.getOktaConfiguration();
case DirectoryType.OneLogin:
@@ -305,17 +317,28 @@ export class StateService
);
}
async getAzureConfiguration(options?: StorageOptions): Promise<AzureConfiguration> {
async getEntraConfiguration(options?: StorageOptions): Promise<EntraIdConfiguration> {
const entraConfig = (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))
)?.directoryConfigurations?.entra;
if (entraConfig != null) {
return entraConfig;
}
return (
await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))
)?.directoryConfigurations?.azure;
}
async setAzureConfiguration(value: AzureConfiguration, options?: StorageOptions): Promise<void> {
async setEntraConfiguration(
value: EntraIdConfiguration,
options?: StorageOptions,
): Promise<void> {
const account = await this.getAccount(
this.reconcileOptions(options, await this.defaultOnDiskOptions()),
);
account.directoryConfigurations.azure = value;
account.directoryConfigurations.entra = value;
await this.saveAccount(
account,
this.reconcileOptions(options, await this.defaultOnDiskOptions()),

View File

@@ -3,7 +3,7 @@ import { StateMigrationService as BaseStateMigrationService } from "@/jslib/comm
import { DirectoryType } from "@/src/enums/directoryType";
import { Account, DirectoryConfigurations, DirectorySettings } from "@/src/models/account";
import { AzureConfiguration } from "@/src/models/azureConfiguration";
import { EntraIdConfiguration } from "@/src/models/entraIdConfiguration";
import { GSuiteConfiguration } from "@/src/models/gsuiteConfiguration";
import { LdapConfiguration } from "@/src/models/ldapConfiguration";
import { OktaConfiguration } from "@/src/models/oktaConfiguration";
@@ -14,6 +14,7 @@ const SecureStorageKeys: { [key: string]: any } = {
ldap: "ldapPassword",
gsuite: "gsuitePrivateKey",
azure: "azureKey",
entra: "entraIdKey",
okta: "oktaToken",
oneLogin: "oneLoginClientSecret",
directoryConfigPrefix: "directoryConfig_",
@@ -104,13 +105,16 @@ export class StateMigrationService extends BaseStateMigrationService {
}
};
// Initilize typed objects from key/value pairs in storage to either be saved temporarily until an account is authed or applied to the active account
// Initialize typed objects from key/value pairs in storage to either be saved temporarily until an account is authed or applied to the active account
const getDirectoryConfig = async <T>(type: DirectoryType) =>
await this.get<T>(SecureStorageKeys.directoryConfigPrefix + type);
const directoryConfigs: DirectoryConfigurations = {
ldap: await getDirectoryConfig<LdapConfiguration>(DirectoryType.Ldap),
gsuite: await getDirectoryConfig<GSuiteConfiguration>(DirectoryType.GSuite),
azure: await getDirectoryConfig<AzureConfiguration>(DirectoryType.AzureActiveDirectory),
// Azure Active Directory was renamed to Entra ID, but we've kept the old property name
// to be backwards compatible with existing configurations.
azure: await getDirectoryConfig<EntraIdConfiguration>(DirectoryType.EntraID),
entra: await getDirectoryConfig<EntraIdConfiguration>(DirectoryType.EntraID),
okta: await getDirectoryConfig<OktaConfiguration>(DirectoryType.Okta),
oneLogin: await getDirectoryConfig<OneLoginConfiguration>(DirectoryType.OneLogin),
};