From 102c4c9d22130762fb4bb5af7874168ea531ca4e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 10 Oct 2023 11:59:36 +0200 Subject: [PATCH 001/378] Fix nuget workflow inputs (#275) --- .github/workflows/publish-dotnet.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 7f438b24c..7c819986e 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -2,9 +2,10 @@ name: Deploy NuGet Package on: workflow_dispatch: - version_number: - description: "New Version" - required: true + inputs: + version_number: + description: "New Version" + required: true jobs: generate_schemas: From 1339bc0f6d0705414c7ca3ea459edd97f85c469b Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 10 Oct 2023 14:59:17 +0200 Subject: [PATCH 002/378] Change LicenseUrl to LicenseFile (#276) --- .../csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj | 139 +++++++++--------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj index 97f850211..c110785a9 100644 --- a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj +++ b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj @@ -1,73 +1,76 @@ - - net6.0 - README.md - enable - enable - Bitwarden.Sdk - Bitwarden Secrets Manager SDK - Bitwarden Inc. - .NET bindings for interacting with the Bitwarden Secrets Manager - Bitwarden Inc. - https://github.com/bitwarden/sdk/tree/master/languages/csharp - Bitwarden;Sdk;.NET - SDK - bitwarden.png - Git - Bitwarden.Sdk - https://bitwarden.com/products/secrets-manager/ - https://github.com/bitwarden/sdk/blob/master/LICENSE - + + net6.0 + enable + enable + Bitwarden.Sdk - - - - - - + Bitwarden Secrets Manager SDK + Bitwarden Inc. + .NET bindings for interacting with the Bitwarden Secrets Manager + Bitwarden Inc. + SDK - - - + https://github.com/bitwarden/sdk/tree/master/languages/csharp + Git - - 4 - - - - Always - true - - - Always - true - - - Always - true - - - - - Always - true - runtimes/osx-x64/native - - - Always - true - runtimes/osx-arm64/native - - - Always - true - runtimes/linux-x64/native - - - Always - true - runtimes/win-x64/native - - - + https://bitwarden.com/products/secrets-manager/ + Bitwarden.Sdk + bitwarden.png + Bitwarden;Sdk;.NET + README.md + LICENSE.txt + + + + + + + + + + + + + + + 4 + + + + Always + true + + + Always + true + + + Always + true + + + + + Always + true + runtimes/osx-x64/native + + + Always + true + runtimes/osx-arm64/native + + + Always + true + runtimes/linux-x64/native + + + Always + true + runtimes/win-x64/native + + + \ No newline at end of file From 33c4cdc97c4964a94d377550b5ad0dcca03b6a19 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:58:13 +0200 Subject: [PATCH 003/378] Bump bitwarden version to 0.3.1 (#280) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden version bump to 0.3.1 Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Cargo.lock | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58fb5ff26..4183b248d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,7 +320,7 @@ checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "bitwarden" -version = "0.3.0" +version = "0.3.1" dependencies = [ "aes", "argon2", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 345b1f9cb..5cbb6660d 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden" -version = "0.3.0" +version = "0.3.1" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 29252d133..0793470b3 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -22,7 +22,7 @@ env_logger = "0.10.0" color-eyre = "0.6" inquire = "0.6.2" -bitwarden = { path = "../bitwarden", version = "0.3.0", features = [ +bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ "internal", "mobile", ] } diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index ed4dc3b91..954c1722b 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -38,7 +38,7 @@ tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } -bitwarden = { path = "../bitwarden", version = "0.3.0", features = ["secrets"] } +bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } [dev-dependencies] tempfile = "3.5.0" From 9f1592826c2b359a3a54f23c76a945da5000ce71 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:09:54 +0200 Subject: [PATCH 004/378] Bump cli version to 0.3.1 (#281) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated cli version bump to 0.3.1 Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Cargo.lock | 2 +- crates/bws/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4183b248d..fbefce76a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -522,7 +522,7 @@ dependencies = [ [[package]] name = "bws" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bat", "bitwarden", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 954c1722b..142a56959 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bws" -version = "0.3.0" +version = "0.3.1" edition = "2021" rust-version = "1.60" authors = ["Bitwarden Inc"] From 0a2844e610f20f2feb1f7adb053e614337d61f15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:13:53 +0200 Subject: [PATCH 005/378] Bump napi version to 0.3.1 (#282) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated napi version bump to 0.3.1 Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Cargo.lock | 2 +- crates/bitwarden-napi/Cargo.toml | 2 +- crates/bitwarden-napi/npm/darwin-arm64/package.json | 2 +- crates/bitwarden-napi/npm/darwin-x64/package.json | 2 +- crates/bitwarden-napi/npm/linux-x64-gnu/package.json | 2 +- crates/bitwarden-napi/npm/win32-x64-msvc/package.json | 2 +- crates/bitwarden-napi/package-lock.json | 4 ++-- crates/bitwarden-napi/package.json | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbefce76a..01f261e6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -413,7 +413,7 @@ dependencies = [ [[package]] name = "bitwarden-napi" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bitwarden-json", "env_logger", diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index bc170631d..505b68e57 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-napi" -version = "0.3.0" +version = "0.3.1" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden-napi/npm/darwin-arm64/package.json b/crates/bitwarden-napi/npm/darwin-arm64/package.json index b9c1c95b7..52d785d87 100644 --- a/crates/bitwarden-napi/npm/darwin-arm64/package.json +++ b/crates/bitwarden-napi/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-darwin-arm64", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/darwin-x64/package.json b/crates/bitwarden-napi/npm/darwin-x64/package.json index 66f352df4..0a1b06423 100644 --- a/crates/bitwarden-napi/npm/darwin-x64/package.json +++ b/crates/bitwarden-napi/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-darwin-x64", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/linux-x64-gnu/package.json b/crates/bitwarden-napi/npm/linux-x64-gnu/package.json index 7f91c241c..2284d8415 100644 --- a/crates/bitwarden-napi/npm/linux-x64-gnu/package.json +++ b/crates/bitwarden-napi/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-linux-x64-gnu", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/npm/win32-x64-msvc/package.json b/crates/bitwarden-napi/npm/win32-x64-msvc/package.json index e4cfa367c..261554e93 100644 --- a/crates/bitwarden-napi/npm/win32-x64-msvc/package.json +++ b/crates/bitwarden-napi/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi-win32-x64-msvc", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 02ea37bec..c77fd4a83 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -1,12 +1,12 @@ { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "license": "SEE LICENSE IN LICENSE", "devDependencies": { "@napi-rs/cli": "^2.13.2", diff --git a/crates/bitwarden-napi/package.json b/crates/bitwarden-napi/package.json index 50bebb58b..a0dbcee3b 100644 --- a/crates/bitwarden-napi/package.json +++ b/crates/bitwarden-napi/package.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-napi", - "version": "0.3.0", + "version": "0.3.1", "homepage": "https://github.com/bitwarden/sdk#readme", "bugs": { "url": "https://github.com/bitwarden/sdk/issues" From 218a909e788d314ebb75fb70ed9c9789acfef050 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:38:56 +0200 Subject: [PATCH 006/378] Bump bitwarden-api-api version to 0.2.2 (#283) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden-api-api version bump to 0.2.2 Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Cargo.lock | 2 +- crates/bitwarden-api-api/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01f261e6d..650f544b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,7 +357,7 @@ dependencies = [ [[package]] name = "bitwarden-api-api" -version = "0.2.1" +version = "0.2.2" dependencies = [ "reqwest", "serde", diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index fd5780dad..518cc33ed 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-api" -version = "0.2.1" +version = "0.2.2" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 5cbb6660d..85c24a708 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -56,7 +56,7 @@ uniffi = { version = "=0.24.1", optional = true } getrandom = { version = ">=0.2.9", features = ["js"] } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.1" } -bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.1" } +bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } [dev-dependencies] tokio = { version = "1.28.2", features = ["rt", "macros"] } From 6b8b84fd7db440173a5accb65ca40b97a9b760c3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:42:57 +0200 Subject: [PATCH 007/378] Bump bitwarden-api-identity version to 0.2.2 (#284) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden-api-identity version bump to 0.2.2 Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Cargo.lock | 2 +- crates/bitwarden-api-identity/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 650f544b8..c1d317d4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "bitwarden-api-identity" -version = "0.2.1" +version = "0.2.2" dependencies = [ "reqwest", "serde", diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index a74a43961..70be0560b 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-identity" -version = "0.2.1" +version = "0.2.2" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 85c24a708..0090ebb0e 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -55,7 +55,7 @@ uniffi = { version = "=0.24.1", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } -bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.1" } +bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } [dev-dependencies] From cfd9e6775318ae8e1253b94f517e16f76a80c8fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:42:43 +0200 Subject: [PATCH 008/378] Update Rust crate bat to 0.24.0 (#287) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 131 +++++++----------------------------------- crates/bws/Cargo.toml | 2 +- 2 files changed, 21 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1d317d4e..bbd44858d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "bat" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd4b13b0233143ae151a66e0135d715b65f631d1028c40502cc88182bcb9f4fa" +checksum = "9dcc9e5637c2330d8eb7b920f2aa5d9e184446c258466f825ea1412c7614cc86" dependencies = [ "ansi_colours", "bincode", @@ -281,17 +281,17 @@ dependencies = [ "clircle", "console", "content_inspector", - "dirs", - "encoding", + "encoding_rs", "flate2", "globset", + "home", "nu-ansi-term", "once_cell", "path_abs", "plist", "semver", "serde", - "serde_yaml 0.8.26", + "serde_yaml", "syntect", "thiserror", "unicode-width", @@ -537,7 +537,7 @@ dependencies = [ "openssl", "serde", "serde_json", - "serde_yaml 0.9.25", + "serde_yaml", "supports-color", "tempfile", "thiserror", @@ -700,9 +700,9 @@ checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "clircle" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68bbd985a63de680ab4d1ad77b6306611a8f961b282c8b5ab513e6de934e396" +checksum = "c8e87cbed5354f17bd8ca8821a097fb62599787fe8f611743fad7ee156a0a600" dependencies = [ "cfg-if", "libc", @@ -983,15 +983,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -1022,70 +1013,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - [[package]] name = "encoding_rs" version = "0.8.33" @@ -1453,6 +1380,15 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "http" version = "0.2.9" @@ -1745,12 +1681,6 @@ dependencies = [ "safemem", ] -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.4.8" @@ -1928,11 +1858,11 @@ dependencies = [ [[package]] name = "nu-ansi-term" -version = "0.47.0" +version = "0.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df031e117bca634c262e9bd3173776844b6c17a90b3741c9163663b4385af76" +checksum = "c073d3c1930d0751774acf49e66653acecb416c3a54c6ec095a9b11caddb5a68" dependencies = [ - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2834,18 +2764,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_yaml" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" -dependencies = [ - "indexmap 1.9.3", - "ryu", - "serde", - "yaml-rust", -] - [[package]] name = "serde_yaml" version = "0.9.25" @@ -3951,15 +3869,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "zeroize" version = "1.6.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 142a56959..00ec40da7 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["bitwarden", "secrets-manager", "cli"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bat = { version = "0.23.0", features = [ +bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } chrono = { version = "0.4.26", features = [ From 6224cfc92cc7c56b445513f9f323a89424dc5837 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:45:25 +0200 Subject: [PATCH 009/378] Update dependency webpack to v5.89.0 (#288) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js_webassembly/package-lock.json | 8 ++++---- languages/js_webassembly/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index da527fe32..8c93e162c 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -9,7 +9,7 @@ "text-encoding": "0.7.0", "ts-loader": "9.5.0", "wasm-pack": "0.12.1", - "webpack": "5.88.2", + "webpack": "5.89.0", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" } @@ -3718,9 +3718,9 @@ } }, "node_modules/webpack": { - "version": "5.88.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", - "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", diff --git a/languages/js_webassembly/package.json b/languages/js_webassembly/package.json index df67eb9b7..95d7002a5 100644 --- a/languages/js_webassembly/package.json +++ b/languages/js_webassembly/package.json @@ -8,7 +8,7 @@ "text-encoding": "0.7.0", "ts-loader": "9.5.0", "wasm-pack": "0.12.1", - "webpack": "5.88.2", + "webpack": "5.89.0", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1" } From 2932f5110f101276a8c10f55522f53aa3a59c5a4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:04:38 +0200 Subject: [PATCH 010/378] Lock file maintenance (#292) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 136 ++++++++--------- crates/bitwarden-napi/package-lock.json | 18 ++- languages/js_webassembly/package-lock.json | 161 ++++++++++++--------- package-lock.json | 36 +++-- 4 files changed, 197 insertions(+), 154 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bbd44858d..0bc355d7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -314,9 +314,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitwarden" @@ -491,9 +491,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.2" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" dependencies = [ "memchr", "serde", @@ -581,9 +581,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" dependencies = [ "serde", ] @@ -958,9 +958,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", +] [[package]] name = "digest" @@ -1043,25 +1046,14 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "event-listener" version = "2.5.3" @@ -1095,9 +1087,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "flate2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -1652,9 +1644,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -1683,9 +1675,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" @@ -1767,7 +1759,7 @@ version = "2.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd063c93b900149304e3ba96ce5bf210cd4f81ef5eb80ded0d100df3e85a3ac0" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "ctor", "napi-derive", "napi-sys", @@ -1916,9 +1908,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", @@ -1977,7 +1969,7 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -2175,6 +2167,12 @@ dependencies = [ "time", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2183,9 +2181,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -2254,9 +2252,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47b0777feb17f61eea78667d61103758b243a871edc09a7786500a50467b605" +checksum = "c09c2b349b6538d8a73d436ca606dab6ce0aaab4dad9e6b7bdd57a4f556c3bc3" dependencies = [ "arc-swap", "log", @@ -2406,25 +2404,25 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.6" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax", + "regex-syntax 0.8.2", ] [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.2", ] [[package]] @@ -2433,6 +2431,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "reqwest" version = "0.11.22" @@ -2517,11 +2521,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.17" +version = "0.38.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" +checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -2661,27 +2665,27 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", @@ -2992,7 +2996,7 @@ dependencies = [ "fnv", "once_cell", "onig", - "regex-syntax", + "regex-syntax 0.7.5", "serde", "serde_json", "thiserror", @@ -3080,12 +3084,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -3123,9 +3128,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", @@ -3224,20 +3229,19 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3830,9 +3834,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index c77fd4a83..5a2945fd3 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,11 +95,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/acorn": { "version": "8.10.0", @@ -205,6 +208,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true, + "peer": true + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index 8c93e162c..3c961135e 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.3", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", - "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", + "version": "8.44.4", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz", + "integrity": "sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==", "dev": true, "dependencies": { "@types/estree": "*", @@ -152,9 +152,9 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.18", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", - "integrity": "sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.19.tgz", + "integrity": "sha512-UtOfBtzN9OvpZPPbnnYunfjM7XCI4jyk1NvnFhTVz5krYAnW4o5DCoIekvms+8ApqhB4+9wSge1kBijdfTSmfg==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -203,16 +203,19 @@ "dev": true }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", + "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", - "dev": true + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@types/qs": { "version": "6.9.8", @@ -221,9 +224,9 @@ "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", + "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", "dev": true }, "node_modules/@types/retry": { @@ -233,9 +236,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", + "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -243,18 +246,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", + "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -263,18 +266,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "version": "0.3.34", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.34.tgz", + "integrity": "sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/ws": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "version": "8.5.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", + "integrity": "sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==", "dev": true, "dependencies": { "@types/node": "*" @@ -753,9 +756,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.11", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.11.tgz", - "integrity": "sha512-xn1UXOKUz7DjdGlg9RrUr0GGiWzI97UQJnugHtH0OLDfJB7jMgoIkYvRIEO1l9EeEERVqeqLYOcFBW9ldjypbQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "dev": true, "funding": [ { @@ -772,8 +775,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001538", - "electron-to-chromium": "^1.4.526", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.13" }, @@ -823,9 +826,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001538", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", - "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "version": "1.0.30001549", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", + "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", "dev": true, "funding": [ { @@ -1251,9 +1254,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.528", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.528.tgz", - "integrity": "sha512-UdREXMXzLkREF4jA8t89FQjA8WHI6ssP38PMY4/4KhXFQbtImnghh4GkCgrtiZwLKUKVD2iTVXvDVQjfomEQuA==", + "version": "1.4.554", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.554.tgz", + "integrity": "sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ==", "dev": true }, "node_modules/encodeurl": { @@ -1534,6 +1537,15 @@ "node": ">=8" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/follow-redirects": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", @@ -1597,9 +1609,9 @@ } }, "node_modules/fs-monkey": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", - "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", + "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", "dev": true }, "node_modules/fs.realpath": { @@ -1623,10 +1635,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/get-intrinsic": { "version": "1.2.1", @@ -1706,13 +1721,10 @@ "dev": true }, "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, "engines": { "node": ">= 0.4.0" } @@ -2209,13 +2221,13 @@ } }, "node_modules/launch-editor": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", - "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", "dev": true, "dependencies": { "picocolors": "^1.0.0", - "shell-quote": "^1.7.3" + "shell-quote": "^1.8.1" } }, "node_modules/loader-runner": { @@ -2520,9 +2532,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", + "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2923,9 +2935,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -3442,9 +3454,9 @@ } }, "node_modules/terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", + "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3595,6 +3607,12 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4007,12 +4025,13 @@ } }, "node_modules/webpack-merge": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", - "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { diff --git a/package-lock.json b/package-lock.json index 22f0e6282..ecbb207ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", - "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", + "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -363,11 +363,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.6.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.5.tgz", - "integrity": "sha512-2qGq5LAOTh9izcc0+F+dToFigBWiK1phKPt7rNhOqJSr35y8rlIBjDwGtFSgAI6MGIhjwOVNSQZVdJsZJ2uR1w==", + "version": "20.8.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", + "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~5.25.1" + } }, "node_modules/@types/urijs": { "version": "1.19.20", @@ -1315,9 +1318,9 @@ } }, "node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -1970,6 +1973,13 @@ "node": ">=8" } }, + "node_modules/undici-types": { + "version": "5.25.3", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", + "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "dev": true, + "peer": true + }, "node_modules/unicode-properties": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", @@ -2120,9 +2130,9 @@ } }, "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", + "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", "dev": true, "engines": { "node": ">= 14" From 4ac7a1700265b05c826ec0136cf2fd25db8c8ead Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:51:27 +0200 Subject: [PATCH 011/378] Update bitwarden/gh-actions digest to c970b0f (#270) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 8 ++++---- .github/workflows/release-napi.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 4cef3fe63..2c30e0fde 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 5d4d3c3e7..234b43aed 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-checksum@c970b0fb89bd966749280e832928db62040812bf with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 5c4992fc5..cff308754 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/release-version-check@c970b0fb89bd966749280e832928db62040812bf with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index c672edb61..fd651e2b2 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@f1125802b1ccae8c601d7c4f61ce39ea254b10c8 + uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" From fdfc2e9958717fd93a94ff5f9d85fd75cab6483c Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Tue, 17 Oct 2023 06:01:17 -0400 Subject: [PATCH 012/378] Add 0.3.1 to changelog (#293) --- crates/bitwarden/CHANGELOG.md | 3 ++- crates/bws/CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index d61af5206..5569ebd7b 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,10 +7,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.3.1] - 2023-10-13 + ### Changed - `auth::request::AccessTokenLoginRequest` moved to `auth::login::AccessTokenLoginRequest` (#178) - - Support for fetching multiple secrets by ids (#150) ## [0.3.0] - 2023-07-26 diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 15fcfdf3b..2dc71f152 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,6 +7,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.3.1] - 2023-10-13 + ### Added - Support for shell autocompletion with the `bws completions` command (#103) From f51b5b976cc0d750accb2e9ba2b7abbdf7ede937 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 17 Oct 2023 18:12:02 +0200 Subject: [PATCH 013/378] Mock a TOTP implementation (#295) --- Cargo.lock | 1 + crates/bitwarden-uniffi/Cargo.toml | 4 ++ crates/bitwarden-uniffi/src/docs.rs | 8 ++- crates/bitwarden-uniffi/src/lib.rs | 1 + crates/bitwarden-uniffi/src/uniffi_support.rs | 16 ++++++ crates/bitwarden-uniffi/src/vault/mod.rs | 19 +++++++ .../bitwarden/src/mobile/vault/client_totp.rs | 18 +++++++ crates/bitwarden/src/mobile/vault/mod.rs | 1 + crates/bitwarden/src/vault/mod.rs | 2 + crates/bitwarden/src/vault/totp.rs | 30 +++++++++++ languages/kotlin/doc.md | 52 ++++++++++++++++--- 11 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 crates/bitwarden-uniffi/src/uniffi_support.rs create mode 100644 crates/bitwarden/src/mobile/vault/client_totp.rs create mode 100644 crates/bitwarden/src/vault/totp.rs diff --git a/Cargo.lock b/Cargo.lock index 0bc355d7c..7bb70fdf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -441,6 +441,7 @@ version = "0.1.0" dependencies = [ "async-lock", "bitwarden", + "chrono", "env_logger", "openssl", "schemars", diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 4c1ce2101..60228c104 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -13,6 +13,10 @@ bench = false [dependencies] async-lock = "2.7.0" +chrono = { version = ">=0.4.26, <0.5", features = [ + "serde", + "std", +], default-features = false } env_logger = "0.10.0" uniffi = "=0.24.1" schemars = { version = ">=0.8, <0.9", optional = true } diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index bd30e974e..bc47a19c3 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -3,7 +3,10 @@ use bitwarden::{ client::kdf::Kdf, mobile::crypto::InitCryptoRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, - vault::{Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView}, + vault::{ + Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, + TotpResponse, + }, }; use schemars::JsonSchema; @@ -35,4 +38,7 @@ pub enum DocRef { // Kdf Kdf(Kdf), + + /// TOTP + TotpResponse(TotpResponse), } diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 2e2543ab3..6e5415d38 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -9,6 +9,7 @@ use bitwarden::{client::client_settings::ClientSettings, mobile::crypto::InitCry pub mod auth; mod error; pub mod tool; +mod uniffi_support; pub mod vault; #[cfg(feature = "docs")] diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs new file mode 100644 index 000000000..f2a0bfde6 --- /dev/null +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -0,0 +1,16 @@ +use crate::UniffiCustomTypeConverter; + +type DateTime = chrono::DateTime; +uniffi::custom_type!(DateTime, std::time::SystemTime); + +impl UniffiCustomTypeConverter for chrono::DateTime { + type Builtin = std::time::SystemTime; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Ok(Self::from(val)) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.into() + } +} diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index 2692632ab..79b3e5835 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -1,5 +1,8 @@ use std::sync::Arc; +use bitwarden::vault::TotpResponse; +use chrono::{DateTime, Utc}; + use crate::Client; pub mod ciphers; @@ -37,4 +40,20 @@ impl ClientVault { pub fn sends(self: Arc) -> Arc { Arc::new(sends::ClientSends(self.0.clone())) } + + /// Generate a TOTP code from a provided key. + /// + /// The key can be either: + /// - A base32 encoded string + /// - OTP Auth URI + /// - Steam URI + pub async fn generate_totp(&self, key: String, time: Option>) -> TotpResponse { + self.0 + .0 + .read() + .await + .vault() + .generate_totp(key, time) + .await + } } diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs new file mode 100644 index 000000000..97eb243af --- /dev/null +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -0,0 +1,18 @@ +use chrono::{DateTime, Utc}; + +use crate::vault::{generate_totp, TotpResponse}; + +use super::client_vault::ClientVault; + +impl<'a> ClientVault<'a> { + /// Generate a TOTP code from a provided key. + /// + /// Key can be either: + /// - A base32 encoded string + /// - OTP Auth URI + /// - Steam URI + /// + pub async fn generate_totp(&'a self, key: String, time: Option>) -> TotpResponse { + generate_totp(key, time).await + } +} diff --git a/crates/bitwarden/src/mobile/vault/mod.rs b/crates/bitwarden/src/mobile/vault/mod.rs index f0fe4ca76..f22f004ce 100644 --- a/crates/bitwarden/src/mobile/vault/mod.rs +++ b/crates/bitwarden/src/mobile/vault/mod.rs @@ -3,4 +3,5 @@ mod client_collection; mod client_folders; mod client_password_history; mod client_sends; +mod client_totp; mod client_vault; diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index 9eecd6620..12910283c 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -3,9 +3,11 @@ mod collection; mod folder; mod password_history; mod send; +mod totp; pub use cipher::{Cipher, CipherListView, CipherView}; pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; pub use send::{Send, SendListView, SendView}; +pub use totp::{generate_totp, TotpResponse}; diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs new file mode 100644 index 000000000..7e701f92e --- /dev/null +++ b/crates/bitwarden/src/vault/totp.rs @@ -0,0 +1,30 @@ +use chrono::{DateTime, Utc}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct TotpResponse { + /// Generated TOTP code + pub code: String, + /// Time period + pub period: u32, +} + +/// Generate a OATH or RFC 6238 TOTP code from a provided key. +/// +/// +/// +/// Key can be either: +/// - A base32 encoded string +/// - OTP Auth URI +/// - Steam URI +/// +/// Supports providing an optional time, and defaults to current system time if none is provided. +pub async fn generate_totp(_key: String, _time: Option>) -> TotpResponse { + TotpResponse { + code: "000 000".to_string(), + period: 30, + } +} diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 9e8c19929..6174df750 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -441,6 +441,24 @@ Sends operations **Output**: Arc +### `generate_totp` + +Generate a TOTP code from a provided key. + +The key can be either: + +- A base32 encoded string +- OTP Auth URI +- Steam URI + +**Arguments**: + +- self: +- key: String +- time: Option + +**Output**: [TotpResponse](#totpresponse) + # References References are generated from the JSON schemas and should mostly match the kotlin and swift @@ -541,17 +559,17 @@ implementations. attachments - array + array,null fields - array + array,null passwordHistory - array + array,null @@ -606,7 +624,7 @@ implementations. notes - string + string,null @@ -666,17 +684,17 @@ implementations. attachments - array + array,null fields - array + array,null passwordHistory - array + array,null @@ -1253,3 +1271,23 @@ implementations. + +## `TotpResponse` + + + + + + + + + + + + + + + + + +
KeyTypeDescription
codestringGenerated TOTP code
periodintegerTime period
From 9ff37c721d1056f48c8954f70c57e76d853f8139 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 19 Oct 2023 08:39:53 -0700 Subject: [PATCH 014/378] Return a non-zero exit code when no subcommands are supplied (#296) ## Type of change - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Return a non-zero exit code when no subcommands are supplied. This matches the behavior in many other CLIs (`bw`, `git`, `ssh`, etc.). ## Code changes - **`crates/bws/src/main.rs`:** Exit with a non-zero exit code ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bws/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 5e6da19d8..c7a910260 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -247,7 +247,7 @@ async fn process_commands() -> Result<()> { let Some(command) = cli.command else { let mut cmd = Cli::command(); eprintln!("{}", cmd.render_help().ansi()); - return Ok(()); + std::process::exit(1); }; // These commands don't require authentication, so we process them first From 1601ecd43ea90ef8775346e0ad0a6d13eda77545 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 23 Oct 2023 12:05:22 +0200 Subject: [PATCH 015/378] Switch from from_str to parse (#299) --- crates/bitwarden/src/auth/login/access_token.rs | 6 ++---- crates/bitwarden/src/auth/login/api_key.rs | 6 ++---- crates/bitwarden/src/auth/login/password.rs | 7 ++----- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 46fa35779..63fd86ebb 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use base64::Engine; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -23,13 +21,13 @@ pub(crate) async fn access_token_login( //info!("api key logging in"); //debug!("{:#?}, {:#?}", client, input); - let access_token = AccessToken::from_str(&input.access_token)?; + let access_token: AccessToken = input.access_token.parse()?; let response = request_access_token(client, &access_token).await?; if let IdentityTokenResponse::Payload(r) = &response { // Extract the encrypted payload and use the access token encryption key to decrypt it - let payload = EncString::from_str(&r.encrypted_payload)?; + let payload: EncString = r.encrypted_payload.parse()?; let decrypted_payload = payload.decrypt_with_key(&access_token.encryption_key)?; diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index a9fa954d7..cdbc383ba 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -46,8 +44,8 @@ pub(crate) async fn api_key_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 33f7ea338..c86f7019f 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "internal")] -use std::str::FromStr; - #[cfg(feature = "internal")] use log::{debug, info}; use schemars::JsonSchema; @@ -49,8 +46,8 @@ pub(crate) async fn password_login( }), ); - let user_key = EncString::from_str(r.key.as_deref().unwrap()).unwrap(); - let private_key = EncString::from_str(r.private_key.as_deref().unwrap()).unwrap(); + let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); + let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); client.initialize_user_crypto(&input.password, user_key, private_key)?; } From e5d4521beb2bc0eb6b049c9a9bb05f6193c63789 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:10:52 +0200 Subject: [PATCH 016/378] Lock file maintenance (#302) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 118 +++++----- crates/bitwarden-napi/package-lock.json | 6 +- languages/js_webassembly/package-lock.json | 255 +++++++++++++-------- package-lock.json | 12 +- 4 files changed, 227 insertions(+), 164 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bb70fdf5..5bdbdc291 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -746,11 +746,11 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "7.0.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab77dbd8adecaf3f0db40581631b995f312a8a5ae3aa9993188bb8f23d83a5b" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ - "crossterm 0.26.1", + "crossterm 0.27.0", "strum", "strum_macros", "unicode-width", @@ -841,9 +841,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" dependencies = [ "libc", ] @@ -884,17 +884,14 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.26.1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "crossterm_winapi", "libc", - "mio", "parking_lot", - "signal-hook", - "signal-hook-mio", "winapi", ] @@ -1339,9 +1336,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -1460,7 +1457,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1482,16 +1479,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -1537,7 +1534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown 0.14.2", ] [[package]] @@ -1589,9 +1586,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" @@ -1682,9 +1679,9 @@ checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -2032,9 +2029,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2048,13 +2045,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -2156,9 +2153,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" +checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ "base64 0.21.4", "indexmap 1.9.3", @@ -2287,9 +2284,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", ] @@ -2392,6 +2389,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -2522,9 +2528,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" dependencies = [ "bitflags 2.4.1", "errno", @@ -2876,9 +2882,9 @@ checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2886,9 +2892,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -2930,21 +2936,21 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" [[package]] name = "strum_macros" -version = "0.24.3" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck", "proc-macro2", "quote", "rustversion", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -3027,9 +3033,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" @@ -3055,18 +3061,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -3139,7 +3145,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -3230,9 +3236,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-core", @@ -3489,9 +3495,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" dependencies = [ "serde", ] @@ -3693,10 +3699,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets 0.48.5", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 5a2945fd3..b0df11947 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "peer": true, "dependencies": { diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index 3c961135e..ea4d8b7f3 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -72,9 +72,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -88,9 +88,9 @@ "dev": true }, "node_modules/@types/body-parser": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.3.tgz", - "integrity": "sha512-oyl4jvAfTGX9Bt6Or4H9ni1Z447/tQuxnZsytsCaExKlmJiU8sFgnIBRzJUpKwB5eWn9HuBYlUlVA74q/yN0eQ==", + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", + "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", "dev": true, "dependencies": { "@types/connect": "*", @@ -98,27 +98,27 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.11.tgz", - "integrity": "sha512-isGhjmBtLIxdHBDl2xGwUzEM8AOyOvWsADWq7rqirdi/ZQoHnLWErHvsThcEzTX8juDRiZtzp2Qkv5bgNh6mAg==", + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", + "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.36", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz", - "integrity": "sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==", + "version": "3.4.37", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", + "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.1.tgz", - "integrity": "sha512-iaQslNbARe8fctL5Lk+DsmgWOM83lM+7FzP0eQUJs1jd3kBE8NWqBTIT2S8SqQOJjxvt2eyIjpOuYeRXq2AdMw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", + "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.4", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.4.tgz", - "integrity": "sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==", + "version": "8.44.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", + "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -136,9 +136,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", - "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", + "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -146,15 +146,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", - "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", + "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", "dev": true }, "node_modules/@types/express": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.19.tgz", - "integrity": "sha512-UtOfBtzN9OvpZPPbnnYunfjM7XCI4jyk1NvnFhTVz5krYAnW4o5DCoIekvms+8ApqhB4+9wSge1kBijdfTSmfg==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", + "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -164,9 +164,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.37", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.37.tgz", - "integrity": "sha512-ZohaCYTgGFcOP7u6aJOhY9uIZQgZ2vxC2yWoArY+FeDXlqeH66ZVBjgvg+RLVAS/DWNq4Ap9ZXu1+SUQiiWYMg==", + "version": "4.17.39", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", + "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", "dev": true, "dependencies": { "@types/node": "*", @@ -182,51 +182,51 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.2.tgz", - "integrity": "sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", + "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.12", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.12.tgz", - "integrity": "sha512-kQtujO08dVtQ2wXAuSFfk9ASy3sug4+ogFR8Kd8UgP8PEuc1/G/8yjYRmp//PcDNJEUKOza/MrQu15bouEUCiw==", + "version": "1.17.13", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", + "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/mime": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.3.tgz", - "integrity": "sha512-Ys+/St+2VF4+xuY6+kDIXGxbNRO0mesVg0bbxEfB97Od1Vjpjx9KD1qxs64Gcb3CWPirk9Xe+PT4YiiHQ9T+eg==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", + "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "dependencies": { "undici-types": "~5.25.1" } }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==", + "version": "6.9.9", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", + "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.5.tgz", - "integrity": "sha512-xrO9OoVPqFuYyR/loIHjnbvvyRZREYKLjxV4+dY6v3FQR3stQ9ZxIGkaclF7YhI9hfjpuTbu14hZEy94qKLtOA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", + "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", "dev": true }, "node_modules/@types/retry": { @@ -236,9 +236,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.2.tgz", - "integrity": "sha512-aAG6yRf6r0wQ29bkS+x97BIs64ZLxeE/ARwyS6wrldMm3C1MdKwCcnnEwMC1slI8wuxJOpiUH9MioC0A0i+GJw==", + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", + "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -246,18 +246,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.2.tgz", - "integrity": "sha512-asaEIoc6J+DbBKXtO7p2shWUpKacZOoMBEGBgPG91P8xhO53ohzHWGCs4ScZo5pQMf5ukQzVT9fhX1WzpHihig==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", + "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.3.tgz", - "integrity": "sha512-yVRvFsEMrv7s0lGhzrggJjNOSmZCdgCjw9xWrPr/kNNLp6FaDfMC1KaYl3TSJ0c58bECwNBMoQrZJ8hA8E1eFg==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", + "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -266,18 +266,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.34", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.34.tgz", - "integrity": "sha512-R+n7qBFnm/6jinlteC9DBL5dGiDGjWAvjo4viUanpnc/dG1y7uDoacXPIQ/PQEg1fI912SMHIa014ZjRpvDw4g==", + "version": "0.3.35", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", + "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/ws": { - "version": "8.5.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", - "integrity": "sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", + "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", "dev": true, "dependencies": { "@types/node": "*" @@ -803,13 +803,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -826,9 +827,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001549", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", - "integrity": "sha512-qRp48dPYSCYaP+KurZLhDYdVE+yEyht/3NlmcJgVQ2VMGt6JL36ndQ/7rgspdZsJuxDPFIo/OzBT2+GmIJ53BA==", + "version": "1.0.30001553", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", + "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", "dev": true, "funding": [ { @@ -1121,6 +1122,20 @@ "node": ">= 10" } }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -1254,9 +1269,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.554", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.554.tgz", - "integrity": "sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ==", + "version": "1.4.563", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", + "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", "dev": true }, "node_modules/encodeurl": { @@ -1644,15 +1659,15 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1708,6 +1723,18 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -1720,15 +1747,6 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1738,6 +1756,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", @@ -1762,6 +1792,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2045,12 +2087,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2532,9 +2574,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.0.tgz", - "integrity": "sha512-HQ4J+ic8hKrgIt3mqk6cVOVrW2ozL4KdvHlqpBv9vDYWx9ysAgENAdvy4FoGF+KFdhR7nQTNm5J0ctAeOwn+3g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3190,6 +3232,21 @@ "node": ">= 0.8.0" } }, + "node_modules/set-function-length": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", + "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", diff --git a/package-lock.json b/package-lock.json index ecbb207ad..0918c67ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.6.tgz", - "integrity": "sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ==", + "version": "20.8.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", + "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", "dev": true, "peer": true, "dependencies": { @@ -373,9 +373,9 @@ } }, "node_modules/@types/urijs": { - "version": "1.19.20", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.20.tgz", - "integrity": "sha512-77Mq/2BeHU894J364dUv9tSwxxyCLtcX228Pc8TwZpP5bvOoMns+gZoftp3LYl3FBH8vChpWbuagKGiMki2c1A==", + "version": "1.19.22", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.22.tgz", + "integrity": "sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==", "dev": true }, "node_modules/abort-controller": { From ba49283f1cb1e888e50d88335595fee35594ffbc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 09:30:02 -0400 Subject: [PATCH 017/378] Update gh minor (#300) --- .github/workflows/build-android.yml | 10 +++++----- .github/workflows/build-cli.yml | 12 ++++++------ .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-napi.yml | 4 ++-- .github/workflows/build-rust-crates.yml | 8 ++++---- .github/workflows/build-rust-cross-platform.yml | 4 ++-- .github/workflows/cloc.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 4 ++-- .github/workflows/generate_schemas.yml | 4 ++-- .github/workflows/lint.yml | 4 ++-- .github/workflows/publish-dotnet.yml | 2 +- .github/workflows/publish-rust-crates.yml | 6 +++--- .github/workflows/release-cli.yml | 6 +++--- .github/workflows/release-napi.yml | 4 ++-- .github/workflows/rust-test.yml | 8 ++++---- .github/workflows/version-bump.yml | 4 ++-- 16 files changed, 42 insertions(+), 42 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 4fd1cc975..110e3758b 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -25,7 +25,7 @@ jobs: - target: i686-linux-android steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -33,7 +33,7 @@ jobs: toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo @@ -57,14 +57,14 @@ jobs: needs: build steps: - name: Checkout repo (PR) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'pull_request' with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.ref }} - name: Checkout repo (Push) - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 if: github.event_name == 'push' with: fetch-depth: 0 @@ -75,7 +75,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-combine-cache diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 624a69c4f..9aa39ab51 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -22,7 +22,7 @@ jobs: package_version: ${{ steps.retrieve-version.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get Package Version id: retrieve-version @@ -60,7 +60,7 @@ jobs: target: aarch64-unknown-linux-gnu steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -69,7 +69,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} @@ -115,7 +115,7 @@ jobs: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -155,7 +155,7 @@ jobs: - setup steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -163,7 +163,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: cargo-cli-about diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 608e8c47d..272fec363 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index b55ef939f..45fab6703 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -51,7 +51,7 @@ jobs: strip *.node steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 @@ -67,7 +67,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 0b868367d..203276556 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -43,7 +43,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Build run: cargo build -p ${{ matrix.package }} --release @@ -64,7 +64,7 @@ jobs: - build steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -73,7 +73,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 007cf5d17..7cfa9b078 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -30,7 +30,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Add build architecture run: rustup target add ${{ matrix.settings.target }} diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index 48f72ff65..a3afad257 100644 --- a/.github/workflows/cloc.yml +++ b/.github/workflows/cloc.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up cloc run: | diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 579817c49..b2085892a 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -45,7 +45,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 with: key: dmv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 9b2ac57c3..cac5bc2b8 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -31,7 +31,7 @@ jobs: run: npm ci - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: NPM Schemas run: npm run schemas diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 425f4e83a..a18e5064a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -25,7 +25,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Cargo fmt run: cargo fmt --check diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 7c819986e..c86b90dd1 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -23,7 +23,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 2c30e0fde..1c5484a5c 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -43,7 +43,7 @@ jobs: packages_command: ${{ steps.packages-list.outputs.packages_command }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -100,7 +100,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -120,7 +120,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 234b43aed..3651e14bc 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -27,7 +27,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -125,7 +125,7 @@ jobs: - setup steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -145,7 +145,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index cff308754..ee0407587 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -33,7 +33,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -90,7 +90,7 @@ jobs: _PKG_VERSION: ${{ needs.setup.outputs.release-version }} steps: - name: Checkout repo - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index f77cb29f6..d4177bea1 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -44,7 +44,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Test run: cargo test --all-features @@ -56,7 +56,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -65,7 +65,7 @@ jobs: targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Check run: cargo check -p bitwarden-wasm --target wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index fd651e2b2..29ee28f80 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Branch - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable @@ -37,7 +37,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@a95ba195448af2da9b00fb742d14ffaaf3c21f43 # v2.7.0 + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 - name: Install cargo-release run: cargo install cargo-edit From b2ae2722b5c7a7a34c8e1d5859524f88068b2edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 30 Oct 2023 16:39:03 +0100 Subject: [PATCH 018/378] Split Encryptable/Decryptable trait into encryption and key retrieval (#297) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective At the moment, the `Encryptable`/`Decryptable` trait handles both encryption/decryption and key retrieval. The goal of this PR is to split this trait into two parts, one part that only handles encryption/decryption (and thus will be able to be moved into a separate `bitwarden-crypto` crate, if we want), and another part that handles retrieving the corresponding encryption key for each model object. ## Code changes What was the `Encryptable`/`Decryptable` trait has been split into multiple parts: - `KeyEncryptable`/`KeyDecryptable`: This receives only the encryption key and handles encryption/decryption only. The name of the interface was chosen to match the current `EncString::decrypt_with_key`, which this replaces. - `LocateKey`, which is implemented by types that know the type of key they need. For example a `Folder` always uses the user key and a `Cipher` uses the user key or one of the organization keys depending on its `organization_id` field. - `Encryptable`/`Decryptable`, this is now a thin compatibility layer between the previously mentioned two, to keep the existing API for the moment and keep the changes in this PR to a minimum. In the future we might decide that it's not necessary. With these changes, any models should implement `KeyEncryptable`/`KeyDecryptable` only, and `LocateKey` if applicable, but never `Encryptable`/`Decryptable` directly. Some of these changes will be more fleshed out in the future to avoid cluttering this PR, so I expect this won't look perfect: - Both `LocateKey` and `Encryptable` have an interface like `enc: &EncryptionSettings, org_id: &Option`. The organization parameter is mostly superfluous now and will be removed in the future: Objects that implement `LocateKey` do not use it, while objects which don't implement it should be provided the keys directly. - `EncString` is implementing `LocateKey` now, which goes against the explanation above. This is to avoid refactoring some secrets manager code, which I'll do on a later PR. - `EncryptionSettings` will change in the future, specially the `get_key` implementation, to be more generic. It also contains an `encrypt` function that shouldn't be there, but is used in a couple of spots of the code base and I'll remove on a later PR. - `KeyEncryptable`/`KeyDecryptable` only handles `SymmetricCryptoKey`, this will be made more generic over key type. --- .../bitwarden/src/auth/login/access_token.rs | 4 +- .../src/client/encryption_settings.rs | 38 +------ crates/bitwarden/src/crypto/enc_string.rs | 57 +++++++--- crates/bitwarden/src/crypto/encryptable.rs | 47 ++++---- .../bitwarden/src/crypto/key_encryptable.rs | 69 ++++++++++++ crates/bitwarden/src/crypto/master_key.rs | 6 +- crates/bitwarden/src/crypto/mod.rs | 4 +- .../src/mobile/vault/client_sends.rs | 22 ++-- .../bitwarden/src/vault/cipher/attachment.rs | 20 ++-- crates/bitwarden/src/vault/cipher/card.rs | 36 +++--- crates/bitwarden/src/vault/cipher/cipher.rs | 99 ++++++++++------- crates/bitwarden/src/vault/cipher/field.rs | 20 ++-- crates/bitwarden/src/vault/cipher/identity.rs | 84 +++++++------- .../bitwarden/src/vault/cipher/local_data.rs | 12 +- crates/bitwarden/src/vault/cipher/login.rs | 40 ++++--- .../bitwarden/src/vault/cipher/secure_note.rs | 12 +- crates/bitwarden/src/vault/collection.rs | 19 +++- crates/bitwarden/src/vault/folder.rs | 17 +-- .../bitwarden/src/vault/password_history.rs | 22 ++-- crates/bitwarden/src/vault/send.rs | 103 ++++++++---------- 20 files changed, 398 insertions(+), 333 deletions(-) create mode 100644 crates/bitwarden/src/crypto/key_encryptable.rs diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 63fd86ebb..e7d60951c 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -8,7 +8,7 @@ use crate::{ login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, util::{decode_token, BASE64_ENGINE}, Client, @@ -29,7 +29,7 @@ pub(crate) async fn access_token_login( // Extract the encrypted payload and use the access token encryption key to decrypt it let payload: EncString = r.encrypted_payload.parse()?; - let decrypted_payload = payload.decrypt_with_key(&access_token.encryption_key)?; + let decrypted_payload: Vec = payload.decrypt_with_key(&access_token.encryption_key)?; // Once decrypted, we have to JSON decode to extract the organization encryption key #[derive(serde::Deserialize)] diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 9c79a1781..e6cf3e145 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -4,7 +4,7 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::client::UserLoginMethod, + crate::{client::UserLoginMethod, crypto::KeyDecryptable}, rsa::{pkcs8::DecodePrivateKey, Oaep}, }; @@ -46,7 +46,7 @@ impl EncryptionSettings { // Decrypt the private key with the user key let private_key = { - let dec = private_key.decrypt_with_key(&user_key)?; + let dec: Vec = private_key.decrypt_with_key(&user_key)?; Some( rsa::RsaPrivateKey::from_pkcs8_der(&dec) .map_err(|_| CryptoError::InvalidKey)?, @@ -98,7 +98,7 @@ impl EncryptionSettings { Ok(self) } - fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { + pub(crate) fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { // If we don't have a private key set (to decode multiple org keys), we just use the main user key if self.private_key.is_none() { return Some(&self.user_key); @@ -110,20 +110,6 @@ impl EncryptionSettings { } } - pub(crate) fn decrypt_bytes( - &self, - cipher: &EncString, - org_id: &Option, - ) -> Result> { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - cipher.decrypt_with_key(key) - } - - pub(crate) fn decrypt(&self, cipher: &EncString, org_id: &Option) -> Result { - let dec = self.decrypt_bytes(cipher, org_id)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) - } - pub(crate) fn encrypt(&self, data: &[u8], org_id: &Option) -> Result { let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; @@ -131,21 +117,3 @@ impl EncryptionSettings { Ok(dec) } } - -#[cfg(test)] -mod tests { - use super::{EncryptionSettings, SymmetricCryptoKey}; - use crate::crypto::{Decryptable, Encryptable}; - - #[test] - fn test_encryption_settings() { - let key = SymmetricCryptoKey::generate("test"); - let settings = EncryptionSettings::new_single_key(key); - - let test_string = "encrypted_test_string".to_string(); - let cipher = test_string.clone().encrypt(&settings, &None).unwrap(); - - let decrypted_str = cipher.decrypt(&settings, &None).unwrap(); - assert_eq!(decrypted_str, test_string); - } -} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index b701aaf8f..976065e60 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -2,15 +2,15 @@ use std::{fmt::Display, str::FromStr}; use base64::Engine; use serde::{de::Visitor, Deserialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{decrypt_aes256_hmac, Decryptable, Encryptable, SymmetricCryptoKey}, + crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; +use super::{KeyDecryptable, KeyEncryptable, LocateKey}; + #[derive(Clone)] #[allow(unused, non_camel_case_types)] pub enum EncString { @@ -304,8 +304,24 @@ impl EncString { EncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, } } +} - pub fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { +fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { + move |e: Vec<_>| EncStringParseError::InvalidLength { + expected, + got: e.len(), + } +} + +impl LocateKey for EncString {} +impl KeyEncryptable for &[u8] { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + super::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + } +} + +impl KeyDecryptable> for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; @@ -317,29 +333,36 @@ impl EncString { } } -fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { - move |e: Vec<_>| EncStringParseError::InvalidLength { - expected, - got: e.len(), - } -} - -impl Encryptable for String { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.encrypt(self.as_bytes(), org_id) +impl KeyEncryptable for String { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + self.as_bytes().encrypt_with_key(key) } } -impl Decryptable for EncString { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - enc.decrypt(self, org_id) +impl KeyDecryptable for EncString { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let dec: Vec = self.decrypt_with_key(key)?; + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) } } #[cfg(test)] mod tests { + use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use super::EncString; + #[test] + fn test_enc_string_roundtrip() { + let key = SymmetricCryptoKey::generate("test"); + + let test_string = "encrypted_test_string".to_string(); + let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); + + let decrypted_str: String = cipher.decrypt_with_key(&key).unwrap(); + assert_eq!(decrypted_str, test_string); + } + #[test] fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index bd987060f..10dbfaac6 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -2,7 +2,22 @@ use std::{collections::HashMap, hash::Hash}; use uuid::Uuid; -use crate::{client::encryption_settings::EncryptionSettings, error::Result}; +use crate::{ + client::encryption_settings::EncryptionSettings, + error::{Error, Result}, +}; + +use super::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + +pub trait LocateKey { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + org_id: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(org_id) + } +} pub trait Encryptable { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; @@ -12,15 +27,17 @@ pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } -impl, Output> Encryptable> for Option { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.map(|e| e.encrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Encryptable for T { + fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.encrypt_with_key(key) } } -impl, Output> Decryptable> for Option { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result> { - self.as_ref().map(|e| e.decrypt(enc, org_id)).transpose() +impl + LocateKey, Output> Decryptable for T { + fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { + let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + self.decrypt_with_key(key) } } @@ -46,7 +63,7 @@ impl, Output, Id: Hash + Eq> Encryptable Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) - .collect::>>() + .collect() } } @@ -60,18 +77,6 @@ impl, Output, Id: Hash + Eq + Copy> Decryptable Result> { self.iter() .map(|(id, e)| Ok((*id, e.decrypt(enc, org_id)?))) - .collect::>>() - } -} - -impl, Output> Encryptable for Box { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (*self).encrypt(enc, org_id) - } -} - -impl, Output> Decryptable for Box { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - (**self).decrypt(enc, org_id) + .collect() } } diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden/src/crypto/key_encryptable.rs new file mode 100644 index 000000000..99c610bb2 --- /dev/null +++ b/crates/bitwarden/src/crypto/key_encryptable.rs @@ -0,0 +1,69 @@ +use std::{collections::HashMap, hash::Hash}; + +use crate::error::Result; + +use super::SymmetricCryptoKey; + +pub trait KeyEncryptable { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; +} + +pub trait KeyDecryptable { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result; +} + +impl, Output> KeyEncryptable> for Option { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.map(|e| e.encrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyDecryptable> for Option { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.as_ref().map(|e| e.decrypt_with_key(key)).transpose() + } +} + +impl, Output> KeyEncryptable for Box { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + (*self).encrypt_with_key(key) + } +} + +impl, Output> KeyDecryptable for Box { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + (**self).decrypt_with_key(key) + } +} + +impl, Output> KeyEncryptable> for Vec { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter().map(|e| e.encrypt_with_key(key)).collect() + } +} + +impl, Output> KeyDecryptable> for Vec { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter().map(|e| e.decrypt_with_key(key)).collect() + } +} + +impl, Output, Id: Hash + Eq> KeyEncryptable> + for HashMap +{ + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + self.into_iter() + .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?))) + .collect() + } +} + +impl, Output, Id: Hash + Eq + Copy> KeyDecryptable> + for HashMap +{ + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + self.iter() + .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?))) + .collect() + } +} diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index f908d5299..064336edb 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256, hkdf_expand, EncString, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, - PBKDF_SHA256_HMAC_OUT_SIZE, + encrypt_aes256, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, + UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -53,7 +53,7 @@ impl MasterKey { pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; - let dec = user_key.decrypt_with_key(&stretched_key)?; + let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_slice()) } } diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index b35157981..d8a1f0557 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -29,7 +29,9 @@ use crate::error::{Error, Result}; mod enc_string; pub use enc_string::EncString; mod encryptable; -pub use encryptable::{Decryptable, Encryptable}; +pub use encryptable::{Decryptable, Encryptable, LocateKey}; +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; mod aes_ops; pub use aes_ops::{decrypt_aes256, decrypt_aes256_hmac, encrypt_aes256, encrypt_aes256_hmac}; mod symmetric_crypto_key; diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index 0adef3410..b1de05f44 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -2,8 +2,8 @@ use std::path::Path; use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, EncString, Encryptable}, - error::Result, + crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}, + error::{Error, Result}, vault::{Send, SendListView, SendView}, Client, }; @@ -43,11 +43,11 @@ impl<'a> ClientSends<'a> { pub async fn decrypt_buffer(&self, send: Send, encrypted_buffer: &[u8]) -> Result> { let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; + let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; let buf = EncString::from_buffer(encrypted_buffer)?; - - enc.decrypt_bytes(&buf, &None) + buf.decrypt_with_key(&key) } pub async fn encrypt(&self, send_view: SendView) -> Result { @@ -71,10 +71,14 @@ impl<'a> ClientSends<'a> { } pub async fn encrypt_buffer(&self, send: Send, buffer: &[u8]) -> Result> { - let enc = self.client.get_encryption_settings()?; - let enc = Send::get_encryption(&send.key, enc, &None)?; - - let enc = enc.encrypt(buffer, &None)?; + let key = self + .client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + let key = Send::get_key(&send.key, key)?; + + let enc = buffer.encrypt_with_key(&key)?; enc.to_buffer() } } diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 143e2a4f9..101c8f4bc 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -33,28 +31,28 @@ pub struct AttachmentView { pub key: Option, } -impl Encryptable for AttachmentView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for AttachmentView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, url: self.url, size: self.size, size_name: self.size_name, - file_name: self.file_name.encrypt(enc, org_id)?, - key: self.key.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, + key: self.key.encrypt_with_key(key)?, }) } } -impl Decryptable for Attachment { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Attachment { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), size: self.size.clone(), size_name: self.size_name.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, - key: self.key.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, + key: self.key.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 9636ba83f..1545ad171 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -32,28 +30,28 @@ pub struct CardView { pub number: Option, } -impl Encryptable for CardView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for CardView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { - cardholder_name: self.cardholder_name.encrypt(enc, org_id)?, - exp_month: self.exp_month.encrypt(enc, org_id)?, - exp_year: self.exp_year.encrypt(enc, org_id)?, - code: self.code.encrypt(enc, org_id)?, - brand: self.brand.encrypt(enc, org_id)?, - number: self.number.encrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.encrypt_with_key(key)?, + exp_month: self.exp_month.encrypt_with_key(key)?, + exp_year: self.exp_year.encrypt_with_key(key)?, + code: self.code.encrypt_with_key(key)?, + brand: self.brand.encrypt_with_key(key)?, + number: self.number.encrypt_with_key(key)?, }) } } -impl Decryptable for Card { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Card { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { - cardholder_name: self.cardholder_name.decrypt(enc, org_id)?, - exp_month: self.exp_month.decrypt(enc, org_id)?, - exp_year: self.exp_year.decrypt(enc, org_id)?, - code: self.code.decrypt(enc, org_id)?, - brand: self.brand.decrypt(enc, org_id)?, - number: self.number.decrypt(enc, org_id)?, + cardholder_name: self.cardholder_name.decrypt_with_key(key)?, + exp_month: self.exp_month.decrypt_with_key(key)?, + exp_year: self.exp_year.decrypt_with_key(key)?, + code: self.code.decrypt_with_key(key)?, + brand: self.brand.decrypt_with_key(key)?, + number: self.number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 9bf4bbd25..b01f17136 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -11,7 +11,7 @@ use super::{ }; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, vault::password_history, }; @@ -129,30 +129,29 @@ pub struct CipherListView { pub revision_date: DateTime, } -impl Encryptable for CipherView { - fn encrypt(self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyEncryptable for CipherView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(key)?, + notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, - login: self.login.encrypt(enc, org_id)?, - identity: self.identity.encrypt(enc, org_id)?, - card: self.card.encrypt(enc, org_id)?, - secure_note: self.secure_note.encrypt(enc, org_id)?, + login: self.login.encrypt_with_key(key)?, + identity: self.identity.encrypt_with_key(key)?, + card: self.card.encrypt_with_key(key)?, + secure_note: self.secure_note.encrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.encrypt(enc, org_id)?, - attachments: self.attachments.encrypt(enc, org_id)?, - fields: self.fields.encrypt(enc, org_id)?, - password_history: self.password_history.encrypt(enc, org_id)?, + local_data: self.local_data.encrypt_with_key(key)?, + attachments: self.attachments.encrypt_with_key(key)?, + fields: self.fields.encrypt_with_key(key)?, + password_history: self.password_history.encrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -160,30 +159,29 @@ impl Encryptable for CipherView { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, - login: self.login.decrypt(enc, org_id)?, - identity: self.identity.decrypt(enc, org_id)?, - card: self.card.decrypt(enc, org_id)?, - secure_note: self.secure_note.decrypt(enc, org_id)?, + login: self.login.decrypt_with_key(key)?, + identity: self.identity.decrypt_with_key(key)?, + card: self.card.decrypt_with_key(key)?, + secure_note: self.secure_note.decrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.decrypt(enc, org_id)?, - attachments: self.attachments.decrypt(enc, org_id)?, - fields: self.fields.decrypt(enc, org_id)?, - password_history: self.password_history.decrypt(enc, org_id)?, + local_data: self.local_data.decrypt_with_key(key)?, + attachments: self.attachments.decrypt_with_key(key)?, + fields: self.fields.decrypt_with_key(key)?, + password_history: self.password_history.decrypt_with_key(key)?, creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -192,17 +190,13 @@ impl Decryptable for Cipher { } impl Cipher { - fn get_decrypted_subtitle( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { return Ok(String::new()); }; - login.username.decrypt(enc, org_id)?.unwrap_or_default() + login.username.decrypt_with_key(key)?.unwrap_or_default() } CipherType::SecureNote => String::new(), CipherType::Card => { @@ -212,11 +206,12 @@ impl Cipher { let mut sub_title = String::new(); if let Some(brand) = &card.brand { - sub_title.push_str(&brand.decrypt(enc, org_id)?); + let brand: String = brand.decrypt_with_key(key)?; + sub_title.push_str(&brand); } if let Some(number) = &card.number { - let number = number.decrypt(enc, org_id)?; + let number: String = number.decrypt_with_key(key)?; let number_len = number.len(); if number_len > 4 { if !sub_title.is_empty() { @@ -242,14 +237,16 @@ impl Cipher { let mut sub_title = String::new(); if let Some(first_name) = &identity.first_name { - sub_title.push_str(&first_name.decrypt(enc, org_id)?); + let first_name: String = first_name.decrypt_with_key(key)?; + sub_title.push_str(&first_name); } if let Some(last_name) = &identity.last_name { if !sub_title.is_empty() { sub_title.push(' '); } - sub_title.push_str(&last_name.decrypt(enc, org_id)?); + let last_name: String = last_name.decrypt_with_key(key)?; + sub_title.push_str(&last_name); } sub_title @@ -258,16 +255,15 @@ impl Cipher { } } -impl Decryptable for Cipher { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = &self.organization_id; +impl KeyDecryptable for Cipher { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CipherListView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt(enc, org_id)?, - sub_title: self.get_decrypted_subtitle(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + sub_title: self.get_decrypted_subtitle(key)?, r#type: self.r#type, favorite: self.favorite, reprompt: self.reprompt, @@ -284,3 +280,22 @@ impl Decryptable for Cipher { }) } } + +impl LocateKey for Cipher { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} +impl LocateKey for CipherView { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&self.organization_id) + } +} diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 9fa05257a..13f7dc9bb 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,12 +1,10 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use super::linked_id::LinkedIdType; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -42,22 +40,22 @@ pub struct FieldView { linked_id: Option, } -impl Encryptable for FieldView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for FieldView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { - name: self.name.encrypt(enc, org_id)?, - value: self.value.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(key)?, + value: self.value.encrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) } } -impl Decryptable for Field { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Field { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { - name: self.name.decrypt(enc, org_id)?, - value: self.value.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(key)?, + value: self.value.decrypt_with_key(key)?, r#type: self.r#type, linked_id: self.linked_id, }) diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index aace84152..d40991866 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -56,52 +54,52 @@ pub struct IdentityView { pub license_number: Option, } -impl Encryptable for IdentityView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for IdentityView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { - title: self.title.encrypt(enc, org_id)?, - first_name: self.first_name.encrypt(enc, org_id)?, - middle_name: self.middle_name.encrypt(enc, org_id)?, - last_name: self.last_name.encrypt(enc, org_id)?, - address1: self.address1.encrypt(enc, org_id)?, - address2: self.address2.encrypt(enc, org_id)?, - address3: self.address3.encrypt(enc, org_id)?, - city: self.city.encrypt(enc, org_id)?, - state: self.state.encrypt(enc, org_id)?, - postal_code: self.postal_code.encrypt(enc, org_id)?, - country: self.country.encrypt(enc, org_id)?, - company: self.company.encrypt(enc, org_id)?, - email: self.email.encrypt(enc, org_id)?, - phone: self.phone.encrypt(enc, org_id)?, - ssn: self.ssn.encrypt(enc, org_id)?, - username: self.username.encrypt(enc, org_id)?, - passport_number: self.passport_number.encrypt(enc, org_id)?, - license_number: self.license_number.encrypt(enc, org_id)?, + title: self.title.encrypt_with_key(key)?, + first_name: self.first_name.encrypt_with_key(key)?, + middle_name: self.middle_name.encrypt_with_key(key)?, + last_name: self.last_name.encrypt_with_key(key)?, + address1: self.address1.encrypt_with_key(key)?, + address2: self.address2.encrypt_with_key(key)?, + address3: self.address3.encrypt_with_key(key)?, + city: self.city.encrypt_with_key(key)?, + state: self.state.encrypt_with_key(key)?, + postal_code: self.postal_code.encrypt_with_key(key)?, + country: self.country.encrypt_with_key(key)?, + company: self.company.encrypt_with_key(key)?, + email: self.email.encrypt_with_key(key)?, + phone: self.phone.encrypt_with_key(key)?, + ssn: self.ssn.encrypt_with_key(key)?, + username: self.username.encrypt_with_key(key)?, + passport_number: self.passport_number.encrypt_with_key(key)?, + license_number: self.license_number.encrypt_with_key(key)?, }) } } -impl Decryptable for Identity { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Identity { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { - title: self.title.decrypt(enc, org_id)?, - first_name: self.first_name.decrypt(enc, org_id)?, - middle_name: self.middle_name.decrypt(enc, org_id)?, - last_name: self.last_name.decrypt(enc, org_id)?, - address1: self.address1.decrypt(enc, org_id)?, - address2: self.address2.decrypt(enc, org_id)?, - address3: self.address3.decrypt(enc, org_id)?, - city: self.city.decrypt(enc, org_id)?, - state: self.state.decrypt(enc, org_id)?, - postal_code: self.postal_code.decrypt(enc, org_id)?, - country: self.country.decrypt(enc, org_id)?, - company: self.company.decrypt(enc, org_id)?, - email: self.email.decrypt(enc, org_id)?, - phone: self.phone.decrypt(enc, org_id)?, - ssn: self.ssn.decrypt(enc, org_id)?, - username: self.username.decrypt(enc, org_id)?, - passport_number: self.passport_number.decrypt(enc, org_id)?, - license_number: self.license_number.decrypt(enc, org_id)?, + title: self.title.decrypt_with_key(key)?, + first_name: self.first_name.decrypt_with_key(key)?, + middle_name: self.middle_name.decrypt_with_key(key)?, + last_name: self.last_name.decrypt_with_key(key)?, + address1: self.address1.decrypt_with_key(key)?, + address2: self.address2.decrypt_with_key(key)?, + address3: self.address3.decrypt_with_key(key)?, + city: self.city.decrypt_with_key(key)?, + state: self.state.decrypt_with_key(key)?, + postal_code: self.postal_code.decrypt_with_key(key)?, + country: self.country.decrypt_with_key(key)?, + company: self.company.decrypt_with_key(key)?, + email: self.email.decrypt_with_key(key)?, + phone: self.phone.decrypt_with_key(key)?, + ssn: self.ssn.decrypt_with_key(key)?, + username: self.username.decrypt_with_key(key)?, + passport_number: self.passport_number.decrypt_with_key(key)?, + license_number: self.license_number.decrypt_with_key(key)?, }) } } diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index 1811ffa8b..8d5fe8694 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,10 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -24,8 +22,8 @@ pub struct LocalDataView { last_launched: Option, } -impl Encryptable for LocalDataView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for LocalDataView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -33,8 +31,8 @@ impl Encryptable for LocalDataView { } } -impl Decryptable for LocalData { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for LocalData { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 941aed221..7a8e18411 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -2,11 +2,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -65,45 +63,45 @@ pub struct LoginView { pub autofill_on_page_load: Option, } -impl Encryptable for LoginUriView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginUriView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { - uri: self.uri.encrypt(enc, org_id)?, + uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Encryptable for LoginView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for LoginView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { - username: self.username.encrypt(enc, org_id)?, - password: self.password.encrypt(enc, org_id)?, + username: self.username.encrypt_with_key(key)?, + password: self.password.encrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.encrypt(enc, org_id)?, - totp: self.totp.encrypt(enc, org_id)?, + uris: self.uris.encrypt_with_key(key)?, + totp: self.totp.encrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } } -impl Decryptable for LoginUri { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for LoginUri { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { - uri: self.uri.decrypt(enc, org_id)?, + uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, }) } } -impl Decryptable for Login { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Login { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { - username: self.username.decrypt(enc, org_id)?, - password: self.password.decrypt(enc, org_id)?, + username: self.username.decrypt_with_key(key)?, + password: self.password.decrypt_with_key(key)?, password_revision_date: self.password_revision_date, - uris: self.uris.decrypt(enc, org_id)?, - totp: self.totp.decrypt(enc, org_id)?, + uris: self.uris.decrypt_with_key(key)?, + totp: self.totp.decrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, }) } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 422a55da1..0c7b4c799 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,11 +1,9 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, Encryptable}, + crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, error::Result, }; @@ -30,16 +28,16 @@ pub struct SecureNoteView { r#type: SecureNoteType, } -impl Encryptable for SecureNoteView { - fn encrypt(self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyEncryptable for SecureNoteView { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, }) } } -impl Decryptable for SecureNote { - fn decrypt(&self, _enc: &EncryptionSettings, _org_id: &Option) -> Result { +impl KeyDecryptable for SecureNote { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 38863a946..58492ef17 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -4,7 +4,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, + crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -36,15 +36,22 @@ pub struct CollectionView { read_only: bool, } -impl Decryptable for Collection { - fn decrypt(&self, enc: &EncryptionSettings, _: &Option) -> Result { - let org_id = Some(self.organization_id); - +impl LocateKey for Collection { + fn locate_key<'a>( + &self, + enc: &'a EncryptionSettings, + _: &Option, + ) -> Option<&'a SymmetricCryptoKey> { + enc.get_key(&Some(self.organization_id)) + } +} +impl KeyDecryptable for Collection { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, - name: self.name.decrypt(enc, &org_id)?, + name: self.name.decrypt_with_key(key)?, external_id: self.external_id.clone(), hide_passwords: self.hide_passwords, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 97d861310..f9ae06055 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -4,8 +4,7 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -27,21 +26,23 @@ pub struct FolderView { revision_date: DateTime, } -impl Encryptable for FolderView { - fn encrypt(self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for FolderView {} +impl KeyEncryptable for FolderView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, - name: self.name.encrypt(enc, &None)?, + name: self.name.encrypt_with_key(key)?, revision_date: self.revision_date, }) } } -impl Decryptable for Folder { - fn decrypt(&self, enc: &EncryptionSettings, _org: &Option) -> Result { +impl LocateKey for Folder {} +impl KeyDecryptable for Folder { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, - name: self.name.decrypt(enc, &None)?, + name: self.name.decrypt_with_key(key)?, revision_date: self.revision_date, }) } diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 8566c9870..da6a4b19e 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,11 +1,9 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString, Encryptable}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::Result, }; @@ -25,23 +23,21 @@ pub struct PasswordHistoryView { last_used_date: DateTime, } -impl Encryptable for PasswordHistoryView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for PasswordHistoryView {} +impl KeyEncryptable for PasswordHistoryView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { - password: self.password.encrypt(enc, org_id)?, + password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, }) } } -impl Decryptable for PasswordHistory { - fn decrypt( - &self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { +impl LocateKey for PasswordHistory {} +impl KeyDecryptable for PasswordHistory { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistoryView { - password: self.password.decrypt(enc, org_id)?, + password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, }) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 124b9dc2f..5c463a0cf 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -5,8 +5,10 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{derive_shareable_key, Decryptable, EncString, Encryptable, SymmetricCryptoKey}, + crypto::{ + derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, + }, error::Result, }; @@ -126,86 +128,75 @@ pub struct SendListView { } impl Send { - fn get_key( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, + pub(crate) fn get_key( + send_key: &EncString, + enc_key: &SymmetricCryptoKey, ) -> Result { - let key: Vec = enc.decrypt_bytes(key, org_id)?; + let key: Vec = send_key.decrypt_with_key(enc_key)?; let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); Ok(key) } - - pub(crate) fn get_encryption( - key: &EncString, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result { - let key = Send::get_key(key, enc, org_id)?; - Ok(EncryptionSettings::new_single_key(key)) - } } -impl Decryptable for SendText { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendText { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { - text: self.text.decrypt(enc, org_id)?, + text: self.text.decrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Encryptable for SendTextView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendTextView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { - text: self.text.encrypt(enc, org_id)?, + text: self.text.encrypt_with_key(key)?, hidden: self.hidden, }) } } -impl Decryptable for SendFile { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for SendFile { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), - file_name: self.file_name.decrypt(enc, org_id)?, + file_name: self.file_name.decrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Encryptable for SendFileView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyEncryptable for SendFileView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), - file_name: self.file_name.encrypt(enc, org_id)?, + file_name: self.file_name.encrypt_with_key(key)?, size: self.size.clone(), size_name: self.size_name.clone(), }) } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for Send {} +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, - notes: self.notes.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, + notes: self.notes.decrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.decrypt(enc, org_id)?, - text: self.text.decrypt(enc, org_id)?, + file: self.file.decrypt_with_key(&key)?, + text: self.text.decrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -219,19 +210,17 @@ impl Decryptable for Send { } } -impl Decryptable for Send { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl KeyDecryptable for Send { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let enc_owned = Send::get_encryption(&self.key, enc, org_id)?; - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(SendListView { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt(enc, org_id)?, + name: self.name.decrypt_with_key(&key)?, r#type: self.r#type, disabled: self.disabled, @@ -243,27 +232,25 @@ impl Decryptable for Send { } } -impl Encryptable for SendView { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { +impl LocateKey for SendView {} +impl KeyEncryptable for SendView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - let key = Send::get_key(&self.key, enc, org_id)?; - let enc_owned = EncryptionSettings::new_single_key(key); - - // For the rest of the fields, we ignore the provided EncryptionSettings and use a new one with the stretched key - let enc = &enc_owned; + // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + let key = Send::get_key(&self.key, key)?; Ok(Send { id: self.id, access_id: self.access_id, - name: self.name.encrypt(enc, org_id)?, - notes: self.notes.encrypt(enc, org_id)?, + name: self.name.encrypt_with_key(&key)?, + notes: self.notes.encrypt_with_key(&key)?, key: self.key.clone(), password: self.password.clone(), r#type: self.r#type, - file: self.file.encrypt(enc, org_id)?, - text: self.text.encrypt(enc, org_id)?, + file: self.file.encrypt_with_key(&key)?, + text: self.text.encrypt_with_key(&key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -298,6 +285,8 @@ mod tests { "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw=".parse().unwrap(), ).unwrap(); + let k = enc.get_key(&None).unwrap(); + // Create a send object, the only value we really care about here is the key let send = Send { id: "d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap(), @@ -330,7 +319,7 @@ mod tests { }; // Get the send key - let send_key = Send::get_key(&send.key, &enc, &None).unwrap(); + let send_key = Send::get_key(&send.key, k).unwrap(); let send_key_b64 = send_key.to_base64(); assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } From a9d52f0e670a5fc732de5dbdede14f43acb41b12 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:39:56 +0100 Subject: [PATCH 019/378] Update Rust crate async-lock to v3 (#310) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-lock](https://togithub.com/smol-rs/async-lock) | dependencies | major | `2.7.0` -> `3.0.0` | --- ### Release Notes
smol-rs/async-lock (async-lock) ### [`v3.0.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-300) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v2.8.0...v3.0.0) - **Breaking:** Add an enabled-by-default `std` feature that allows using this crate without the standard library. ([#​43](https://togithub.com/smol-rs/async-lock/issues/43)) - Support blocking and non-blocking operations on the same locks. ([#​56](https://togithub.com/smol-rs/async-lock/issues/56)) - Switch to a more efficient event notification mechanism. ([#​43](https://togithub.com/smol-rs/async-lock/issues/43)) ### [`v2.8.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-280) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v2.7.0...v2.8.0) - Fix a bug where the `SemaphoreGuard::acquire_arc` future would busy wait under certain conditions ([#​42](https://togithub.com/smol-rs/async-lock/issues/42)). - Add a `Semaphore::add_permits()` function to increase the number of available permits on the semaphore ([#​44](https://togithub.com/smol-rs/async-lock/issues/44)). - Make `RwLockReadGuard` covariant over its lifetime ([#​45](https://togithub.com/smol-rs/async-lock/issues/45)) - Add `RwLockReadGuardArc`, `RwLockWriteGuardArc`, and other reference counted guards for the `RwLock` type ([#​47](https://togithub.com/smol-rs/async-lock/issues/47)). - Loosen the `Send`/`Sync` bounds on certain future types ([#​48](https://togithub.com/smol-rs/async-lock/issues/48)). - Fix UB caused by the `MutexGuardArc::source` function allowing the user to drop an object in a different thread than the one it was acquired in ([#​50](https://togithub.com/smol-rs/async-lock/issues/50)). This is a breaking change, but in the name of soundness. Therefore it doesn't break any valid behavior. - Fix a bug where this crate would not compile properly on `wasm64` ([#​51](https://togithub.com/smol-rs/async-lock/issues/51)).
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 31 ++++++++++++++++++++++++++---- crates/bitwarden-uniffi/Cargo.toml | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bdbdc291..8cd3063db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,17 +197,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-lock" -version = "2.8.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener", + "event-listener 3.0.0", + "event-listener-strategy", + "pin-project-lite", ] [[package]] @@ -1058,6 +1060,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +dependencies = [ + "event-listener 3.0.0", + "pin-project-lite", +] + [[package]] name = "eyre" version = "0.6.8" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 60228c104..759e84e19 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "2.7.0" +async-lock = "3.0.0" chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", From 6754c7d704c6cda65dd2dddc21e2aba1170e586c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:04:24 +0100 Subject: [PATCH 020/378] Lock file maintenance (#313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 163 ++++++++++----------- crates/bitwarden-napi/package-lock.json | 26 ++-- languages/js_webassembly/package-lock.json | 54 ++++--- package-lock.json | 26 ++-- 4 files changed, 134 insertions(+), 135 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cd3063db..92cc6e5f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -207,7 +207,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" dependencies = [ - "event-listener 3.0.0", + "event-listener 3.0.1", "event-listener-strategy", "pin-project-lite", ] @@ -252,9 +252,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64ct" @@ -264,9 +264,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" +checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" dependencies = [ "serde", ] @@ -327,7 +327,7 @@ dependencies = [ "aes", "argon2", "assert_matches", - "base64 0.21.4", + "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", "cbc", @@ -545,7 +545,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.2", + "toml 0.8.6", "uuid", ] @@ -654,9 +654,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -664,9 +664,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -676,18 +676,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.3" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clircle" @@ -843,9 +843,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1062,9 +1062,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" dependencies = [ "concurrent-queue", "parking", @@ -1077,7 +1077,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.0", + "event-listener 3.0.1", "pin-project-lite", ] @@ -1154,9 +1154,9 @@ checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1169,9 +1169,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1179,15 +1179,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1196,9 +1196,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1217,9 +1217,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -1228,15 +1228,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -1246,9 +1246,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -1764,9 +1764,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "log", @@ -2018,9 +2018,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.5+3.1.3" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] @@ -2180,7 +2180,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "indexmap 1.9.3", "line-wrap", "quick-xml", @@ -2403,15 +2403,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2473,7 +2464,7 @@ version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.4", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2514,25 +2505,23 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" dependencies = [ - "byteorder", "const-oid", "digest", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -2551,9 +2540,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", "errno", @@ -2704,18 +2693,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -2735,9 +2724,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -2768,9 +2757,9 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", @@ -2779,9 +2768,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -2800,9 +2789,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap 2.0.2", "itoa", @@ -3062,13 +3051,13 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "windows-sys 0.48.0", ] @@ -3196,9 +3185,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -3219,9 +3208,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" dependencies = [ "serde", "serde_spanned", @@ -3231,18 +3220,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ "indexmap 2.0.2", "serde", @@ -3889,7 +3878,7 @@ checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.4", + "base64 0.21.5", "deadpool", "futures", "futures-timer", diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index b0df11947..4a85cb304 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,19 +95,19 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -117,9 +117,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -209,9 +209,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "peer": true }, diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index ea4d8b7f3..066f862be 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -209,12 +209,21 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", + "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", + "dev": true, + "dependencies": { + "@types/node": "*" } }, "node_modules/@types/qs": { @@ -499,9 +508,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -827,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001553", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001553.tgz", - "integrity": "sha512-N0ttd6TrFfuqKNi+pMgWJTb9qrdJu4JSpgPFLe/lrD19ugC6fZgF0pUewRowDwzdDnb9V41mFcdlYgl/PyKf4A==", + "version": "1.0.30001558", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", + "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", "dev": true, "funding": [ { @@ -1269,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.563", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.563.tgz", - "integrity": "sha512-dg5gj5qOgfZNkPNeyKBZQAQitIQ/xwfIDmEQJHCbXaD9ebTZxwJXUsDYcBlAvZGZLi+/354l35J1wkmP6CqYaw==", + "version": "1.4.569", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", + "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", "dev": true }, "node_modules/encodeurl": { @@ -3089,11 +3098,12 @@ "dev": true }, "node_modules/selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, "dependencies": { + "@types/node-forge": "^1.3.0", "node-forge": "^1" }, "engines": { @@ -3511,9 +3521,9 @@ } }, "node_modules/terser": { - "version": "5.22.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.22.0.tgz", - "integrity": "sha512-hHZVLgRA2z4NWcN6aS5rQDc+7Dcy58HOf2zbYwmFcQ+ua3h6eEFf5lIDKTzbWwlazPyOZsFQO8V80/IjVNExEw==", + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.23.0.tgz", + "integrity": "sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -3665,9 +3675,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, "node_modules/unpipe": { diff --git a/package-lock.json b/package-lock.json index 0918c67ba..2ee17dd0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,13 +363,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", - "integrity": "sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ==", + "version": "20.8.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", + "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", "dev": true, "peer": true, "dependencies": { - "undici-types": "~5.25.1" + "undici-types": "~5.26.4" } }, "node_modules/@types/urijs": { @@ -391,9 +391,9 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -403,9 +403,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1974,9 +1974,9 @@ } }, "node_modules/undici-types": { - "version": "5.25.3", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.25.3.tgz", - "integrity": "sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==", + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "peer": true }, From 1c86c09e7d12b8103b7c32342b368d0f49950695 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 1 Nov 2023 12:19:04 +0100 Subject: [PATCH 021/378] Fix make_user_key which previously didn't stretch the users key (#315) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective The `make_user_key` needs to use the same key as `decrypt_user_key`, which should be the stretched users key. ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- Cargo.lock | 1 + crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/auth/register.rs | 6 +- crates/bitwarden/src/client/client.rs | 10 +-- crates/bitwarden/src/crypto/master_key.rs | 75 ++++++++++++++++++++--- crates/bitwarden/src/crypto/user_key.rs | 2 +- crates/bitwarden/tests/register.rs | 35 +++++++++++ 7 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 crates/bitwarden/tests/register.rs diff --git a/Cargo.lock b/Cargo.lock index 92cc6e5f4..b865c9fe6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -341,6 +341,7 @@ dependencies = [ "num-traits", "pbkdf2", "rand 0.8.5", + "rand_chacha 0.3.1", "reqwest", "rsa", "schemars", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 0090ebb0e..fcbe5b3ac 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -59,5 +59,6 @@ bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2 bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } [dev-dependencies] +rand_chacha = "0.3.1" tokio = { version = "1.28.2", features = ["rt", "macros"] } wiremock = "0.5.18" diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 8336ec9c9..206c1905b 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -79,7 +79,7 @@ pub(super) fn make_register_keys( #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct RegisterKeyResponse { - master_password_hash: String, - encrypted_user_key: String, - keys: RsaKeyPair, + pub master_password_hash: String, + pub encrypted_user_key: String, + pub keys: RsaKeyPair, } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index f6eb0c954..b29118fe5 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,10 @@ use std::time::{Duration, Instant}; +use reqwest::header::{self}; +use uuid::Uuid; + +#[cfg(feature = "secrets")] +use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ auth::login::{ @@ -13,11 +18,6 @@ use crate::{ SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, }, }; -use reqwest::header::{self}; -use uuid::Uuid; - -#[cfg(feature = "secrets")] -use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; use crate::{ auth::renew::renew_token, client::{ diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 064336edb..b2c8e6e5f 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, - UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, + encrypt_aes256_hmac, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, + SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -41,13 +41,7 @@ impl MasterKey { } pub(crate) fn make_user_key(&self) -> Result<(UserKey, EncString)> { - let mut user_key = [0u8; 64]; - rand::thread_rng().fill(&mut user_key); - - let protected = encrypt_aes256(&user_key, self.0.key)?; - - let u: &[u8] = &user_key; - Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) + make_user_key(rand::thread_rng(), self) } pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { @@ -58,6 +52,22 @@ impl MasterKey { } } +/// Generate a new random user key and encrypt it with the master key. +fn make_user_key( + mut rng: impl rand::RngCore, + master_key: &MasterKey, +) -> Result<(UserKey, EncString)> { + let mut user_key = [0u8; 64]; + rng.fill(&mut user_key); + + let stretched_key = stretch_master_key(master_key)?; + let protected = + encrypt_aes256_hmac(&user_key, stretched_key.mac_key.unwrap(), stretched_key.key)?; + + let u: &[u8] = &user_key; + Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) +} + /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { let hash = match kdf { @@ -112,7 +122,9 @@ fn stretch_master_key(master_key: &MasterKey) -> Result { mod tests { use std::num::NonZeroU32; - use super::{stretch_master_key, HashPurpose, MasterKey}; + use rand::SeedableRng; + + use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; use crate::{client::kdf::Kdf, crypto::SymmetricCryptoKey}; #[test] @@ -225,4 +237,47 @@ mod tests { .unwrap(), ); } + + #[test] + fn test_make_user_key() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let master_key = MasterKey(SymmetricCryptoKey { + key: [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, 167, + 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + mac_key: None, + }); + + let (user_key, protected) = make_user_key(&mut rng, &master_key).unwrap(); + + assert_eq!( + user_key.0.key.as_slice(), + [ + 62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161, 44, 132, 14, + 195, 206, 154, 127, 59, 24, 27, 225, 136, 239, 113, 26, 30 + ] + ); + assert_eq!( + user_key.0.mac_key.unwrap().as_slice(), + [ + 152, 76, 225, 114, 185, 33, 111, 65, 159, 68, 83, 103, 69, 109, 86, 25, 49, 74, 66, + 163, 218, 134, 176, 1, 56, 123, 253, 184, 14, 12, 254, 66 + ] + ); + + // Ensure we can decrypt the key and get back the same key + let decrypted = master_key.decrypt_user_key(protected).unwrap(); + + assert_eq!( + decrypted.key, user_key.0.key, + "Decrypted key doesn't match user key" + ); + assert_eq!( + decrypted.mac_key, user_key.0.mac_key, + "Decrypted key doesn't match user key" + ); + } } diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs index 0fe560665..7f5bae413 100644 --- a/crates/bitwarden/src/crypto/user_key.rs +++ b/crates/bitwarden/src/crypto/user_key.rs @@ -6,7 +6,7 @@ use crate::{ error::Result, }; -pub(crate) struct UserKey(SymmetricCryptoKey); +pub(crate) struct UserKey(pub(super) SymmetricCryptoKey); impl UserKey { pub(crate) fn new(key: SymmetricCryptoKey) -> Self { diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs new file mode 100644 index 000000000..d4e632e55 --- /dev/null +++ b/crates/bitwarden/tests/register.rs @@ -0,0 +1,35 @@ +/// Integration test for registering a new user and unlocking the vault +#[cfg(feature = "mobile")] +#[tokio::test] +async fn test_register_initialize_crypto() { + use std::num::NonZeroU32; + + use bitwarden::{client::kdf::Kdf, mobile::crypto::InitCryptoRequest, Client}; + + let mut client = Client::new(None); + + let email = "test@bitwarden.com"; + let password = "test123"; + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }; + + let register_response = client + .auth() + .make_register_keys(email.to_owned(), password.to_owned(), kdf.clone()) + .unwrap(); + + // Ensure we can initialize the crypto with the new keys + client + .crypto() + .initialize_crypto(InitCryptoRequest { + kdf_params: kdf, + email: email.to_owned(), + password: password.to_owned(), + user_key: register_response.encrypted_user_key, + private_key: register_response.keys.private.to_string(), + organization_keys: Default::default(), + }) + .await + .unwrap(); +} From 4819efd70240ced59f2a12f16d0ef13f01fb9fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Wed, 1 Nov 2023 12:45:05 +0100 Subject: [PATCH 022/378] Update Rust crate uniffi to v0.25.0 (#303) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Updated Uniffi to 0.25.0. This required some code changes: - BitwardenError now needs to implement Error. - Defining the uniffi_support types in both crates seems to be causing duplicate symbols on xcode at least, so we instead use `ffi_converter_forward!` to forward the type definitions from the `bitwarden` crate to the `bitwarden-uniffi` crate. - There is a name collision with our `Send`, and Rust's `Send`, so I've changed the imports to use `vault::Send`. - Removed the unused UDL file. --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 154 +++++++++++++++--- Cargo.toml | 12 +- crates/bitwarden-uniffi/Cargo.toml | 4 +- crates/bitwarden-uniffi/src/error.rs | 10 +- crates/bitwarden-uniffi/src/sdk.udl | 8 - crates/bitwarden-uniffi/src/uniffi_support.rs | 17 +- crates/bitwarden-uniffi/src/vault/sends.rs | 16 +- crates/bitwarden/Cargo.toml | 2 +- crates/uniffi-bindgen/Cargo.toml | 2 +- 9 files changed, 157 insertions(+), 68 deletions(-) delete mode 100644 crates/bitwarden-uniffi/src/sdk.udl diff --git a/Cargo.lock b/Cargo.lock index b865c9fe6..e4bf4f9df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,7 +287,7 @@ dependencies = [ "flate2", "globset", "home", - "nu-ansi-term", + "nu-ansi-term 0.49.0", "once_cell", "path_abs", "plist", @@ -1263,6 +1263,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1717,6 +1730,29 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if", + "generator", + "pin-utils", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" version = "2.6.4" @@ -1870,6 +1906,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -1963,6 +2009,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "oneshot" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" +dependencies = [ + "loom", +] + [[package]] name = "onig" version = "6.4.0" @@ -2045,6 +2100,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owo-colors" version = "3.5.0" @@ -2432,10 +2493,19 @@ checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata", + "regex-automata 0.4.3", "regex-syntax 0.8.2", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + [[package]] name = "regex-automata" version = "0.4.3" @@ -2447,6 +2517,12 @@ dependencies = [ "regex-syntax 0.8.2", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.7.5" @@ -3254,9 +3330,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "tracing-core" version = "0.1.32" @@ -3277,15 +3365,33 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ + "matchers", + "nu-ansi-term 0.46.0", + "once_cell", + "regex", "sharded-slab", + "smallvec", "thread_local", + "tracing", "tracing-core", + "tracing-log", ] [[package]] @@ -3344,8 +3450,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", @@ -3365,8 +3471,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "askama", @@ -3380,7 +3486,6 @@ dependencies = [ "once_cell", "paste", "serde", - "serde_json", "toml 0.5.11", "uniffi_meta", "uniffi_testing", @@ -3389,8 +3494,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", @@ -3399,8 +3504,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "quote", "syn 2.0.38", @@ -3408,23 +3513,23 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "bytes", "camino", - "cargo_metadata", "log", "once_cell", + "oneshot", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "bincode", "camino", @@ -3441,34 +3546,31 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "bytes", - "serde", "siphasher", "uniffi_checksum_derive", ] [[package]] name = "uniffi_testing" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "camino", "cargo_metadata", "fs-err", "once_cell", - "serde", - "serde_json", ] [[package]] name = "uniffi_udl" -version = "0.24.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +version = "0.25.0" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "anyhow", "uniffi_meta", @@ -3675,7 +3777,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=53d5ac7274d8b4d66ad35b68cb6e2d89898f96af#53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" +source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index dbd4ed30f..a192c14e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ codegen-units = 1 # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true -# Uniffi proc-macro support is still not part of a release, so we need to use the git version for now +# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "53d5ac7274d8b4d66ad35b68cb6e2d89898f96af" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 759e84e19..a7b774c3c 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -18,13 +18,13 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } env_logger = "0.10.0" -uniffi = "=0.24.1" +uniffi = "=0.25.0" schemars = { version = ">=0.8, <0.9", optional = true } bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.24.1", features = ["build"] } +uniffi = { version = "=0.25.0", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index 1a1e9d29a..b6175eb3b 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -1,7 +1,7 @@ use std::fmt::{Display, Formatter}; // Name is converted from *Error to *Exception, so we can't just name the enum Error because Exception already exists -#[derive(uniffi::Error)] +#[derive(uniffi::Error, Debug)] #[uniffi(flat_error)] pub enum BitwardenError { E(bitwarden::error::Error), @@ -21,4 +21,12 @@ impl Display for BitwardenError { } } +impl std::error::Error for BitwardenError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + BitwardenError::E(e) => Some(e), + } + } +} + pub type Result = std::result::Result; diff --git a/crates/bitwarden-uniffi/src/sdk.udl b/crates/bitwarden-uniffi/src/sdk.udl deleted file mode 100644 index 96cfb31c0..000000000 --- a/crates/bitwarden-uniffi/src/sdk.udl +++ /dev/null @@ -1,8 +0,0 @@ -interface Client { - constructor(optional string settings = ""); - string run_command(string command); -}; - -namespace bitwarden { - -}; diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index f2a0bfde6..82cd343a7 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,16 +1,3 @@ -use crate::UniffiCustomTypeConverter; - +// Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; -uniffi::custom_type!(DateTime, std::time::SystemTime); - -impl UniffiCustomTypeConverter for chrono::DateTime { - type Builtin = std::time::SystemTime; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Ok(Self::from(val)) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.into() - } -} +uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden-uniffi/src/vault/sends.rs b/crates/bitwarden-uniffi/src/vault/sends.rs index 6e2f1b879..696c4a861 100644 --- a/crates/bitwarden-uniffi/src/vault/sends.rs +++ b/crates/bitwarden-uniffi/src/vault/sends.rs @@ -1,6 +1,6 @@ use std::{path::Path, sync::Arc}; -use bitwarden::vault::{Send, SendListView, SendView}; +use bitwarden::vault::{self, SendListView, SendView}; use crate::{Client, Result}; @@ -10,12 +10,12 @@ pub struct ClientSends(pub Arc); #[uniffi::export] impl ClientSends { /// Encrypt send - pub async fn encrypt(&self, send: SendView) -> Result { + pub async fn encrypt(&self, send: SendView) -> Result { Ok(self.0 .0.read().await.vault().sends().encrypt(send).await?) } /// Encrypt a send file in memory - pub async fn encrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { + pub async fn encrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -30,7 +30,7 @@ impl ClientSends { /// Encrypt a send file located in the file system pub async fn encrypt_file( &self, - send: Send, + send: vault::Send, decrypted_file_path: String, encrypted_file_path: String, ) -> Result<()> { @@ -50,12 +50,12 @@ impl ClientSends { } /// Decrypt send - pub async fn decrypt(&self, send: Send) -> Result { + pub async fn decrypt(&self, send: vault::Send) -> Result { Ok(self.0 .0.read().await.vault().sends().decrypt(send).await?) } /// Decrypt send list - pub async fn decrypt_list(&self, sends: Vec) -> Result> { + pub async fn decrypt_list(&self, sends: Vec) -> Result> { Ok(self .0 .0 @@ -68,7 +68,7 @@ impl ClientSends { } /// Decrypt a send file in memory - pub async fn decrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { + pub async fn decrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -83,7 +83,7 @@ impl ClientSends { /// Decrypt a send file located in the file system pub async fn decrypt_file( &self, - send: Send, + send: vault::Send, encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index fcbe5b3ac..65db9db7d 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -50,7 +50,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -uniffi = { version = "=0.24.1", optional = true } +uniffi = { version = "=0.25.0", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index c9c177c84..980434e89 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.24.1", features = ["cli"] } +uniffi = { version = "=0.25.0", features = ["cli"] } From a0bfa3c53e626ec371dfafff839af1c49da64315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 2 Nov 2023 17:14:06 +0100 Subject: [PATCH 023/378] [PM-4270] Individual cipher key encryption (#278) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement individual vault item encryption and encryption. Note that at the moment it will not migrate items that don't have a key when encrypting. --- crates/bitwarden/src/vault/cipher/cipher.rs | 33 +++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index b01f17136..b95a2f090 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -43,6 +43,9 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, + /// More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + pub key: Option, + pub name: EncString, pub notes: Option, @@ -77,6 +80,8 @@ pub struct CipherView { pub folder_id: Option, pub collection_ids: Vec, + pub key: Option, + pub name: String, pub notes: Option, @@ -131,11 +136,15 @@ pub struct CipherListView { impl KeyEncryptable for CipherView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(Cipher { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids, + key: self.key, name: self.name.encrypt_with_key(key)?, notes: self.notes.encrypt_with_key(key)?, r#type: self.r#type, @@ -161,11 +170,15 @@ impl KeyEncryptable for CipherView { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), + key: self.key.clone(), name: self.name.decrypt_with_key(key)?, notes: self.notes.decrypt_with_key(key)?, r#type: self.r#type, @@ -190,6 +203,23 @@ impl KeyDecryptable for Cipher { } impl Cipher { + /// Get the decrypted individual encryption key for this cipher. + /// Note that some ciphers do not have individual encryption keys, + /// in which case this will return Ok(None) and the key associated + /// with this cipher's user or organization must be used instead + fn get_cipher_key( + key: &SymmetricCryptoKey, + ciphers_key: &Option, + ) -> Result> { + ciphers_key + .as_ref() + .map(|k| { + let key: Vec = k.decrypt_with_key(key)?; + SymmetricCryptoKey::try_from(key.as_slice()) + }) + .transpose() + } + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { @@ -257,6 +287,9 @@ impl Cipher { impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + Ok(CipherListView { id: self.id, organization_id: self.organization_id, From eefc58b783abbfdabbe12b98834168a20ff26de9 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 2 Nov 2023 17:53:10 +0100 Subject: [PATCH 024/378] Extract JWT to it's own file (#317) --- .vscode/settings.json | 1 + crates/bitwarden/src/auth/jwt_token.rs | 71 +++++++++++++++++++ .../bitwarden/src/auth/login/access_token.rs | 5 +- crates/bitwarden/src/auth/login/api_key.rs | 4 +- crates/bitwarden/src/auth/mod.rs | 2 + crates/bitwarden/src/util.rs | 53 -------------- 6 files changed, 79 insertions(+), 57 deletions(-) create mode 100644 crates/bitwarden/src/auth/jwt_token.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index e75498e9c..d49fe884f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "Pbkdf", "PKCS8", "repr", + "reqwest", "schemars", "uniffi", "wordlist" diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs new file mode 100644 index 000000000..14cbaf84f --- /dev/null +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -0,0 +1,71 @@ +use std::str::FromStr; + +use base64::Engine; + +use crate::{error::Result, util::BASE64_ENGINE}; + +/// A Bitwarden secrets manager JWT Token. +/// +/// References: +/// - +/// - +/// +/// TODO: We need to expand this to support user based JWT tokens. +#[derive(serde::Deserialize)] +pub struct JWTToken { + pub sub: String, + pub email: Option, + pub organization: Option, + pub scope: Vec, +} + +impl FromStr for JWTToken { + type Err = crate::error::Error; + + /// Parses a JWT token from a string. + /// + /// **Note:** This function does not validate the token signature. + fn from_str(s: &str) -> Result { + let split = s.split('.').collect::>(); + if split.len() != 3 { + return Err(crate::error::Error::Internal( + "JWT token has an invalid number of parts", + )); + } + let decoded = BASE64_ENGINE.decode(split[1])?; + Ok(serde_json::from_slice(&decoded)?) + } +} + +#[cfg(test)] +mod tests { + use crate::auth::jwt_token::JWTToken; + + #[test] + fn can_decode_jwt() { + let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ + g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ + YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ + 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ + EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ + iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ + bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ + jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ + IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ + XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ + wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ + a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ + ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ + qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ + wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ + U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ + f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; + + let token: JWTToken = jwt.parse().unwrap(); + assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); + assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); + assert_eq!(token.organization.as_deref(), None); + assert_eq!(token.scope[0], "api"); + assert_eq!(token.scope[1], "offline_access"); + } +} diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index e7d60951c..d80bfda84 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -6,11 +6,12 @@ use crate::{ auth::{ api::{request::AccessTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, - util::{decode_token, BASE64_ENGINE}, + util::BASE64_ENGINE, Client, }; @@ -44,7 +45,7 @@ pub(crate) async fn access_token_login( let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an access token let organization_id = access_token_obj diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index cdbc383ba..8a42396af 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -5,11 +5,11 @@ use crate::{ auth::{ api::{request::ApiTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, + JWTToken, }, client::{LoginMethod, UserLoginMethod}, crypto::EncString, error::{Error, Result}, - util::decode_token, Client, }; @@ -23,7 +23,7 @@ pub(crate) async fn api_key_login( let response = request_api_identity_tokens(client, input).await?; if let IdentityTokenResponse::Authenticated(r) = &response { - let access_token_obj = decode_token(&r.access_token)?; + let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an api key let email = access_token_obj diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index f2f6a3144..89197d4bc 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,10 +1,12 @@ pub(super) mod api; #[cfg(feature = "internal")] pub mod client_auth; +mod jwt_token; pub mod login; #[cfg(feature = "internal")] pub mod password; pub mod renew; +pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index fc9f30447..b6c8465ec 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -3,11 +3,8 @@ use std::num::NonZeroU32; use base64::{ alphabet, engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, - Engine, }; -use crate::error::Result; - pub fn default_pbkdf2_iterations() -> NonZeroU32 { NonZeroU32::new(600_000).unwrap() } @@ -24,14 +21,6 @@ pub fn default_argon2_parallelism() -> NonZeroU32 { NonZeroU32::new(4).unwrap() } -#[derive(serde::Deserialize)] -pub struct JWTToken { - pub sub: String, - pub email: Option, - pub organization: Option, - pub scope: Vec, -} - const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() .with_encode_padding(true) .with_decode_padding_mode(DecodePaddingMode::Indifferent); @@ -39,48 +28,6 @@ const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() pub const BASE64_ENGINE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); -pub fn decode_token(token: &str) -> Result { - let split = token.split('.').collect::>(); - if split.len() != 3 { - return Err(crate::error::Error::Internal( - "JWT token has an invalid number of parts", - )); - } - let decoded = BASE64_ENGINE.decode(split[1])?; - Ok(serde_json::from_slice(&decoded)?) -} - -#[cfg(test)] -mod tests { - #[test] - fn can_decode_jwt() { - let jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQz\ - g1REJEOUFSUzI1NiIsInR5cCI6ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJu\ - YmYiOjE2NzUxMDM1NzcsImV4cCI6MTY3NTEwNzE3NywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI\ - 6IndlYiIsInN1YiI6ImUyNWQzN2YzLWI2MDMtNDBkZS04NGJhLWFmOTYwMTJmNWE0MiIsImF1dGhfdGltZSI6MTY3NT\ - EwMzU0OSwiaWRwIjoiYml0d2FyZGVuIiwicHJlbWl1bSI6ZmFsc2UsImVtYWlsIjoidGVzdEBiaXR3YXJkZW4uY29tI\ - iwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IkUzNElDWVhRUFRDS01EVldBREZDNktHNDJCQldJRDdJIiwi\ - bmFtZSI6IlRlc3QiLCJvcmdvd25lciI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImRldml\ - jZSI6Ijg5Mjg5M2FiLWRkNDMtNDUwYS04NGI1LWFhOWM1YjdiYjJkOCIsImp0aSI6IkEzMkVFNjY5NDdEQzlDNUE2MT\ - IwRURBRTIwNzc5OUJFIiwiaWF0IjoxNjc1MTAzNTc3LCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb\ - XIiOlsiQXBwbGljYXRpb24iXX0.AyDkKvjmyaSPQViQSa2sGTKIkDGrUAtDmwpE57K4DDWT0QvwDe7FMktmwiF4LH36\ - wx_FnpH21VI1pzwJeTHXtaz3niANJtQZjzGFsNAna_95vrsxZC2YizgGlt6mX4YIGmAw9DiYrmaN0BvQOEm_caV_u6f\ - a30iz9Kvjxf7cpzeZvPEysxGpB3k3TRYTkFUdV43HiXdhXMBhyyOpFU6Fk6yA41y7-8bGYc5mYGknWktmPD9Yx-1xKL\ - ftFja1SnCoLPWvDeK60lqWZQiT4tZHCYJ7m0bBNCccYHc2Kk2Bo5-UoyDxazPwsqMxeNfjlaUuj3o5N_uQ-4n_gVbeA\ - qWV2wrel5UhYjWnczMSLBtt9p0W35kkBPt3ZAnRWMtQMPNH04p-_L6cG-Xu6lDksBTwaavcmtnCKG8V91826EiQ8MrF\ - wGWQRZV6tPKTDAYCgSAZGBY3QDmPGT5BeFcg5Ag_nYYIIifKP-kv10v_N-TOcT3NeGBOUlAZ-9m7iT7Rk3vC--SDZdA\ - U5turoBFiiPL2XXfAjM7P0r7J91gfXc0FaD6I2jDxOmym5h7Yn5phLsbC2NlIXkZp54dKHICenPl4ve6ndDIJacVeS5\ - f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; - - let token = super::decode_token(jwt).unwrap(); - assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); - assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); - assert_eq!(token.organization.as_deref(), None); - assert_eq!(token.scope[0], "api"); - assert_eq!(token.scope[1], "offline_access"); - } -} - #[cfg(test)] pub async fn start_mock(mocks: Vec) -> (wiremock::MockServer, crate::Client) { let server = wiremock::MockServer::start().await; From 1338396f4febd022162c6f0a06b2fc6dab76848e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 2 Nov 2023 17:56:01 +0100 Subject: [PATCH 025/378] Begin documenting the crypto module (#318) --- Cargo.lock | 9 +++++ crates/bitwarden/src/crypto/aes_ops.rs | 38 ++++++++++++++++++- crates/bitwarden/src/crypto/enc_string.rs | 43 +++++++++++++++++++++- crates/bitwarden/src/crypto/encryptable.rs | 2 + crates/bitwarden/src/crypto/fingerprint.rs | 6 +++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4bf4f9df..9672d26e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3813,6 +3813,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.51.1" diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 34d4021e8..87cb96029 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -1,3 +1,13 @@ +//! # AES operations +//! +//! Contains low level AES operations used by the rest of the library. +//! +//! **Warning**: Consider carefully if you have to use these functions directly, as generally we +//! expose higher level functions that are easier to use and more secure. +//! +//! In most cases you should use the [EncString] with [KeyEncryptable][super::KeyEncryptable] & +//! [KeyDecryptable][super::KeyDecryptable] instead. + use aes::cipher::{ block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, BlockEncryptMut, KeyIvInit, @@ -10,6 +20,9 @@ use crate::{ error::{CryptoError, Result}, }; +/// Decrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [decrypt_aes256_hmac], but does not validate the MAC. pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) -> Result> { // Decrypt data let iv = GenericArray::from_slice(iv); @@ -18,13 +31,16 @@ pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; - //Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length let decrypted_len = decrypted_key_slice.len(); data.truncate(decrypted_len); Ok(data) } +/// Decrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [decrypt_aes256], but also validates the MAC. pub fn decrypt_aes256_hmac( iv: &[u8; 16], mac: &[u8; 32], @@ -39,12 +55,26 @@ pub fn decrypt_aes256_hmac( decrypt_aes256(iv, data, key) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Behaves similar to [encrypt_aes256_hmac], but does't generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_B64 EncString pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { let (iv, data) = encrypt_aes256_internal(data_dec, key); Ok(EncString::AesCbc256_B64 { iv, data }) } +/// Encrypt using AES-256 in CBC mode with MAC. +/// +/// Behaves similar to [encrypt_aes256], but also generate a MAC. +/// +/// ## Returns +/// +/// A AesCbc256_HmacSha256_B64 EncString pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, @@ -56,6 +86,11 @@ pub fn encrypt_aes256_hmac( Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } +/// Encrypt using AES-256 in CBC mode. +/// +/// Used internally by: +/// - [encrypt_aes256] +/// - [encrypt_aes256_hmac] fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; rand::thread_rng().fill_bytes(&mut iv); @@ -65,6 +100,7 @@ fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; (iv, data) } +/// Validate a MAC using HMAC-SHA256. fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); hmac.update(iv); diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index 976065e60..ac7f3fc6b 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -11,6 +11,45 @@ use crate::{ use super::{KeyDecryptable, KeyEncryptable, LocateKey}; +/// # Encrypted string primitive +/// +/// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are +/// are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and decrypt +/// data using [SymmetricCryptoKey]s. +/// +/// The flexibility of the [EncString] type allows for different encryption algorithms to be used +/// which is represented by the different variants of the enum. +/// +/// ## Note +/// +/// We are currently in the progress of splitting the [EncString] into distinct AES and RSA +/// variants. To provide better control of which encryption algorithm is expected. +/// +/// For backwards compatibility we will rarely if ever be able to remove support for decrypting old +/// variants, but we should be opinionated in which variants are used for encrypting. +/// +/// ## Variants +/// - [AesCbc256_B64](EncString::AesCbc256_B64) +/// - [AesCbc128_HmacSha256_B64](EncString::AesCbc128_HmacSha256_B64) +/// - [AesCbc256_HmacSha256_B64](EncString::AesCbc256_HmacSha256_B64) +/// - [Rsa2048_OaepSha256_B64](EncString::Rsa2048_OaepSha256_B64) +/// - [Rsa2048_OaepSha1_B64](EncString::Rsa2048_OaepSha1_B64) +/// +/// ## Serialization +/// +/// [EncString] implements [Display] and [FromStr] to allow for easy serialization and uses a +/// custom scheme to represent the different variants. +/// +/// The scheme is one of the following schemes: +/// - `[type].[iv]|[data]` +/// - `[type].[iv]|[data]|[mac]` +/// - `[type].[data]` +/// +/// Where: +/// - `[type]`: is a digit number representing the variant. +/// - `[iv]`: (optional) is the initialization vector used for encryption. +/// - `[data]`: is the encrypted data. +/// - `[mac]`: (optional) is the MAC used to validate the integrity of the data. #[derive(Clone)] #[allow(unused, non_camel_case_types)] pub enum EncString { @@ -40,13 +79,14 @@ pub enum EncString { Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec }, } -// We manually implement these to make sure we don't print any sensitive data +/// To avoid printing sensitive information, [EncString] debug prints to `EncString`. impl std::fmt::Debug for EncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EncString").finish() } } +/// Deserializes an [EncString] from a string. impl FromStr for EncString { type Err = Error; @@ -291,6 +331,7 @@ impl serde::Serialize for EncString { } impl EncString { + /// The numerical representation of the encryption type of the [EncString]. const fn enc_type(&self) -> u8 { match self { EncString::AesCbc256_B64 { .. } => 0, diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index 10dbfaac6..f1bc78f15 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -19,10 +19,12 @@ pub trait LocateKey { } } +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Encryptable { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; } +/// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } diff --git a/crates/bitwarden/src/crypto/fingerprint.rs b/crates/bitwarden/src/crypto/fingerprint.rs index 9473a2cda..ddcf89d40 100644 --- a/crates/bitwarden/src/crypto/fingerprint.rs +++ b/crates/bitwarden/src/crypto/fingerprint.rs @@ -7,6 +7,11 @@ use crate::{ wordlist::EFF_LONG_WORD_LIST, }; +/// Computes a fingerprint of the given `fingerprint_material` using the given `public_key`. +/// +/// This is commonly used for account fingerprints. With the following arguments: +/// - `fingerprint_material`: user's id. +/// - `public_key`: user's public key. pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result { let mut h = sha2::Sha256::new(); h.update(public_key); @@ -22,6 +27,7 @@ pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Resu Ok(hash_word(user_fingerprint).unwrap()) } +/// Derive a 5 word phrase from a 32 byte hash. fn hash_word(hash: [u8; 32]) -> Result { let minimum_entropy = 64; From 66480f31a922ad0bb20d71d32ef6849810bfabca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:07:39 -0400 Subject: [PATCH 026/378] Update actions/setup-node action to v4 (#311) --- .github/workflows/build-napi.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/release-napi.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 45fab6703..16f87a177 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -54,7 +54,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index cac5bc2b8..5f5742da0 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -21,7 +21,7 @@ jobs: toolchain: stable - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a18e5064a..cb1fb2b67 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -31,7 +31,7 @@ jobs: run: cargo fmt --check - name: Set up Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index ee0407587..1cee4a47e 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -93,7 +93,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 with: node-version: 18 cache: "npm" From 0dd1d95ee1329221e6f95f00e799e569cbaae2ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:07:53 -0600 Subject: [PATCH 027/378] Update bitwarden/gh-actions digest to ba6a775 (#307) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | bitwarden/gh-actions | action | digest | `c970b0f` -> `ba6a775` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 8 ++++---- .github/workflows/release-napi.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 1c5484a5c..39926d18b 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 3651e14bc..bf348a291 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-checksum@ba6a77541fa0732735408d10f3ca1e122221201d with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 1cee4a47e..ec88803a2 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/release-version-check@ba6a77541fa0732735408d10f3ca1e122221201d with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 29ee28f80..e875fc663 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c970b0fb89bd966749280e832928db62040812bf + uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" From 13a195cd336bb757c7860f130c6ca7a89337b386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 3 Nov 2023 11:06:14 +0100 Subject: [PATCH 028/378] Remove encrypt from EncryptionSettings (#314) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective After #297, there were some places in the secrets manager parts of the code that used EncryptionSettings to encrypt directly, instead of dealing with the Encryptable/KeyEncryptable trait. This PR removes those uses so that all encryption opearations have to go through Encryptable/KeyEncryptable. --- .../src/client/encryption_settings.rs | 18 ++++++------------ .../src/secrets_manager/projects/create.rs | 15 ++++++++++----- .../src/secrets_manager/projects/update.rs | 15 ++++++++++----- .../src/secrets_manager/secrets/create.rs | 19 ++++++++++++------- .../src/secrets_manager/secrets/update.rs | 19 ++++++++++++------- 5 files changed, 50 insertions(+), 36 deletions(-) diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index e6cf3e145..da5398a12 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -4,14 +4,15 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::{client::UserLoginMethod, crypto::KeyDecryptable}, + crate::{ + client::UserLoginMethod, + crypto::{EncString, KeyDecryptable}, + error::{CryptoError, Result}, + }, rsa::{pkcs8::DecodePrivateKey, Oaep}, }; -use crate::{ - crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey}, - error::{CryptoError, Result}, -}; +use crate::crypto::SymmetricCryptoKey; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, @@ -109,11 +110,4 @@ impl EncryptionSettings { None => Some(&self.user_key), } } - - pub(crate) fn encrypt(&self, data: &[u8], org_id: &Option) -> Result { - let key = self.get_key(org_id).ok_or(CryptoError::NoKeyForOrg)?; - - let dec = encrypt_aes256_hmac(data, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key)?; - Ok(dec) - } } diff --git a/crates/bitwarden/src/secrets_manager/projects/create.rs b/crates/bitwarden/src/secrets_manager/projects/create.rs index 3ba6ecd36..996a3463e 100644 --- a/crates/bitwarden/src/secrets_manager/projects/create.rs +++ b/crates/bitwarden/src/secrets_manager/projects/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -19,12 +23,13 @@ pub(crate) async fn create_project( client: &mut Client, input: &ProjectCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectCreateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/projects/update.rs b/crates/bitwarden/src/secrets_manager/projects/update.rs index b0a040c96..6a0479d88 100644 --- a/crates/bitwarden/src/secrets_manager/projects/update.rs +++ b/crates/bitwarden/src/secrets_manager/projects/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::ProjectResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -21,12 +25,13 @@ pub(crate) async fn update_project( client: &mut Client, input: &ProjectPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let project = Some(ProjectUpdateRequestModel { - name: enc.encrypt(input.name.as_bytes(), &org_id)?.to_string(), + name: input.name.clone().encrypt_with_key(key)?.to_string(), }); let config = client.get_api_configurations().await; diff --git a/crates/bitwarden/src/secrets_manager/secrets/create.rs b/crates/bitwarden/src/secrets_manager/secrets/create.rs index ddec3abd4..a1bb81799 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/create.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/create.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{error::Result, Client}; +use crate::{ + crypto::KeyEncryptable, + error::{Error, Result}, + Client, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn create_secret( client: &mut Client, input: &SecretCreateRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretCreateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); diff --git a/crates/bitwarden/src/secrets_manager/secrets/update.rs b/crates/bitwarden/src/secrets_manager/secrets/update.rs index b1a82bad8..970812c5a 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/update.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/update.rs @@ -4,7 +4,11 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; -use crate::{client::Client, error::Result}; +use crate::{ + client::Client, + crypto::KeyEncryptable, + error::{Error, Result}, +}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -24,14 +28,15 @@ pub(crate) async fn update_secret( client: &mut Client, input: &SecretPutRequest, ) -> Result { - let enc = client.get_encryption_settings()?; - - let org_id = Some(input.organization_id); + let key = client + .get_encryption_settings()? + .get_key(&Some(input.organization_id)) + .ok_or(Error::VaultLocked)?; let secret = Some(SecretUpdateRequestModel { - key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(), - value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(), - note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(), + key: input.key.clone().encrypt_with_key(key)?.to_string(), + value: input.value.clone().encrypt_with_key(key)?.to_string(), + note: input.note.clone().encrypt_with_key(key)?.to_string(), project_ids: input.project_ids.clone(), }); From 5d9e99730d8a2ff674bc98c782d833cdd0f8aa12 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 3 Nov 2023 15:52:13 +0100 Subject: [PATCH 029/378] Move login methods to auth (#319) --- crates/bitwarden-json/src/client.rs | 8 +- crates/bitwarden/CHANGELOG.md | 5 + crates/bitwarden/README.md | 2 +- crates/bitwarden/src/auth/client_auth.rs | 159 +++++++++++++++++- .../bitwarden/src/auth/login/access_token.rs | 2 +- crates/bitwarden/src/auth/login/api_key.rs | 4 +- crates/bitwarden/src/auth/login/mod.rs | 6 +- crates/bitwarden/src/auth/login/password.rs | 2 +- crates/bitwarden/src/auth/login/two_factor.rs | 2 +- crates/bitwarden/src/auth/mod.rs | 1 - crates/bitwarden/src/client/client.rs | 139 +-------------- crates/bitwarden/src/lib.rs | 2 +- crates/bw/src/auth/login.rs | 16 +- crates/bw/src/auth/mod.rs | 2 +- crates/bw/src/main.rs | 4 +- crates/bws/src/main.rs | 3 +- 16 files changed, 192 insertions(+), 165 deletions(-) diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index f771a5ce4..416067b66 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -46,13 +46,15 @@ impl Client { match cmd { #[cfg(feature = "internal")] - Command::PasswordLogin(req) => self.0.password_login(&req).await.into_string(), + Command::PasswordLogin(req) => self.0.auth().login_password(&req).await.into_string(), #[cfg(feature = "secrets")] - Command::AccessTokenLogin(req) => self.0.access_token_login(&req).await.into_string(), + Command::AccessTokenLogin(req) => { + self.0.auth().login_access_token(&req).await.into_string() + } #[cfg(feature = "internal")] Command::GetUserApiKey(req) => self.0.get_user_api_key(&req).await.into_string(), #[cfg(feature = "internal")] - Command::ApiKeyLogin(req) => self.0.api_key_login(&req).await.into_string(), + Command::ApiKeyLogin(req) => self.0.auth().login_api_key(&req).await.into_string(), #[cfg(feature = "internal")] Command::Sync(req) => self.0.sync(&req).await.into_string(), #[cfg(feature = "internal")] diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index 5569ebd7b..8bb18ff72 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,6 +7,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Deprecated + +- `client.access_token_login()` is now deprecated and will be removed in a future release. Please + use `client.auth().login_access_token()` instead. (#319) + ## [0.3.1] - 2023-10-13 ### Changed diff --git a/crates/bitwarden/README.md b/crates/bitwarden/README.md index a0708b7e6..67c347583 100644 --- a/crates/bitwarden/README.md +++ b/crates/bitwarden/README.md @@ -42,7 +42,7 @@ async fn test() -> Result<()> { // Before we operate, we need to authenticate with a token let token = AccessTokenLoginRequest { access_token: String::from("") }; - client.access_token_login(&token).await.unwrap(); + client.auth().login_access_token(&token).await.unwrap(); let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 8ffca0a44..aa1615c3b 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,14 +1,40 @@ -use super::{ - password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, - register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, +#[cfg(feature = "secrets")] +use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::{auth::renew::renew_token, error::Result, Client}; +#[cfg(feature = "internal")] +use crate::{ + auth::{ + login::{ + login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, + ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, + TwoFactorEmailRequest, + }, + password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, + register::{make_register_keys, register}, + RegisterKeyResponse, RegisterRequest, + }, + client::kdf::Kdf, }; -use crate::{client::kdf::Kdf, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, } +impl<'a> ClientAuth<'a> { + pub async fn renew_token(&mut self) -> Result<()> { + renew_token(self.client).await + } + + #[cfg(feature = "secrets")] + pub async fn login_access_token( + &mut self, + input: &AccessTokenLoginRequest, + ) -> Result { + login_access_token(self.client, input).await + } +} + +#[cfg(feature = "internal")] impl<'a> ClientAuth<'a> { pub async fn password_strength( &self, @@ -37,10 +63,33 @@ impl<'a> ClientAuth<'a> { make_register_keys(email, password, kdf) } - #[cfg(feature = "internal")] pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } + + pub async fn prelogin(&mut self, email: String) -> Result { + use crate::auth::login::request_prelogin; + + request_prelogin(self.client, email).await?.try_into() + } + + pub async fn login_password( + &mut self, + input: &PasswordLoginRequest, + ) -> Result { + login_password(self.client, input).await + } + + pub async fn login_api_key( + &mut self, + input: &ApiKeyLoginRequest, + ) -> Result { + login_api_key(self.client, input).await + } + + pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { + send_two_factor_email(self.client, tf).await + } } impl<'a> Client { @@ -48,3 +97,101 @@ impl<'a> Client { ClientAuth { client: self } } } + +#[cfg(test)] +mod tests { + + #[cfg(feature = "secrets")] + #[tokio::test] + async fn test_access_token_login() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; + + // Create the mock server with the necessary routes for this test + let (_server, mut client) = crate::util::start_mock(vec![ + Mock::given(matchers::path("/identity/connect/token")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ + ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ + iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ + mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ + 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ + ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ + 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ + SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ + Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ + He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ + TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", + "expires_in":3600, + "token_type":"Bearer", + "scope":"api.secrets", + "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ + Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) + )), + Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "secrets":[{ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z" + }], + "projects":[], + "object":"SecretsWithProjectsList" + }) + )), + Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) + .respond_with(ResponseTemplate::new(200).set_body_json( + serde_json::json!({ + "id":"15744a66-341a-4c62-af50-af960166b6bc", + "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", + "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", + "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", + "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", + "creationDate":"2023-01-26T21:46:02.2182556Z", + "revisionDate":"2023-01-26T21:46:02.2182557Z", + "object":"secret" + }) + )) + ]).await; + + // Test the login is correct and we store the returned organization ID correctly + let res = client + .auth() + .login_access_token(&AccessTokenLoginRequest { + access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), + }) + .await + .unwrap(); + assert!(res.authenticated); + let organization_id = client.get_access_token_organization().unwrap(); + assert_eq!( + organization_id.to_string(), + "f4e44a7f-1190-432a-9d4a-af96013127cb" + ); + + // Test that we can retrieve the list of secrets correctly + let mut res = client + .secrets() + .list(&SecretIdentifiersRequest { organization_id }) + .await + .unwrap(); + assert_eq!(res.data.len(), 1); + + // Test that given a secret ID we can get it's data + let res = client + .secrets() + .get(&SecretGetRequest { + id: res.data.remove(0).id, + }) + .await + .unwrap(); + assert_eq!(res.key, "TEST"); + assert_eq!(res.note, "TEST"); + assert_eq!(res.value, "TEST"); + } +} diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index d80bfda84..1ec8c8b34 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -15,7 +15,7 @@ use crate::{ Client, }; -pub(crate) async fn access_token_login( +pub(crate) async fn login_access_token( client: &mut Client, input: &AccessTokenLoginRequest, ) -> Result { diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index 8a42396af..db5cbe01d 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -13,7 +13,7 @@ use crate::{ Client, }; -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( client: &mut Client, input: &ApiKeyLoginRequest, ) -> Result { @@ -30,7 +30,7 @@ pub(crate) async fn api_key_login( .email .ok_or(Error::Internal("Access token doesn't contain email"))?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; client.set_tokens( r.access_token.clone(), diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 9e1dbb818..4ec9d1b49 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -14,7 +14,7 @@ pub mod response; mod password; #[cfg(feature = "internal")] -pub(crate) use password::password_login; +pub(crate) use password::login_password; #[cfg(feature = "internal")] pub use password::PasswordLoginRequest; pub use password::PasswordLoginResponse; @@ -28,14 +28,14 @@ pub use two_factor::{TwoFactorEmailRequest, TwoFactorProvider, TwoFactorRequest} #[cfg(feature = "internal")] mod api_key; #[cfg(feature = "internal")] -pub(crate) use api_key::api_key_login; +pub(crate) use api_key::login_api_key; #[cfg(feature = "internal")] pub use api_key::{ApiKeyLoginRequest, ApiKeyLoginResponse}; #[cfg(feature = "secrets")] mod access_token; #[cfg(feature = "secrets")] -pub(crate) use access_token::access_token_login; +pub(super) use access_token::login_access_token; #[cfg(feature = "secrets")] pub use access_token::{AccessTokenLoginRequest, AccessTokenLoginResponse}; diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index c86f7019f..a320131ea 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -22,7 +22,7 @@ use crate::{ }; #[cfg(feature = "internal")] -pub(crate) async fn password_login( +pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index 04c411349..d8ede2473 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -20,7 +20,7 @@ pub(crate) async fn send_two_factor_email( input: &TwoFactorEmailRequest, ) -> Result<()> { // TODO: This should be resolved from the client - let kdf = client.prelogin(input.email.clone()).await?; + let kdf = client.auth().prelogin(input.email.clone()).await?; let password_hash = determine_password_hash(&input.email, &kdf, &input.password).await?; diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 89197d4bc..023f3270b 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,5 +1,4 @@ pub(super) mod api; -#[cfg(feature = "internal")] pub mod client_auth; mod jwt_token; pub mod login; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index b29118fe5..213a12fb2 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -4,13 +4,9 @@ use reqwest::header::{self}; use uuid::Uuid; #[cfg(feature = "secrets")] -use crate::auth::login::{access_token_login, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ - auth::login::{ - api_key_login, password_login, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, - }, client::kdf::Kdf, crypto::EncString, platform::{ @@ -19,7 +15,6 @@ use crate::{ }, }; use crate::{ - auth::renew::renew_token, client::{ client_settings::{ClientSettings, DeviceType}, encryption_settings::EncryptionSettings, @@ -133,39 +128,17 @@ impl Client { pub(crate) async fn get_api_configurations(&mut self) -> &ApiConfigurations { // At the moment we ignore the error result from the token renewal, if it fails, // the token will end up expiring and the next operation is going to fail anyway. - self.renew_token().await.ok(); + self.auth().renew_token().await.ok(); &self.__api_configurations } - #[cfg(feature = "internal")] - pub async fn prelogin(&mut self, email: String) -> Result { - use crate::auth::login::request_prelogin; - - request_prelogin(self, email).await?.try_into() - } - - #[cfg(feature = "internal")] - pub async fn password_login( - &mut self, - input: &PasswordLoginRequest, - ) -> Result { - password_login(self, input).await - } - - #[cfg(feature = "internal")] - pub async fn api_key_login( - &mut self, - input: &ApiKeyLoginRequest, - ) -> Result { - api_key_login(self, input).await - } - #[cfg(feature = "secrets")] + #[deprecated(note = "Use auth().login_access_token() instead")] pub async fn access_token_login( &mut self, input: &AccessTokenLoginRequest, ) -> Result { - access_token_login(self, input).await + self.auth().login_access_token(input).await } #[cfg(feature = "internal")] @@ -223,10 +196,6 @@ impl Client { self.__api_configurations.api.oauth_access_token = Some(token); } - pub async fn renew_token(&mut self) -> Result<()> { - renew_token(self).await - } - #[cfg(feature = "internal")] pub fn is_authed(&self) -> bool { self.token.is_some() || self.login_method.is_some() @@ -279,104 +248,4 @@ impl Client { pub fn fingerprint(&mut self, input: &FingerprintRequest) -> Result { generate_fingerprint(input) } - - #[cfg(feature = "internal")] - pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { - send_two_factor_email(self, tf).await - } -} - -#[cfg(test)] -mod tests { - use wiremock::{matchers, Mock, ResponseTemplate}; - - use crate::{auth::login::AccessTokenLoginRequest, secrets_manager::secrets::*}; - - #[tokio::test] - async fn test_access_token_login() { - // Create the mock server with the necessary routes for this test - let (_server, mut client) = crate::util::start_mock(vec![ - Mock::given(matchers::path("/identity/connect/token")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "access_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjMwMURENkE1MEU4NEUxRDA5MUM4MUQzQjAwQkY5MDEwQzg1REJEOUFSUzI1NiIsInR5cCI6\ - ImF0K2p3dCIsIng1dCI6Ik1CM1dwUTZFNGRDUnlCMDdBTC1RRU1oZHZabyJ9.eyJuYmYiOjE2NzUxMDM3ODEsImV4cCI6MTY3NTEwNzM4MSwiaXNzIjo\ - iaHR0cDovL2xvY2FsaG9zdCIsImNsaWVudF9pZCI6ImVjMmMxZDQ2LTZhNGItNDc1MS1hMzEwLWFmOTYwMTMxN2YyZCIsInN1YiI6ImQzNDgwNGNhLTR\ - mNmMtNDM5Mi04NmI3LWFmOTYwMTMxNzVkMCIsIm9yZ2FuaXphdGlvbiI6ImY0ZTQ0YTdmLTExOTAtNDMyYS05ZDRhLWFmOTYwMTMxMjdjYiIsImp0aSI\ - 6IjU3QUU0NzQ0MzIwNzk1RThGQkQ4MUIxNDA2RDQyNTQyIiwiaWF0IjoxNjc1MTAzNzgxLCJzY29wZSI6WyJhcGkuc2VjcmV0cyJdfQ.GRKYzqgJZHEE\ - ZHsJkhVZH8zjYhY3hUvM4rhdV3FU10WlCteZdKHrPIadCUh-Oz9DxIAA2HfALLhj1chL4JgwPmZgPcVS2G8gk8XeBmZXowpVWJ11TXS1gYrM9syXbv9j\ - 0JUCdpeshH7e56WnlpVynyUwIum9hmYGZ_XJUfmGtlKLuNjYnawTwLEeR005uEjxq3qI1kti-WFnw8ciL4a6HLNulgiFw1dAvs4c7J0souShMfrnFO3g\ - SOHff5kKD3hBB9ynDBnJQSFYJ7dFWHIjhqs0Vj-9h0yXXCcHvu7dVGpaiNjNPxbh6YeXnY6UWcmHLDtFYsG2BWcNvVD4-VgGxXt3cMhrn7l3fSYuo32Z\ - Yk4Wop73XuxqF2fmfmBdZqGI1BafhENCcZw_bpPSfK2uHipfztrgYnrzwvzedz0rjFKbhDyrjzuRauX5dqVJ4ntPeT9g_I5n71gLxiP7eClyAx5RxdF6\ - He87NwC8i-hLBhugIvLTiDj-Sk9HvMth6zaD0ebxd56wDjq8-CMG_WcgusDqNzKFHqWNDHBXt8MLeTgZAR2rQMIMFZqFgsJlRflbig8YewmNUA9wAU74\ - TfxLY1foO7Xpg49vceB7C-PlvGi1VtX6F2i0tc_67lA5kWXnnKBPBUyspoIrmAUCwfms5nTTqA9xXAojMhRHAos_OdM", - "expires_in":3600, - "token_type":"Bearer", - "scope":"api.secrets", - "encrypted_payload":"2.E9fE8+M/VWMfhhim1KlCbQ==|eLsHR484S/tJbIkM6spnG/HP65tj9A6Tba7kAAvUp+rYuQmGLixiOCfMsqt5OvBctDfvvr/Aes\ - Bu7cZimPLyOEhqEAjn52jF0eaI38XZfeOG2VJl0LOf60Wkfh3ryAMvfvLj3G4ZCNYU8sNgoC2+IQ==|lNApuCQ4Pyakfo/wwuuajWNaEX/2MW8/3rjXB/V7n+k="}) - )), - Mock::given(matchers::path("/api/organizations/f4e44a7f-1190-432a-9d4a-af96013127cb/secrets")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "secrets":[{ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z" - }], - "projects":[], - "object":"SecretsWithProjectsList" - }) - )), - Mock::given(matchers::path("/api/secrets/15744a66-341a-4c62-af50-af960166b6bc")) - .respond_with(ResponseTemplate::new(200).set_body_json( - serde_json::json!({ - "id":"15744a66-341a-4c62-af50-af960166b6bc", - "organizationId":"f4e44a7f-1190-432a-9d4a-af96013127cb", - "key":"2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8=", - "value":"2.Gl34n9JYABC7V21qHcBzHg==|c1Ds244pob7i+8+MXe4++w==|Shimz/qKMYZmzSFWdeBzFb9dFz7oF6Uv9oqkws7rEe0=", - "note":"2.Cn9ABJy7+WfR4uUHwdYepg==|+nbJyU/6hSknoa5dcEJEUg==|1DTp/ZbwGO3L3RN+VMsCHz8XDr8egn/M5iSitGGysPA=", - "creationDate":"2023-01-26T21:46:02.2182556Z", - "revisionDate":"2023-01-26T21:46:02.2182557Z", - "object":"secret" - }) - )) - ]).await; - - // Test the login is correct and we store the returned organization ID correctly - let res = client - .access_token_login(&AccessTokenLoginRequest { - access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), - }) - .await - .unwrap(); - assert!(res.authenticated); - let organization_id = client.get_access_token_organization().unwrap(); - assert_eq!( - organization_id.to_string(), - "f4e44a7f-1190-432a-9d4a-af96013127cb" - ); - - // Test that we can retrieve the list of secrets correctly - let mut res = client - .secrets() - .list(&SecretIdentifiersRequest { organization_id }) - .await - .unwrap(); - assert_eq!(res.data.len(), 1); - - // Test that given a secret ID we can get it's data - let res = client - .secrets() - .get(&SecretGetRequest { - id: res.data.remove(0).id, - }) - .await - .unwrap(); - assert_eq!(res.key, "TEST"); - assert_eq!(res.note, "TEST"); - assert_eq!(res.value, "TEST"); - } } diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index a61857992..20e36d237 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -39,7 +39,7 @@ //! //! // Before we operate, we need to authenticate with a token //! let token = AccessTokenLoginRequest { access_token: String::from("") }; -//! client.access_token_login(&token).await.unwrap(); +//! client.auth().login_access_token(&token).await.unwrap(); //! //! let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; //! println!("Stored secrets: {:#?}", client.secrets().list(&org_id).await.unwrap()); diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index 1c169817f..1fcd15414 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -10,15 +10,16 @@ use color_eyre::eyre::{bail, Result}; use inquire::{Password, Text}; use log::{debug, error, info}; -pub(crate) async fn password_login(mut client: Client, email: Option) -> Result<()> { +pub(crate) async fn login_password(mut client: Client, email: Option) -> Result<()> { let email = text_prompt_when_none("Email", email)?; let password = Password::new("Password").without_confirmation().prompt()?; - let kdf = client.prelogin(email.clone()).await?; + let kdf = client.auth().prelogin(email.clone()).await?; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email: email.clone(), password: password.clone(), two_factor: None, @@ -45,6 +46,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> } else if let Some(tf) = two_factor.email { // Send token client + .auth() .send_two_factor_email(&TwoFactorEmailRequest { email: email.clone(), password: password.clone(), @@ -64,7 +66,8 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> }; let result = client - .password_login(&PasswordLoginRequest { + .auth() + .login_password(&PasswordLoginRequest { email, password, two_factor, @@ -80,7 +83,7 @@ pub(crate) async fn password_login(mut client: Client, email: Option) -> Ok(()) } -pub(crate) async fn api_key_login( +pub(crate) async fn login_api_key( mut client: Client, client_id: Option, client_secret: Option, @@ -91,7 +94,8 @@ pub(crate) async fn api_key_login( let password = Password::new("Password").without_confirmation().prompt()?; let result = client - .api_key_login(&ApiKeyLoginRequest { + .auth() + .login_api_key(&ApiKeyLoginRequest { client_id, client_secret, password, diff --git a/crates/bw/src/auth/mod.rs b/crates/bw/src/auth/mod.rs index a745a70f0..a4c7e2ed5 100644 --- a/crates/bw/src/auth/mod.rs +++ b/crates/bw/src/auth/mod.rs @@ -1,2 +1,2 @@ mod login; -pub(crate) use login::{api_key_login, password_login}; +pub(crate) use login::{login_api_key, login_password}; diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index 73e64a4aa..609650ab1 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -143,12 +143,12 @@ async fn process_commands() -> Result<()> { match args.command { // FIXME: Rust CLI will not support password login! LoginCommands::Password { email } => { - auth::password_login(client, email).await?; + auth::login_password(client, email).await?; } LoginCommands::ApiKey { client_id, client_secret, - } => auth::api_key_login(client, client_id, client_secret).await?, + } => auth::login_api_key(client, client_id, client_secret).await?, } return Ok(()); } diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index c7a910260..6f27a0e4d 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -324,7 +324,8 @@ async fn process_commands() -> Result<()> { // Load session or return if no session exists let _ = client - .access_token_login(&AccessTokenLoginRequest { access_token }) + .auth() + .login_access_token(&AccessTokenLoginRequest { access_token }) .await?; let organization_id = match client.get_access_token_organization() { From a19c45293e2557020e70c187f26497abdee298ee Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 3 Nov 2023 16:03:11 +0100 Subject: [PATCH 030/378] Exclude snapshots from the GH artifact cleanup job (#321) --- .github/workflows/delete-old-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index 517560ede..323a9a0a2 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -22,4 +22,4 @@ jobs: min-versions-to-keep: 25 # Ignore versions only containing version numbers - ignore-versions: '^\\d*\\.\\d*\\.\\d*$' + ignore-versions: '^\\d*\\.\\d*\\.\\d*(-SNAPSHOT)?$' From ab3c4c12312a347e2fcad8875796ad0a60889d08 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Thu, 9 Nov 2023 10:22:29 -0500 Subject: [PATCH 031/378] All workflows - Update 'master' to 'main' for any actions in the gh-actions repository (#328) --- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 8 ++++---- .github/workflows/release-napi.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 39926d18b..468570cd8 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -109,7 +109,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index bf348a291..4c52529e8 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -58,7 +58,7 @@ jobs: - name: Download all Release artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -67,7 +67,7 @@ jobs: - name: Dry Run - Download all artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-cli.yml path: packages @@ -75,7 +75,7 @@ jobs: branch: master - name: Get checksum files - uses: bitwarden/gh-actions/get-checksum@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-checksum@main with: packages_dir: "packages" file_path: "packages/bws-sha256-checksums-${{ steps.version.outputs.version }}.txt" @@ -134,7 +134,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "cratesio-api-token" diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index ec88803a2..daa450c0b 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -47,7 +47,7 @@ jobs: - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/release-version-check@main with: release-type: ${{ github.event.inputs.release_type }} project-type: ts @@ -101,7 +101,7 @@ jobs: - name: Download schemas if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -111,7 +111,7 @@ jobs: - name: Dry Run - Download schemas if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml artifacts: schemas.ts @@ -132,14 +132,14 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "npm-api-key" - name: Download artifacts if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts @@ -148,7 +148,7 @@ jobs: - name: Dry Run - Download artifacts if: ${{ github.event.inputs.release_type == 'Dry Run' }} - uses: bitwarden/gh-actions/download-artifacts@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/download-artifacts@main with: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index e875fc663..d902c5700 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -49,7 +49,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@ba6a77541fa0732735408d10f3ca1e122221201d + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" From 5268e78b0f15ae1c40488b3b32b1e443d40abd60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 13:27:35 +0100 Subject: [PATCH 032/378] Update npm minor (#323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`2.16.3` -> `2.16.5`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/2.16.3/2.16.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/2.16.3/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/2.16.3/2.16.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`3.0.3` -> `3.1.0`](https://renovatebot.com/diffs/npm/prettier/3.0.3/3.1.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.0.3/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.0.3/3.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [quicktype-core](https://togithub.com/quicktype/quicktype) | [`23.0.76` -> `23.0.77`](https://renovatebot.com/diffs/npm/quicktype-core/23.0.76/23.0.77) | [![age](https://developer.mend.io/api/mc/badges/age/npm/quicktype-core/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/quicktype-core/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/quicktype-core/23.0.76/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/quicktype-core/23.0.76/23.0.77?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
napi-rs/napi-rs (@​napi-rs/cli) ### [`v2.16.5`](https://togithub.com/napi-rs/napi-rs/releases/tag/%40napi-rs/cli%402.16.5) [Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@2.16.4...@napi-rs/cli@2.16.5) #### What's Changed - fix(cli): switch name parsing to allow periods in name by [@​RaphaelDarley](https://togithub.com/RaphaelDarley) [https://github.com/napi-rs/napi-rs/pull/1716](https://togithub.com/napi-rs/napi-rs/pull/1716) #### New Contributors - [@​RaphaelDarley](https://togithub.com/RaphaelDarley) made their first contribution in [https://github.com/napi-rs/napi-rs/pull/1716](https://togithub.com/napi-rs/napi-rs/pull/1716) **Full Changelog**: https://github.com/napi-rs/napi-rs/compare/[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.4...[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.5 ### [`v2.16.4`](https://togithub.com/napi-rs/napi-rs/releases/tag/%40napi-rs/cli%402.16.4) [Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@2.16.3...@napi-rs/cli@2.16.4) #### What's Changed - chore(cli): update ci template by [@​Brooooooklyn](https://togithub.com/Brooooooklyn) in [https://github.com/napi-rs/napi-rs/pull/1770](https://togithub.com/napi-rs/napi-rs/pull/1770) **Full Changelog**: https://github.com/napi-rs/napi-rs/compare/[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.3...[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).16.4
prettier/prettier (prettier) ### [`v3.1.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#310) [Compare Source](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0) [diff](https://togithub.com/prettier/prettier/compare/3.0.3...3.1.0) 🔗 [Release Notes](https://prettier.io/blog/2023/11/13/3.1.0.html)
quicktype/quicktype (quicktype-core) ### [`v23.0.77`](https://togithub.com/quicktype/quicktype/compare/fb0ee714b89e65f288789ce2f2e3e33b41107405...55dc6a7912715b7db45419958bf89d00637cd4cd) [Compare Source](https://togithub.com/quicktype/quicktype/compare/fb0ee714b89e65f288789ce2f2e3e33b41107405...55dc6a7912715b7db45419958bf89d00637cd4cd)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 6 +++--- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 4a85cb304..65266d1e4 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -55,9 +55,9 @@ } }, "node_modules/@napi-rs/cli": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.3.tgz", - "integrity": "sha512-3mLNPlbbOhpbIUKicLrJtIearlHXUuXL3UeueYyRRplpVMNkdn8xCyzY6PcYZi3JXR8bmCOiWgkVmLnrSL7DKw==", + "version": "2.16.5", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.5.tgz", + "integrity": "sha512-mFEzwrg4IOLngGd2/P6yeqIWgwQNn59Z08n1rndu6kLDq1gg954NH9cM1O9Da0RJuybt46p43lqgSsnAY2mxqA==", "dev": true, "bin": { "napi": "scripts/index.js" diff --git a/package-lock.json b/package-lock.json index 2ee17dd0a..7791b3b69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,8 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" @@ -1470,9 +1470,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", + "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.76", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.76.tgz", - "integrity": "sha512-QinZRNovSTQcFuhRKxeHb22eFmyucbG96EPaQDSbz9qvIPxUhs1BZviNc8HAkHWYFqTSET/xZcEoHpm1DeDbRg==", + "version": "23.0.77", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.77.tgz", + "integrity": "sha512-QABFgMHVsyW7CAcLGWvIQXgjZ7ehPnebfV/3x9c5HtuJVXgYLrEG/+zyQd1O+OPWpQrhbwU97doJTZRw+acA6A==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index fdeb8fe58..ad38f3a10 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.0.3", - "quicktype-core": "23.0.76", + "prettier": "3.1.0", + "quicktype-core": "23.0.77", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" From ee33be94e55463b2c0417a8887b7636e01c75eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 13 Nov 2023 13:48:20 +0100 Subject: [PATCH 033/378] Update uniffi to solve Send conflict (#326) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update uniffi to solve the conflict between our `Send` and Rust's `Send` --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 10 +++++----- crates/bitwarden-uniffi/src/vault/sends.rs | 16 ++++++++-------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9672d26e9..184066772 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3451,7 +3451,7 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3472,7 +3472,7 @@ dependencies = [ [[package]] name = "uniffi_bindgen" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "askama", @@ -3495,7 +3495,7 @@ dependencies = [ [[package]] name = "uniffi_build" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3505,7 +3505,7 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "quote", "syn 2.0.38", @@ -3514,7 +3514,7 @@ dependencies = [ [[package]] name = "uniffi_core" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", @@ -3529,7 +3529,7 @@ dependencies = [ [[package]] name = "uniffi_macros" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "bincode", "camino", @@ -3547,7 +3547,7 @@ dependencies = [ [[package]] name = "uniffi_meta" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "bytes", @@ -3558,7 +3558,7 @@ dependencies = [ [[package]] name = "uniffi_testing" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "camino", @@ -3570,7 +3570,7 @@ dependencies = [ [[package]] name = "uniffi_udl" version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "anyhow", "uniffi_meta", @@ -3777,7 +3777,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=eb97592f8c48a7f5cf02a94662b8b7861a6544f3#eb97592f8c48a7f5cf02a94662b8b7861a6544f3" +source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index a192c14e5..da8805342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ codegen-units = 1 # Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "eb97592f8c48a7f5cf02a94662b8b7861a6544f3" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } diff --git a/crates/bitwarden-uniffi/src/vault/sends.rs b/crates/bitwarden-uniffi/src/vault/sends.rs index 696c4a861..6e2f1b879 100644 --- a/crates/bitwarden-uniffi/src/vault/sends.rs +++ b/crates/bitwarden-uniffi/src/vault/sends.rs @@ -1,6 +1,6 @@ use std::{path::Path, sync::Arc}; -use bitwarden::vault::{self, SendListView, SendView}; +use bitwarden::vault::{Send, SendListView, SendView}; use crate::{Client, Result}; @@ -10,12 +10,12 @@ pub struct ClientSends(pub Arc); #[uniffi::export] impl ClientSends { /// Encrypt send - pub async fn encrypt(&self, send: SendView) -> Result { + pub async fn encrypt(&self, send: SendView) -> Result { Ok(self.0 .0.read().await.vault().sends().encrypt(send).await?) } /// Encrypt a send file in memory - pub async fn encrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { + pub async fn encrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -30,7 +30,7 @@ impl ClientSends { /// Encrypt a send file located in the file system pub async fn encrypt_file( &self, - send: vault::Send, + send: Send, decrypted_file_path: String, encrypted_file_path: String, ) -> Result<()> { @@ -50,12 +50,12 @@ impl ClientSends { } /// Decrypt send - pub async fn decrypt(&self, send: vault::Send) -> Result { + pub async fn decrypt(&self, send: Send) -> Result { Ok(self.0 .0.read().await.vault().sends().decrypt(send).await?) } /// Decrypt send list - pub async fn decrypt_list(&self, sends: Vec) -> Result> { + pub async fn decrypt_list(&self, sends: Vec) -> Result> { Ok(self .0 .0 @@ -68,7 +68,7 @@ impl ClientSends { } /// Decrypt a send file in memory - pub async fn decrypt_buffer(&self, send: vault::Send, buffer: Vec) -> Result> { + pub async fn decrypt_buffer(&self, send: Send, buffer: Vec) -> Result> { Ok(self .0 .0 @@ -83,7 +83,7 @@ impl ClientSends { /// Decrypt a send file located in the file system pub async fn decrypt_file( &self, - send: vault::Send, + send: Send, encrypted_file_path: String, decrypted_file_path: String, ) -> Result<()> { From 39891e0adb9049dd5852028d110ff8f2be0b6855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 13 Nov 2023 14:09:14 +0100 Subject: [PATCH 034/378] Update public modules to get correct documentation (#325) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective All the functions in `Client` that return `Client*` were inside private modules, which make them accessible for use, but `cargo doc` will not document them. By making them public, the cargo docs generate the correct documentation. Also made `aes_ops` private as it's not used outside the crypto module anymore. --- crates/bitwarden/src/crypto/aes_ops.rs | 1 + crates/bitwarden/src/crypto/mod.rs | 2 +- crates/bitwarden/src/mobile/mod.rs | 7 +++++-- crates/bitwarden/src/mobile/vault/mod.rs | 7 +++++++ crates/bitwarden/src/secrets_manager/mod.rs | 3 +++ crates/bitwarden/src/tool/exporters/mod.rs | 1 + crates/bitwarden/src/tool/generators/mod.rs | 1 + crates/bitwarden/src/tool/mod.rs | 4 ++-- 8 files changed, 21 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 87cb96029..132718349 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -62,6 +62,7 @@ pub fn decrypt_aes256_hmac( /// ## Returns /// /// A AesCbc256_B64 EncString +#[allow(unused)] pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { let (iv, data) = encrypt_aes256_internal(data_dec, key); diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index d8a1f0557..b030a5107 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -33,7 +33,7 @@ pub use encryptable::{Decryptable, Encryptable, LocateKey}; mod key_encryptable; pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; mod aes_ops; -pub use aes_ops::{decrypt_aes256, decrypt_aes256_hmac, encrypt_aes256, encrypt_aes256_hmac}; +use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; mod symmetric_crypto_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod shareable_key; diff --git a/crates/bitwarden/src/mobile/mod.rs b/crates/bitwarden/src/mobile/mod.rs index ad2d794af..fe3083aa8 100644 --- a/crates/bitwarden/src/mobile/mod.rs +++ b/crates/bitwarden/src/mobile/mod.rs @@ -3,8 +3,11 @@ pub mod crypto; pub mod kdf; pub mod vault; -pub(crate) mod client_crypto; -pub(crate) mod client_kdf; +mod client_crypto; +mod client_kdf; + +pub use client_crypto::ClientCrypto; +pub use client_kdf::ClientKdf; // Usually we wouldn't want to expose EncStrings in the API or the schemas, // but we need them in the mobile API, so define it here to limit the scope diff --git a/crates/bitwarden/src/mobile/vault/mod.rs b/crates/bitwarden/src/mobile/vault/mod.rs index f22f004ce..97f9556af 100644 --- a/crates/bitwarden/src/mobile/vault/mod.rs +++ b/crates/bitwarden/src/mobile/vault/mod.rs @@ -5,3 +5,10 @@ mod client_password_history; mod client_sends; mod client_totp; mod client_vault; + +pub use client_ciphers::ClientCiphers; +pub use client_collection::ClientCollections; +pub use client_folders::ClientFolders; +pub use client_password_history::ClientPasswordHistory; +pub use client_sends::ClientSends; +pub use client_vault::ClientVault; diff --git a/crates/bitwarden/src/secrets_manager/mod.rs b/crates/bitwarden/src/secrets_manager/mod.rs index 0afbfe38c..27b84121e 100644 --- a/crates/bitwarden/src/secrets_manager/mod.rs +++ b/crates/bitwarden/src/secrets_manager/mod.rs @@ -3,3 +3,6 @@ pub mod secrets; mod client_projects; mod client_secrets; + +pub use client_projects::ClientProjects; +pub use client_secrets::ClientSecrets; diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 508aae8fb..1170dbd38 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -6,6 +6,7 @@ use crate::{ }; mod client_exporter; +pub use client_exporter::ClientExporters; #[derive(JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs index bdc0fb260..4d991b765 100644 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ b/crates/bitwarden/src/tool/generators/mod.rs @@ -1,4 +1,5 @@ mod client_generator; mod password; +pub use client_generator::ClientGenerator; pub use password::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; diff --git a/crates/bitwarden/src/tool/mod.rs b/crates/bitwarden/src/tool/mod.rs index 2130a6b0c..212ce4bf7 100644 --- a/crates/bitwarden/src/tool/mod.rs +++ b/crates/bitwarden/src/tool/mod.rs @@ -1,5 +1,5 @@ mod exporters; mod generators; -pub use exporters::ExportFormat; -pub use generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; +pub use exporters::{ClientExporters, ExportFormat}; +pub use generators::{ClientGenerator, PassphraseGeneratorRequest, PasswordGeneratorRequest}; From a55c2d7733be6ac49b259950301b4b423f3cb4c2 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:25:30 -0800 Subject: [PATCH 035/378] [BEEEP] SM-1005 - Add env output option (#320) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Add an env output option to `bws`. This allows for easier command-line usage in scripts, particularly where a JSON or YAML parser is not desirable or available. Basic usage examples in Bash: - `source <(bws secret get ec9e0489-244e-4b3f-8782-b0a800fe562f -o env)` - `bws secret list -o env > .env` ## Code changes - **`crates/bws/src/render.rs`:** Output secrets in `key="value"` format ## Screenshots ![image](https://github.com/bitwarden/sdk/assets/5676771/72201357-dc4c-471e-b1f0-011297dbb978) ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --------- Co-authored-by: Daniel García --- Cargo.lock | 1 + crates/bws/Cargo.toml | 1 + crates/bws/src/render.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 184066772..6a02ad594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,6 +539,7 @@ dependencies = [ "env_logger", "log", "openssl", + "regex", "serde", "serde_json", "serde_yaml", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 00ec40da7..9ccd5c546 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -37,6 +37,7 @@ thiserror = "1.0.40" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } +regex = { version = "1.10.2", features=["std", "perf"], default-features=false } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } diff --git a/crates/bws/src/render.rs b/crates/bws/src/render.rs index 4f2a32e9a..83c5cd532 100644 --- a/crates/bws/src/render.rs +++ b/crates/bws/src/render.rs @@ -9,6 +9,7 @@ use serde::Serialize; pub(crate) enum Output { JSON, YAML, + Env, Table, TSV, None, @@ -49,6 +50,31 @@ pub(crate) fn serialize_response, const N: usiz let text = serde_yaml::to_string(&data).unwrap(); pretty_print("yaml", &text, color); } + Output::Env => { + let valid_key_regex = regex::Regex::new("^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap(); + + let mut commented_out = false; + let mut text: Vec = data + .get_values() + .into_iter() + .map(|row| { + if valid_key_regex.is_match(&row[1]) { + format!("{}=\"{}\"", row[1], row[2]) + } else { + commented_out = true; + format!("# {}=\"{}\"", row[1], row[2].replace('\n', "\n# ")) + } + }) + .collect(); + + if commented_out { + text.push(String::from( + "\n# one or more secrets have been commented-out due to a problematic key name", + )); + } + + pretty_print("sh", &format!("{}\n", text.join("\n")), color); + } Output::Table => { let mut table = Table::new(); table From c4b041197652a67e52fafc9dbf772f043e5b393f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:30:53 +0100 Subject: [PATCH 036/378] Update npm minor (#336) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [quicktype-core](https://togithub.com/quicktype/quicktype) | [`23.0.77` -> `23.0.79`](https://renovatebot.com/diffs/npm/quicktype-core/23.0.77/23.0.79) | [![age](https://developer.mend.io/api/mc/badges/age/npm/quicktype-core/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/quicktype-core/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/quicktype-core/23.0.77/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/quicktype-core/23.0.77/23.0.79?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [ts-loader](https://togithub.com/TypeStrong/ts-loader) | [`9.5.0` -> `9.5.1`](https://renovatebot.com/diffs/npm/ts-loader/9.5.0/9.5.1) | [![age](https://developer.mend.io/api/mc/badges/age/npm/ts-loader/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/ts-loader/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/ts-loader/9.5.0/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ts-loader/9.5.0/9.5.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
quicktype/quicktype (quicktype-core) ### [`v23.0.79`](https://togithub.com/quicktype/quicktype/compare/317deefa6a0c8ba0201b9b2b50d00c7e93c41d78...958d199d74b507175d9a49871c5d3770eaaf7873) [Compare Source](https://togithub.com/quicktype/quicktype/compare/317deefa6a0c8ba0201b9b2b50d00c7e93c41d78...958d199d74b507175d9a49871c5d3770eaaf7873) ### [`v23.0.78`](https://togithub.com/quicktype/quicktype/compare/55dc6a7912715b7db45419958bf89d00637cd4cd...317deefa6a0c8ba0201b9b2b50d00c7e93c41d78) [Compare Source](https://togithub.com/quicktype/quicktype/compare/55dc6a7912715b7db45419958bf89d00637cd4cd...317deefa6a0c8ba0201b9b2b50d00c7e93c41d78)
TypeStrong/ts-loader (ts-loader) ### [`v9.5.1`](https://togithub.com/TypeStrong/ts-loader/blob/HEAD/CHANGELOG.md#951) [Compare Source](https://togithub.com/TypeStrong/ts-loader/compare/v9.5.0...v9.5.1) - [fix: inputSourceMap can be null](https://togithub.com/TypeStrong/ts-loader/pull/1639) \[[#​1638](https://togithub.com/TypeStrong/ts-loader/issues/1638)] - thanks [@​johnnyreilly](https://togithub.com/johnnyreilly) and [@​michaeltford](https://togithub.com/michaeltford)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js_webassembly/package-lock.json | 8 ++++---- languages/js_webassembly/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index 066f862be..e3e20e9aa 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -7,7 +7,7 @@ "devDependencies": { "html-webpack-plugin": "5.5.3", "text-encoding": "0.7.0", - "ts-loader": "9.5.0", + "ts-loader": "9.5.1", "wasm-pack": "0.12.1", "webpack": "5.89.0", "webpack-cli": "5.1.4", @@ -3613,9 +3613,9 @@ } }, "node_modules/ts-loader": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.0.tgz", - "integrity": "sha512-LLlB/pkB4q9mW2yLdFMnK3dEHbrBjeZTYguaaIfusyojBgAGf5kF+O6KcWqiGzWqHk0LBsoolrp4VftEURhybg==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", "dev": true, "dependencies": { "chalk": "^4.1.0", diff --git a/languages/js_webassembly/package.json b/languages/js_webassembly/package.json index 95d7002a5..d5d7342df 100644 --- a/languages/js_webassembly/package.json +++ b/languages/js_webassembly/package.json @@ -6,7 +6,7 @@ "devDependencies": { "html-webpack-plugin": "5.5.3", "text-encoding": "0.7.0", - "ts-loader": "9.5.0", + "ts-loader": "9.5.1", "wasm-pack": "0.12.1", "webpack": "5.89.0", "webpack-cli": "5.1.4", diff --git a/package-lock.json b/package-lock.json index 7791b3b69..ac70b185d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.77", + "quicktype-core": "23.0.79", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.77", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.77.tgz", - "integrity": "sha512-QABFgMHVsyW7CAcLGWvIQXgjZ7ehPnebfV/3x9c5HtuJVXgYLrEG/+zyQd1O+OPWpQrhbwU97doJTZRw+acA6A==", + "version": "23.0.79", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.79.tgz", + "integrity": "sha512-Auzy8AhorFt6YGeB53/dzUSINmKKassAyCsr2wpNgG9XoC3i6oUoLuySNUzYIkyCFCGmKdBRBQeyAqPOVteoYw==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index ad38f3a10..97f08c571 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.77", + "quicktype-core": "23.0.79", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" From 9fab1fa4ddbdcae7b597bbb674da4e2fd11fd287 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:58:19 +0100 Subject: [PATCH 037/378] Update Rust crate itertools to 0.12.0 (#338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [itertools](https://togithub.com/rust-itertools/itertools) | dependencies | minor | `0.11.0` -> `0.12.0` | --- ### Release Notes
rust-itertools/itertools (itertools) ### [`v0.12.0`](https://togithub.com/rust-itertools/itertools/blob/HEAD/CHANGELOG.md#0120) [Compare Source](https://togithub.com/rust-itertools/itertools/compare/v0.11.0...v0.12.0) ##### Breaking - Made `take_while_inclusive` consume iterator by value ([#​709](https://togithub.com/rust-itertools/itertools/issues/709)) - Added `Clone` bound to `Unique` ([#​777](https://togithub.com/rust-itertools/itertools/issues/777)) ##### Added - Added `Itertools::try_len` ([#​723](https://togithub.com/rust-itertools/itertools/issues/723)) - Added free function `sort_unstable` ([#​796](https://togithub.com/rust-itertools/itertools/issues/796)) - Added `GroupMap::fold_with` ([#​778](https://togithub.com/rust-itertools/itertools/issues/778), [#​785](https://togithub.com/rust-itertools/itertools/issues/785)) - Added `PeekNth::{peek_mut, peek_nth_mut}` ([#​716](https://togithub.com/rust-itertools/itertools/issues/716)) - Added `PeekNth::{next_if, next_if_eq}` ([#​734](https://togithub.com/rust-itertools/itertools/issues/734)) - Added conversion into `(Option,Option)` to `EitherOrBoth` ([#​713](https://togithub.com/rust-itertools/itertools/issues/713)) - Added conversion from `Either` to `EitherOrBoth` ([#​715](https://togithub.com/rust-itertools/itertools/issues/715)) - Implemented `ExactSizeIterator` for `Tuples` ([#​761](https://togithub.com/rust-itertools/itertools/issues/761)) - Implemented `ExactSizeIterator` for `(Circular)TupleWindows` ([#​752](https://togithub.com/rust-itertools/itertools/issues/752)) - Made `EitherOrBoth` a shorthand for `EitherOrBoth` ([#​719](https://togithub.com/rust-itertools/itertools/issues/719)) ##### Changed - Added missing `#[must_use]` annotations on iterator adaptors ([#​794](https://togithub.com/rust-itertools/itertools/issues/794)) - Made `Combinations` lazy ([#​795](https://togithub.com/rust-itertools/itertools/issues/795)) - Made `Intersperse(With)` lazy ([#​797](https://togithub.com/rust-itertools/itertools/issues/797)) - Made `Permutations` lazy ([#​793](https://togithub.com/rust-itertools/itertools/issues/793)) - Made `Product` lazy ([#​800](https://togithub.com/rust-itertools/itertools/issues/800)) - Made `TupleWindows` lazy ([#​602](https://togithub.com/rust-itertools/itertools/issues/602)) - Specialized `Combinations::{count, size_hint}` ([#​729](https://togithub.com/rust-itertools/itertools/issues/729)) - Specialized `CombinationsWithReplacement::{count, size_hint}` ([#​737](https://togithub.com/rust-itertools/itertools/issues/737)) - Specialized `Powerset::fold` ([#​765](https://togithub.com/rust-itertools/itertools/issues/765)) - Specialized `Powerset::count` ([#​735](https://togithub.com/rust-itertools/itertools/issues/735)) - Specialized `TupleCombinations::{count, size_hint}` ([#​763](https://togithub.com/rust-itertools/itertools/issues/763)) - Specialized `TupleCombinations::fold` ([#​775](https://togithub.com/rust-itertools/itertools/issues/775)) - Specialized `WhileSome::fold` ([#​780](https://togithub.com/rust-itertools/itertools/issues/780)) - Specialized `WithPosition::fold` ([#​772](https://togithub.com/rust-itertools/itertools/issues/772)) - Specialized `ZipLongest::fold` ([#​774](https://togithub.com/rust-itertools/itertools/issues/774)) - Changed `{min, max}_set*` operations require `alloc` feature, instead of `std` ([#​760](https://togithub.com/rust-itertools/itertools/issues/760)) - Improved documentation of `tree_fold1` ([#​787](https://togithub.com/rust-itertools/itertools/issues/787)) - Improved documentation of `permutations` ([#​724](https://togithub.com/rust-itertools/itertools/issues/724)) - Fixed typo in documentation of `multiunzip` ([#​770](https://togithub.com/rust-itertools/itertools/issues/770)) ##### Notable Internal Changes - Improved specialization tests ([#​799](https://togithub.com/rust-itertools/itertools/issues/799), [#​786](https://togithub.com/rust-itertools/itertools/issues/786), [#​782](https://togithub.com/rust-itertools/itertools/issues/782)) - Simplified implementation of `Permutations` ([#​739](https://togithub.com/rust-itertools/itertools/issues/739), [#​748](https://togithub.com/rust-itertools/itertools/issues/748), [#​790](https://togithub.com/rust-itertools/itertools/issues/790)) - Combined `Merge`/`MergeBy`/`MergeJoinBy` implementations ([#​736](https://togithub.com/rust-itertools/itertools/issues/736)) - Simplified `Permutations::size_hint` ([#​739](https://togithub.com/rust-itertools/itertools/issues/739)) - Fix wrapping arithmetic in benchmarks ([#​770](https://togithub.com/rust-itertools/itertools/issues/770)) - Enforced `rustfmt` in CI ([#​751](https://togithub.com/rust-itertools/itertools/issues/751)) - Disallowed compile warnings in CI ([#​720](https://togithub.com/rust-itertools/itertools/issues/720)) - Used `cargo hack` to check MSRV ([#​754](https://togithub.com/rust-itertools/itertools/issues/754))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a02ad594..7ca15b625 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1647,9 +1647,9 @@ checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index c6de9eaca..64ce34274 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -15,7 +15,7 @@ internal = [ schemars = { version = "0.8.12", features = ["preserve_order"] } serde_json = "1.0.96" anyhow = "1.0.71" -itertools = "0.11.0" +itertools = "0.12.0" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From 8788f184750fef3045d0fc38666ddf82627d34b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 20 Nov 2023 11:03:45 +0100 Subject: [PATCH 038/378] Split initializeCrypto (#329) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Split initializeCrypto into separate user and organization methods, so clients won't need to hold on to the master password until after sync is done to initialize the organization keys. --- crates/bitwarden-uniffi/README.md | 1 + crates/bitwarden-uniffi/src/crypto.rs | 35 +++++++ crates/bitwarden-uniffi/src/docs.rs | 5 +- crates/bitwarden-uniffi/src/lib.rs | 22 +---- .../src/client/encryption_settings.rs | 4 + crates/bitwarden/src/mobile/client_crypto.rs | 13 ++- crates/bitwarden/src/mobile/crypto.rs | 57 +++++++---- crates/bitwarden/tests/register.rs | 16 ++- .../bitwarden/myapplication/MainActivity.kt | 21 ++-- languages/kotlin/doc.md | 99 +++++++++++++++---- languages/swift/iOS/App/ContentView.swift | 14 ++- 11 files changed, 212 insertions(+), 75 deletions(-) create mode 100644 crates/bitwarden-uniffi/src/crypto.rs diff --git a/crates/bitwarden-uniffi/README.md b/crates/bitwarden-uniffi/README.md index 7dff0b291..1be7706bb 100644 --- a/crates/bitwarden-uniffi/README.md +++ b/crates/bitwarden-uniffi/README.md @@ -5,6 +5,7 @@ ```bash cargo +nightly rustdoc -p bitwarden -- -Zunstable-options --output-format json cargo +nightly rustdoc -p bitwarden-uniffi -- -Zunstable-options --output-format json +npm run schemas npx ts-node ./support/docs/docs.ts > languages/kotlin/doc.md ``` diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs new file mode 100644 index 000000000..1792a5bbc --- /dev/null +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -0,0 +1,35 @@ +use std::sync::Arc; + +use bitwarden::mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}; + +use crate::{error::Result, Client}; + +#[derive(uniffi::Object)] +pub struct ClientCrypto(pub(crate) Arc); + +#[uniffi::export] +impl ClientCrypto { + /// Initialization method for the user crypto. Needs to be called before any other crypto operations. + pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .initialize_user_crypto(req) + .await?) + } + + /// Initialization method for the organization crypto. Needs to be called after `initialize_user_crypto` but before any other crypto operations. + pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .initialize_org_crypto(req) + .await?) + } +} diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index bc47a19c3..45fabb0b7 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,7 +1,7 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, client::kdf::Kdf, - mobile::crypto::InitCryptoRequest, + mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, vault::{ Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, @@ -24,7 +24,8 @@ pub enum DocRef { SendListView(SendListView), // Crypto - InitCryptoRequest(InitCryptoRequest), + InitUserCryptoRequest(InitUserCryptoRequest), + InitOrgCryptoRequest(InitOrgCryptoRequest), // Generators PasswordGeneratorRequest(PasswordGeneratorRequest), diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 6e5415d38..5035f22b9 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -4,9 +4,10 @@ use std::sync::Arc; use async_lock::RwLock; use auth::ClientAuth; -use bitwarden::{client::client_settings::ClientSettings, mobile::crypto::InitCryptoRequest}; +use bitwarden::client::client_settings::ClientSettings; pub mod auth; +pub mod crypto; mod error; pub mod tool; mod uniffi_support; @@ -15,6 +16,7 @@ pub mod vault; #[cfg(feature = "docs")] pub mod docs; +use crypto::ClientCrypto; use error::Result; use tool::ClientGenerators; use vault::ClientVault; @@ -22,9 +24,6 @@ use vault::ClientVault; #[derive(uniffi::Object)] pub struct Client(RwLock); -#[derive(uniffi::Object)] -pub struct ClientCrypto(Arc); - #[uniffi::export] impl Client { /// Initialize a new instance of the SDK client @@ -58,18 +57,3 @@ impl Client { msg } } - -#[uniffi::export] -impl ClientCrypto { - /// Initialization method for the crypto. Needs to be called before any other crypto operations. - pub async fn initialize_crypto(&self, req: InitCryptoRequest) -> Result<()> { - Ok(self - .0 - .0 - .write() - .await - .crypto() - .initialize_crypto(req) - .await?) - } -} diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index da5398a12..6533c7d2e 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -80,6 +80,10 @@ impl EncryptionSettings { let private_key = self.private_key.as_ref().ok_or(Error::VaultLocked)?; + // Make sure we only keep the keys given in the arguments and not any of the previous + // ones, which might be from organizations that the user is no longer a part of anymore + self.org_keys.clear(); + // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { let data = match org_enc_key { diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index 67f69d8f1..c0edb1982 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -2,7 +2,9 @@ use crate::Client; #[cfg(feature = "internal")] use crate::{ error::Result, - mobile::crypto::{initialize_crypto, InitCryptoRequest}, + mobile::crypto::{ + initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoRequest, + }, }; pub struct ClientCrypto<'a> { @@ -11,8 +13,13 @@ pub struct ClientCrypto<'a> { impl<'a> ClientCrypto<'a> { #[cfg(feature = "internal")] - pub async fn initialize_crypto(&mut self, req: InitCryptoRequest) -> Result<()> { - initialize_crypto(self.client, req).await + pub async fn initialize_user_crypto(&mut self, req: InitUserCryptoRequest) -> Result<()> { + initialize_user_crypto(self.client, req).await + } + + #[cfg(feature = "internal")] + pub async fn initialize_org_crypto(&mut self, req: InitOrgCryptoRequest) -> Result<()> { + initialize_org_crypto(self.client, req).await } } diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index f4d26dc6c..2cf850279 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -9,23 +9,32 @@ use crate::{client::kdf::Kdf, crypto::EncString, error::Result, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] -pub struct InitCryptoRequest { +pub struct InitUserCryptoRequest { /// The user's KDF parameters, as received from the prelogin request pub kdf_params: Kdf, /// The user's email address pub email: String, - /// The user's master password - pub password: String, - /// The user's encrypted symmetric crypto key - pub user_key: String, - /// The user's encryptred private key + /// The user's encrypted private key pub private_key: String, - /// The encryption keys for all the organizations the user is a part of - pub organization_keys: HashMap, + /// The initialization method to use + pub method: InitUserCryptoMethod, } #[cfg(feature = "internal")] -pub async fn initialize_crypto(client: &mut Client, req: InitCryptoRequest) -> Result<()> { +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum InitUserCryptoMethod { + Password { + /// The user's master password + password: String, + /// The user's encrypted symmetric crypto key + user_key: String, + }, +} + +#[cfg(feature = "internal")] +pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), email: req.email, @@ -33,18 +42,30 @@ pub async fn initialize_crypto(client: &mut Client, req: InitCryptoRequest) -> R }); client.set_login_method(login_method); - let user_key = req.user_key.parse::()?; - let private_key = req.private_key.parse::()?; + let private_key: EncString = req.private_key.parse()?; - client.initialize_user_crypto(&req.password, user_key, private_key)?; + match req.method { + InitUserCryptoMethod::Password { password, user_key } => { + let user_key: EncString = user_key.parse()?; + client.initialize_user_crypto(&password, user_key, private_key)?; + } + } - let organization_keys = req - .organization_keys - .into_iter() - .map(|(k, v)| Ok((k, v.parse::()?))) - .collect::>>()?; + Ok(()) +} - client.initialize_org_crypto(organization_keys)?; +#[cfg(feature = "internal")] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct InitOrgCryptoRequest { + /// The encryption keys for all the organizations the user is a part of + pub organization_keys: HashMap, +} +#[cfg(feature = "internal")] +pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoRequest) -> Result<()> { + let organization_keys = req.organization_keys.into_iter().collect(); + client.initialize_org_crypto(organization_keys)?; Ok(()) } diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs index d4e632e55..956fe86ce 100644 --- a/crates/bitwarden/tests/register.rs +++ b/crates/bitwarden/tests/register.rs @@ -4,7 +4,11 @@ async fn test_register_initialize_crypto() { use std::num::NonZeroU32; - use bitwarden::{client::kdf::Kdf, mobile::crypto::InitCryptoRequest, Client}; + use bitwarden::{ + client::kdf::Kdf, + mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, + Client, + }; let mut client = Client::new(None); @@ -22,13 +26,15 @@ async fn test_register_initialize_crypto() { // Ensure we can initialize the crypto with the new keys client .crypto() - .initialize_crypto(InitCryptoRequest { + .initialize_user_crypto(InitUserCryptoRequest { kdf_params: kdf, email: email.to_owned(), - password: password.to_owned(), - user_key: register_response.encrypted_user_key, private_key: register_response.keys.private.to_string(), - organization_keys: Default::default(), + + method: InitUserCryptoMethod::Password { + password: password.to_owned(), + user_key: register_response.encrypted_user_key, + }, }) .await .unwrap(); diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 2d204e075..13dec7d0e 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -12,7 +12,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import com.bitwarden.core.DateTime import com.bitwarden.core.Folder -import com.bitwarden.core.InitCryptoRequest +import com.bitwarden.core.InitOrgCryptoRequest +import com.bitwarden.core.InitUserCryptoMethod +import com.bitwarden.core.InitUserCryptoRequest import com.bitwarden.core.Kdf import com.bitwarden.core.Uuid import com.bitwarden.myapplication.ui.theme.MyApplicationTheme @@ -117,7 +119,7 @@ class MainActivity : ComponentActivity() { }.body() val folders = (syncBody["folders"] as JsonArray).map { - val o = it as JsonObject; + val o = it as JsonObject Folder( (o["id"] as JsonPrimitive).content, (o["name"] as JsonPrimitive).content, @@ -136,13 +138,20 @@ class MainActivity : ComponentActivity() { orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content } - client.crypto().initializeCrypto( - InitCryptoRequest( + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( kdfParams = kdf, email = EMAIL, - password = PASSWORD, - userKey = loginBody.Key, privateKey = loginBody.PrivateKey, + method = InitUserCryptoMethod.Password( + password = PASSWORD, + userKey = loginBody.Key + ) + ) + ) + + client.crypto().initializeOrgCrypto( + InitOrgCryptoRequest( organizationKeys = orgKeys ) ) diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 6174df750..70446bd8f 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -182,14 +182,26 @@ Decrypt collection list ## ClientCrypto -### `initialize_crypto` +### `initialize_user_crypto` -Initialization method for the crypto. Needs to be called before any other crypto operations. +Initialization method for the user crypto. Needs to be called before any other crypto operations. **Arguments**: - self: -- req: [InitCryptoRequest](#initcryptorequest) +- req: [InitUserCryptoRequest](#initusercryptorequest) + +**Output**: std::result::Result<,BitwardenError> + +### `initialize_org_crypto` + +Initialization method for the organization crypto. Needs to be called after +`initialize_user_crypto` but before any other crypto operations. + +**Arguments**: + +- self: +- req: [InitOrgCryptoRequest](#initorgcryptorequest) **Output**: std::result::Result<,BitwardenError> @@ -492,6 +504,11 @@ implementations. array + + key + + More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + name @@ -617,6 +634,11 @@ implementations. array + + key + + + name string @@ -835,7 +857,7 @@ implementations. -## `InitCryptoRequest` +## `InitOrgCryptoRequest` @@ -844,34 +866,75 @@ implementations. - - - + + + +
Description
kdfParamsThe user's KDF parameters, as received from the prelogin requestorganizationKeysobjectThe encryption keys for all the organizations the user is a part of
+ +## `InitUserCryptoMethod` + + - - - + + + - - + + + + + + +
emailstringThe user's email addressKeyTypeDescription
passwordstringThe user's master passwordobject
+ + + + + + + + + + + + + + + + +
KeyTypeDescription
passwordstringThe user's master password
user_keystringThe user's encrypted symmetric crypto key
+
+ +## `InitUserCryptoRequest` + + + + + + + + + + + - + - + - + - - - + + +
KeyTypeDescription
kdfParamsThe user's KDF parameters, as received from the prelogin request
userKeyemail stringThe user's encrypted symmetric crypto keyThe user's email address
privateKey stringThe user's encryptred private keyThe user's encrypted private key
organizationKeysobjectThe encryption keys for all the organizations the user is a part ofmethodThe initialization method to use
diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index 4b3555403..484caf14f 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -136,13 +136,19 @@ struct ContentView: View { ///////////////////////////// Initialize crypto ///////////////////////////// - try await client.crypto().initializeCrypto( - req: InitCryptoRequest( + try await client.crypto().initializeUserCrypto( + req: InitUserCryptoRequest( kdfParams: kdf, email: EMAIL, - password: PASSWORD, - userKey: loginData.Key, privateKey: loginData.PrivateKey, + method: InitUserCryptoMethod.password( + password: PASSWORD, + userKey: loginData.Key + ) + )) + + try await client.crypto().initializeOrgCrypto( + req: InitOrgCryptoRequest( organizationKeys: Dictionary.init( uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } ) From 4c68256820e65572313d209c5c09e07f0f2d29e1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:38:19 +0100 Subject: [PATCH 039/378] Update pyo3 non-major (#289) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [pyo3](https://togithub.com/pyo3/pyo3) | dependencies | minor | `0.19.1` -> `0.20.0` | | [pyo3-asyncio](https://togithub.com/awestlake87/pyo3-asyncio) | dependencies | minor | `0.19.0` -> `0.20.0` | | [pyo3-build-config](https://togithub.com/pyo3/pyo3) | build-dependencies | minor | `0.19.1` -> `0.20.0` | | [pyo3-log](https://togithub.com/vorner/pyo3-log) | dependencies | minor | `0.8.3` -> `0.9.0` | --- ### Release Notes
pyo3/pyo3 (pyo3) ### [`v0.20.0`](https://togithub.com/pyo3/pyo3/blob/HEAD/CHANGELOG.md#0200---2023-10-11) [Compare Source](https://togithub.com/pyo3/pyo3/compare/v0.19.2...v0.20.0) ##### Packaging - Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#​3108](https://togithub.com/PyO3/pyo3/pull/3108) - Update MSRV to Rust 1.56. [#​3208](https://togithub.com/PyO3/pyo3/pull/3208) - Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#​3237](https://togithub.com/PyO3/pyo3/pull/3237) - Bump `syn` dependency to 2.0. [#​3239](https://togithub.com/PyO3/pyo3/pull/3239) - Drop support for debug builds of Python 3.7. [#​3387](https://togithub.com/PyO3/pyo3/pull/3387) - Bump `chrono` optional dependency to require 0.4.25 or newer. [#​3427](https://togithub.com/PyO3/pyo3/pull/3427) - Support Python 3.12. [#​3488](https://togithub.com/PyO3/pyo3/pull/3488) ##### Added - Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#​3203](https://togithub.com/PyO3/pyo3/pull/3203) - Add FFI definition `Py_GETENV`. [#​3336](https://togithub.com/PyO3/pyo3/pull/3336) - Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#​3359](https://togithub.com/PyO3/pyo3/pull/3359) - Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#​3366](https://togithub.com/PyO3/pyo3/pull/3366) - Add `#[pyclass(rename_all = "...")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `"camelCase"`, `"kebab-case"`, `"lowercase"`, `"PascalCase"`, `"SCREAMING-KEBAB-CASE"`, `"SCREAMING_SNAKE_CASE"`, `"snake_case"`, `"UPPERCASE"`. [#​3384](https://togithub.com/PyO3/pyo3/pull/3384) - Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#​3403](https://togithub.com/PyO3/pyo3/pull/3403) - Add types for `None`, `Ellipsis`, and `NotImplemented`. [#​3408](https://togithub.com/PyO3/pyo3/pull/3408) - Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#​3494](https://togithub.com/PyO3/pyo3/pull/3494) - Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#​3502](https://togithub.com/PyO3/pyo3/pull/3502) ##### Changed - Change `PySet::discard` to return `PyResult` (previously returned nothing). [#​3281](https://togithub.com/PyO3/pyo3/pull/3281) - Optimize implmentation of `IntoPy` for Rust tuples to Python tuples. [#​3321](https://togithub.com/PyO3/pyo3/pull/3321) - Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#​3330](https://togithub.com/PyO3/pyo3/pull/3330) - Deprecate FFI definitions which are deprecated in Python 3.12. [#​3336](https://togithub.com/PyO3/pyo3/pull/3336) - `AsPyPointer` is now an `unsafe trait`. [#​3358](https://togithub.com/PyO3/pyo3/pull/3358) - Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#​3374](https://togithub.com/PyO3/pyo3/pull/3374) - Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#​3378](https://togithub.com/PyO3/pyo3/pull/3378) - Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#​3379](https://togithub.com/PyO3/pyo3/pull/3379) - `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#​3389](https://togithub.com/PyO3/pyo3/pull/3389) - Replace `AsPyPointer` with `AsRef` as a bound in the blanket implementation of `From<&T> for PyObject`. [#​3391](https://togithub.com/PyO3/pyo3/pull/3391) - Replace blanket `impl IntoPy for &T where T: AsPyPointer` with implementations of `impl IntoPy` for `&PyAny`, `&T where T: AsRef`, and `&Py`. [#​3393](https://togithub.com/PyO3/pyo3/pull/3393) - Preserve `std::io::Error` kind in implementation of `From` for `PyErr` [#​3396](https://togithub.com/PyO3/pyo3/pull/3396) - Try to select a relevant `ErrorKind` in implementation of `From` for `OSError` subclass. [#​3397](https://togithub.com/PyO3/pyo3/pull/3397) - Retrieve the original `PyErr` in implementation of `From` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#​3402](https://togithub.com/PyO3/pyo3/pull/3402) - `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#​3446](https://togithub.com/PyO3/pyo3/pull/3446) - Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#​3458](https://togithub.com/PyO3/pyo3/pull/3458) - `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#​3455](https://togithub.com/PyO3/pyo3/pull/3455) - Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#​3505](https://togithub.com/PyO3/pyo3/pull/3505) ##### Removed - Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#​3232](https://togithub.com/PyO3/pyo3/pull/3232) - Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#​3385](https://togithub.com/PyO3/pyo3/pull/3385) ##### Fixed - Handle exceptions properly in `PySet::discard`. [#​3281](https://togithub.com/PyO3/pyo3/pull/3281) - The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#​3366](https://togithub.com/PyO3/pyo3/pull/3366) - Linking of `PyOS_FSPath` on PyPy. [#​3374](https://togithub.com/PyO3/pyo3/pull/3374) - Fix memory leak in `PyTypeBuilder::build`. [#​3401](https://togithub.com/PyO3/pyo3/pull/3401) - Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#​3403](https://togithub.com/PyO3/pyo3/pull/3403) - Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#​3404](https://togithub.com/PyO3/pyo3/pull/3404) - Some-wrapping of `Option` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#​3461](https://togithub.com/PyO3/pyo3/pull/3461) - Fix `IterNextOutput::Return` not returning a value on PyPy. [#​3471](https://togithub.com/PyO3/pyo3/pull/3471) - Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#​3491](https://togithub.com/PyO3/pyo3/pull/3491) - Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#​3484](https://togithub.com/PyO3/pyo3/pull/3484) - Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#​3490](https://togithub.com/PyO3/pyo3/pull/3490) - Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#​3500](https://togithub.com/PyO3/pyo3/pull/3500) ### [`v0.19.2`](https://togithub.com/pyo3/pyo3/blob/HEAD/CHANGELOG.md#0192---2023-08-01) [Compare Source](https://togithub.com/pyo3/pyo3/compare/v0.19.1...v0.19.2) ##### Added - Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#​3295](https://togithub.com/PyO3/pyo3/pull/3295) - Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#​3297](https://togithub.com/PyO3/pyo3/pull/3297) - Add a "performance" section to the guide collecting performance-related tricks and problems. [#​3304](https://togithub.com/PyO3/pyo3/pull/3304) - Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#​3334](https://togithub.com/PyO3/pyo3/pull/3334) - Add FFI definition `PyType_GetDict()` for Python 3.12. [#​3339](https://togithub.com/PyO3/pyo3/pull/3339) - Add `PyAny::downcast_exact`. [#​3346](https://togithub.com/PyO3/pyo3/pull/3346) - Add `PySlice::full()` to construct a full slice (`::`). [#​3353](https://togithub.com/PyO3/pyo3/pull/3353) ##### Changed - Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#​3306](https://togithub.com/PyO3/pyo3/pull/3306) - Update FFI definitions of `object.h` for Python 3.12.0b4. [#​3335](https://togithub.com/PyO3/pyo3/pull/3335) - Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#​3342](https://togithub.com/PyO3/pyo3/pull/3342) - Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#​3345](https://togithub.com/PyO3/pyo3/pull/3345) ##### Fixed - Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#​3269](https://togithub.com/PyO3/pyo3/pull/3269) - Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#​3297](https://togithub.com/PyO3/pyo3/pull/3297) - Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#​3300](https://togithub.com/PyO3/pyo3/pull/3300) - Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#​3313](https://togithub.com/PyO3/pyo3/pull/3313) - Fix loss of panic message in `PanicException` when unwinding after the exception was "normalized". [#​3326](https://togithub.com/PyO3/pyo3/pull/3326) - Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#​3328](https://togithub.com/PyO3/pyo3/pull/3328) - Fix reference counting of immortal objects on Python 3.12.0b4. [#​3335](https://togithub.com/PyO3/pyo3/pull/3335)
vorner/pyo3-log (pyo3-log) ### [`v0.9.0`](https://togithub.com/vorner/pyo3-log/blob/HEAD/CHANGELOG.md#090) [Compare Source](https://togithub.com/vorner/pyo3-log/compare/v0.8.4...v0.9.0) - Bump lowest allowed version of pyo3 to 0.15 ‒ this prevents linking multiple pyo3 versions together. ### [`v0.8.4`](https://togithub.com/vorner/pyo3-log/blob/HEAD/CHANGELOG.md#084) [Compare Source](https://togithub.com/vorner/pyo3-log/compare/v0.8.3...v0.8.4) - Allow pyo3 0.20.
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 45 +++++++++++++++++----------------- crates/bitwarden-py/Cargo.toml | 8 +++--- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ca15b625..e4ad7e61e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1577,9 +1577,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.9" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "infer" @@ -2274,9 +2274,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" +checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" dependencies = [ "cfg-if", "indoc", @@ -2291,9 +2291,9 @@ dependencies = [ [[package]] name = "pyo3-asyncio" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cc34c1f907ca090d7add03dc523acdd91f3a4dab12286604951e2f5152edad" +checksum = "6ea6b68e93db3622f3bb3bf363246cf948ed5375afe7abff98ccbdd50b184995" dependencies = [ "futures", "once_cell", @@ -2305,9 +2305,9 @@ dependencies = [ [[package]] name = "pyo3-asyncio-macros" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4045f06429547179e4596f5c0b13c82efc8b04296016780133653ed69ce26b3" +checksum = "56c467178e1da6252c95c29ecf898b133f742e9181dca5def15dc24e19d45a39" dependencies = [ "proc-macro2", "quote", @@ -2316,9 +2316,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" +checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" dependencies = [ "once_cell", "target-lexicon", @@ -2326,9 +2326,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" +checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" dependencies = [ "libc", "pyo3-build-config", @@ -2336,9 +2336,9 @@ dependencies = [ [[package]] name = "pyo3-log" -version = "0.8.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09c2b349b6538d8a73d436ca606dab6ce0aaab4dad9e6b7bdd57a4f556c3bc3" +checksum = "4c10808ee7250403bedb24bc30c32493e93875fef7ba3e4292226fe924f398bd" dependencies = [ "arc-swap", "log", @@ -2347,25 +2347,26 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" +checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] name = "pyo3-macros-backend" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" +checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" dependencies = [ + "heck", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.38", ] [[package]] @@ -3581,9 +3582,9 @@ dependencies = [ [[package]] name = "unindent" -version = "0.1.11" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "unsafe-libyaml" diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 5d8d95575..613203c84 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -10,17 +10,17 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.19.1", features = ["extension-module"] } -pyo3-log = "0.8.3" +pyo3 = { version = "0.20.0", features = ["extension-module"] } +pyo3-log = "0.9.0" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [build-dependencies] -pyo3-build-config = { version = "0.19.1" } +pyo3-build-config = { version = "0.20.0" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } -pyo3-asyncio = { version = "0.19.0", features = [ +pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", ] } From d64782e7bf4937eb50500556057a70b686ac57ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:32:10 +0100 Subject: [PATCH 040/378] Lock file maintenance (#324) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate logo banner](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Daniel García --- Cargo.lock | 283 +++++++++++---------- crates/bitwarden-napi/package-lock.json | 6 +- crates/bitwarden-napi/src/client.rs | 1 - crates/bitwarden-wasm/Cargo.toml | 2 +- languages/js_webassembly/package-lock.json | 168 ++++++------ package-lock.json | 30 +-- 6 files changed, 247 insertions(+), 243 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4ad7e61e..f9fbba7e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -203,11 +203,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e900cdcd39bb94a14487d3f7ef92ca222162e6c7c3fe7cb3550ea75fb486ed" +checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "event-listener-strategy", "pin-project-lite", ] @@ -220,7 +220,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -332,7 +332,7 @@ dependencies = [ "bitwarden-api-identity", "cbc", "chrono", - "getrandom 0.2.10", + "getrandom 0.2.11", "hkdf", "hmac", "lazy_static", @@ -495,9 +495,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -547,7 +547,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.6", + "toml 0.8.8", "uuid", ] @@ -586,9 +586,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ "serde", ] @@ -656,9 +656,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -694,7 +694,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -732,9 +732,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -925,7 +925,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1002,9 +1002,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "either" @@ -1029,9 +1029,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", "is-terminal", @@ -1048,9 +1048,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1064,9 +1064,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cec0252c2afff729ee6f00e903d479fba81784c8e2bd77447673471fdfaea1" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ "concurrent-queue", "parking", @@ -1079,15 +1079,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" dependencies = [ - "event-listener 3.0.1", + "event-listener 3.1.0", "pin-project-lite", ] [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" dependencies = [ "indenter", "once_cell", @@ -1150,9 +1150,12 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "fb5fd9bcbe8b1087cbd395b51498c01bc997cef73e778a80b77a811af5e2d29f" +dependencies = [ + "autocfg", +] [[package]] name = "futures" @@ -1225,7 +1228,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1300,9 +1303,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -1349,9 +1352,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1359,7 +1362,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1419,9 +1422,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1567,9 +1570,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.2", @@ -1680,18 +1683,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1700,6 +1703,17 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] + [[package]] name = "line-wrap" version = "0.1.1" @@ -1711,9 +1725,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "lock_api" @@ -1814,9 +1828,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.13.3" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd063c93b900149304e3ba96ce5bf210cd4f81ef5eb80ded0d100df3e85a3ac0" +checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" dependencies = [ "bitflags 2.4.1", "ctor", @@ -1828,15 +1842,15 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882a73d9ef23e8dc2ebbffb6a6ae2ef467c0f18ac10711e4cc59c5485d41df0e" +checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.13.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da1c6a8fa84d549aa8708fcd062372bf8ec6e849de39016ab921067d21bde367" +checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330" dependencies = [ "cfg-if", "convert_case", @@ -1848,9 +1862,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.52" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20bbc7c69168d06a848f925ec5f0e0997f98e8c8d4f2cc30157f0da51c009e17" +checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91" dependencies = [ "convert_case", "once_cell", @@ -1863,9 +1877,9 @@ dependencies = [ [[package]] name = "napi-sys" -version = "2.2.3" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166b5ef52a3ab5575047a9fe8d4a030cdd0f63c96f071cd6907674453b07bae3" +checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" dependencies = [ "libloading", ] @@ -2043,9 +2057,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -2064,7 +2078,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2084,9 +2098,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -2137,7 +2151,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -2239,12 +2253,12 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] name = "plist" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.5", - "indexmap 1.9.3", + "indexmap 2.1.0", "line-wrap", "quick-xml", "serde", @@ -2354,7 +2368,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2366,14 +2380,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", ] @@ -2446,7 +2460,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -2458,15 +2472,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -2478,12 +2483,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -2619,9 +2624,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -2668,9 +2673,9 @@ dependencies = [ [[package]] name = "schemars" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7b0ce13155372a76ee2e1c5ffba1fe61ede73fbea5630d61eee6fac4929c0c" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "chrono", "dyn-clone", @@ -2683,9 +2688,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e85e2a16b12bdb763244c69ab79363d71db2b4b918a2def53f80b02e0574b13c" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -2722,7 +2727,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2772,22 +2777,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.190" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2842,7 +2847,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -2872,7 +2877,7 @@ version = "0.9.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -2942,9 +2947,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core 0.6.4", @@ -2967,9 +2972,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" @@ -3041,7 +3046,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3073,9 +3078,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -3136,16 +3141,16 @@ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -3167,7 +3172,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3226,9 +3231,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -3243,13 +3248,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3287,9 +3292,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff9e3abce27ee2c9a37f9ad37238c1bdd4e789c84ba37df76aa4d528f5072cc" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", @@ -3308,11 +3313,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -3344,7 +3349,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3369,20 +3374,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term 0.46.0", @@ -3510,7 +3515,7 @@ version = "0.25.0" source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -3540,7 +3545,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.38", + "syn 2.0.39", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3612,9 +3617,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "c58fe91d841bc04822c9801002db4ea904b9e4b8e6bbad25127b46eff8dc516b" dependencies = [ "serde", ] @@ -3697,7 +3702,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] @@ -3731,7 +3736,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3967,9 +3972,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -3986,9 +3991,9 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.19" +version = "0.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f71803d3a1c80377a06221e0530be02035d5b3e854af56c6ece7ac20ac441d" +checksum = "079aee011e8a8e625d16df9e785de30a6b77f80a6126092d76a57375f96448da" dependencies = [ "assert-json-diff", "async-trait", @@ -4008,6 +4013,6 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 65266d1e4..3ccf3a7cb 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "peer": true, "dependencies": { diff --git a/crates/bitwarden-napi/src/client.rs b/crates/bitwarden-napi/src/client.rs index 840fd2533..d794b18f4 100644 --- a/crates/bitwarden-napi/src/client.rs +++ b/crates/bitwarden-napi/src/client.rs @@ -1,7 +1,6 @@ extern crate log; use bitwarden_json::client::Client as JsonClient; -use napi::bindgen_prelude::*; use napi_derive::napi; #[napi] diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 6055388fb..add03f0f3 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] js-sys = "0.3.63" serde = {version = "1.0.163", features = ["derive"] } -wasm-bindgen = { version = "0.2.86", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.36" console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index e3e20e9aa..d5345c00a 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -88,9 +88,9 @@ "dev": true }, "node_modules/@types/body-parser": { - "version": "1.19.4", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.4.tgz", - "integrity": "sha512-N7UDG0/xiPQa2D/XrVJXjkWbpqHCd2sBaB32ggRF2l83RhPfamgKGF8gwwqyksS95qUS5ZYF9aF+lLPRlwI2UA==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "dev": true, "dependencies": { "@types/connect": "*", @@ -98,27 +98,27 @@ } }, "node_modules/@types/bonjour": { - "version": "3.5.12", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.12.tgz", - "integrity": "sha512-ky0kWSqXVxSqgqJvPIkgFkcn4C8MnRog308Ou8xBBIVo39OmUFy+jqNe0nPwLCDFxUpmT9EvT91YzOJgkDRcFg==", + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.37", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.37.tgz", - "integrity": "sha512-zBUSRqkfZ59OcwXon4HVxhx5oWCJmc0OtBTK05M+p0dYjgN6iTwIL2T/WbsQZrEsdnwaF9cWQ+azOnpPvIqY3Q==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.2.tgz", - "integrity": "sha512-gX2j9x+NzSh4zOhnRPSdPPmTepS4DfxES0AvIFv3jGv5QyeAJf6u6dY5/BAoAJU9Qq1uTvwOku8SSC2GnCRl6Q==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.3.tgz", + "integrity": "sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.6.tgz", - "integrity": "sha512-P6bY56TVmX8y9J87jHNgQh43h6VVU+6H7oN7hgvivV81K2XY8qJZ5vqPy/HdUoVIelii2kChYVzQanlswPWVFw==", + "version": "8.44.7", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", + "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -136,9 +136,9 @@ } }, "node_modules/@types/eslint-scope": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.6.tgz", - "integrity": "sha512-zfM4ipmxVKWdxtDaJ3MP3pBurDXOCoyjvlpE3u6Qzrmw4BPbfm4/ambIeTk/r/J0iq/+2/xp0Fmt+gFvXJY2PQ==", + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "dependencies": { "@types/eslint": "*", @@ -146,15 +146,15 @@ } }, "node_modules/@types/estree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.3.tgz", - "integrity": "sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, "node_modules/@types/express": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.20.tgz", - "integrity": "sha512-rOaqlkgEvOW495xErXMsmyX3WKBInbhG5eqojXYi3cGUaLoRDlXa5d52fkfWZT963AZ3v2eZ4MbKE6WpDAGVsw==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "dev": true, "dependencies": { "@types/body-parser": "*", @@ -164,9 +164,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.39", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.39.tgz", - "integrity": "sha512-BiEUfAiGCOllomsRAZOiMFP7LAnrifHpt56pc4Z7l9K6ACyN06Ns1JLMBxwkfLOjJRlSf06NwWsT7yzfpaVpyQ==", + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", "dev": true, "dependencies": { "@types/node": "*", @@ -182,60 +182,60 @@ "dev": true }, "node_modules/@types/http-errors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.3.tgz", - "integrity": "sha512-pP0P/9BnCj1OVvQR2lF41EkDG/lWWnDyA203b/4Fmi2eTyORnBtcDoKDwjWQthELrBvWkMOrvSOnZ8OVlW6tXA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "dev": true }, "node_modules/@types/http-proxy": { - "version": "1.17.13", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.13.tgz", - "integrity": "sha512-GkhdWcMNiR5QSQRYnJ+/oXzu0+7JJEPC8vkWXK351BkhjraZF+1W13CUYARUvX9+NqIU2n6YHA4iwywsc/M6Sw==", + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", - "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.4.tgz", - "integrity": "sha512-1Gjee59G25MrQGk8bsNvC6fxNiRgUlGn2wlhGf95a59DrprnnHk80FIMMFG9XHMdrfsuA119ht06QPDXA1Z7tw==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/node-forge": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.8.tgz", - "integrity": "sha512-vGXshY9vim9CJjrpcS5raqSjEfKlJcWy2HNdgUasR66fAnVEYarrf1ULV4nfvpC1nZq/moA9qyqBcu83x+Jlrg==", + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.9.tgz", + "integrity": "sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/qs": { - "version": "6.9.9", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.9.tgz", - "integrity": "sha512-wYLxw35euwqGvTDx6zfY1vokBFnsK0HNrzc6xNHchxfO2hpuRg74GbkEW7e3sSmPvj0TjCDT1VCa6OtHXnubsg==", + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", "dev": true }, "node_modules/@types/range-parser": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.6.tgz", - "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "dev": true }, "node_modules/@types/retry": { @@ -245,9 +245,9 @@ "dev": true }, "node_modules/@types/send": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.3.tgz", - "integrity": "sha512-/7fKxvKUoETxjFUsuFlPB9YndePpxxRAOfGC/yJdc9kTjTeP5kRCTzfnE8kPUKCeyiyIZu0YQ76s50hCedI1ug==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "dev": true, "dependencies": { "@types/mime": "^1", @@ -255,18 +255,18 @@ } }, "node_modules/@types/serve-index": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.3.tgz", - "integrity": "sha512-4KG+yMEuvDPRrYq5fyVm/I2uqAJSAwZK9VSa+Zf+zUq9/oxSSvy3kkIqyL+jjStv6UCVi8/Aho0NHtB1Fwosrg==", + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", "dev": true, "dependencies": { "@types/express": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.4.tgz", - "integrity": "sha512-aqqNfs1XTF0HDrFdlY//+SGUxmdSUbjeRXb5iaZc3x0/vMbYmdw9qvOgHWOyyLFxSSRnUuP5+724zBgfw8/WAw==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", "dev": true, "dependencies": { "@types/http-errors": "*", @@ -275,18 +275,18 @@ } }, "node_modules/@types/sockjs": { - "version": "0.3.35", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.35.tgz", - "integrity": "sha512-tIF57KB+ZvOBpAQwSaACfEu7htponHXaFzP7RfKYgsOS0NoYnn+9+jzp7bbq4fWerizI3dTB4NfAZoyeQKWJLw==", + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/ws": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.8.tgz", - "integrity": "sha512-flUksGIQCnJd6sZ1l5dqCEG/ksaoAg/eUwiLAGTJQcfgvZJKF++Ta4bJA6A5aPSJmsr+xlseHn4KLgVlNnvPTg==", + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", + "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", "dev": true, "dependencies": { "@types/node": "*" @@ -836,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001558", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz", - "integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==", + "version": "1.0.30001563", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", + "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", "dev": true, "funding": [ { @@ -1278,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.569", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.569.tgz", - "integrity": "sha512-LsrJjZ0IbVy12ApW3gpYpcmHS3iRxH4bkKOW98y1/D+3cvDUWGcbzbsFinfUS8knpcZk/PG/2p/RnkMCYN7PVg==", + "version": "1.4.588", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", + "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", "dev": true }, "node_modules/encodeurl": { @@ -1315,9 +1315,9 @@ } }, "node_modules/envinfo": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", - "integrity": "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", "dev": true, "bin": { "envinfo": "dist/cli.js" @@ -1327,9 +1327,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.1.tgz", - "integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", "dev": true }, "node_modules/escalade": { @@ -2845,9 +2845,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -3521,9 +3521,9 @@ } }, "node_modules/terser": { - "version": "5.23.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.23.0.tgz", - "integrity": "sha512-Iyy83LN0uX9ZZLCX4Qbu5JiHiWjOCTwrmM9InWOzVeM++KNWEsqV4YgN9U9E8AlohQ6Gs42ztczlWOG/lwDAMA==", + "version": "5.24.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", + "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", diff --git a/package-lock.json b/package-lock.json index ac70b185d..6ee8982ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.8.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", - "integrity": "sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==", + "version": "20.9.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", + "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", "dev": true, "peer": true, "dependencies": { @@ -373,9 +373,9 @@ } }, "node_modules/@types/urijs": { - "version": "1.19.22", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.22.tgz", - "integrity": "sha512-qnYBwfN7O/+i6E1Kr8JaCKsrCLpRCiQ1XxkSxNIYuJ/5Aagt0+HlMX78DJMUrNzDULMz0eu2gcprlxJaDtACOw==", + "version": "1.19.23", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.23.tgz", + "integrity": "sha512-3Zbk6RzmIpvKTNEHO2RcPOGHM++BQEITMqBRR1Ju32WbruhV/pygYgxiP3xA0b1B88zjzs0Izzjxsbj768+IjA==", "dev": true }, "node_modules/abort-controller": { @@ -1252,9 +1252,9 @@ } }, "node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz", + "integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -2007,9 +2007,9 @@ "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -2130,9 +2130,9 @@ } }, "node_modules/yaml": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.3.tgz", - "integrity": "sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" From 27045bf2c33c1906685742e230841e6fe33e9cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 20 Nov 2023 15:32:38 +0100 Subject: [PATCH 041/378] Generate immutable records in uniffi bindings (#332) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update the uniffi code generation to output immutable structs. I've pointed the dependencies to my fork until this is included in the main uniffi repo, but it should be enough to let the mobile devs test if the solution is appropiate for them. --- Cargo.lock | 38 ++++++++++++++--------------- Cargo.toml | 12 ++++----- crates/bitwarden-uniffi/Cargo.toml | 4 +-- crates/bitwarden-uniffi/uniffi.toml | 2 ++ crates/bitwarden/Cargo.toml | 2 +- crates/bitwarden/uniffi.toml | 2 ++ crates/uniffi-bindgen/Cargo.toml | 2 +- 7 files changed, 33 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9fbba7e7..c040eb279 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3457,8 +3457,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3478,8 +3478,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "askama", @@ -3501,8 +3501,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3511,8 +3511,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "quote", "syn 2.0.39", @@ -3520,8 +3520,8 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "bytes", @@ -3535,8 +3535,8 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "bincode", "camino", @@ -3553,8 +3553,8 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "bytes", @@ -3564,8 +3564,8 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "camino", @@ -3576,8 +3576,8 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.25.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +version = "0.25.1" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "anyhow", "uniffi_meta", @@ -3784,7 +3784,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=b369e7c15b1b7ebca34de9028209db11b7ff353d#b369e7c15b1b7ebca34de9028209db11b7ff353d" +source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index da8805342..c7c2906dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ codegen-units = 1 # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true -# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798 +# Using git dependency temporarily to add support for immutable records in generated code [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index a7b774c3c..53da0eb8d 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -18,13 +18,13 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } env_logger = "0.10.0" -uniffi = "=0.25.0" +uniffi = "=0.25.1" schemars = { version = ">=0.8, <0.9", optional = true } bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.25.0", features = ["build"] } +uniffi = { version = "=0.25.1", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden-uniffi/uniffi.toml b/crates/bitwarden-uniffi/uniffi.toml index 456a3676e..c9cb0899c 100644 --- a/crates/bitwarden-uniffi/uniffi.toml +++ b/crates/bitwarden-uniffi/uniffi.toml @@ -1,7 +1,9 @@ [bindings.kotlin] package_name = "com.bitwarden.sdk" cdylib_name = "bitwarden_uniffi" +generate_immutable_records = true [bindings.swift] ffi_module_name = "BitwardenFFI" module_name = "BitwardenSDK" +generate_immutable_records = true diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 65db9db7d..fea9a2fd7 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -50,7 +50,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -uniffi = { version = "=0.25.0", optional = true } +uniffi = { version = "=0.25.1", optional = true } # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9", features = ["js"] } diff --git a/crates/bitwarden/uniffi.toml b/crates/bitwarden/uniffi.toml index 5c66e5382..bc4a9d9ec 100644 --- a/crates/bitwarden/uniffi.toml +++ b/crates/bitwarden/uniffi.toml @@ -1,6 +1,8 @@ [bindings.kotlin] package_name = "com.bitwarden.core" +generate_immutable_records = true [bindings.swift] ffi_module_name = "BitwardenCoreFFI" module_name = "BitwardenCore" +generate_immutable_records = true diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index 980434e89..825f923e3 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.25.0", features = ["cli"] } +uniffi = { version = "=0.25.1", features = ["cli"] } From bebf731307d4a93ef4dba8c80373b3de22be60ca Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 21 Nov 2023 14:03:25 +0100 Subject: [PATCH 042/378] AES tests (#340) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daniel García --- crates/bitwarden/src/crypto/aes_ops.rs | 100 +++++++++++++++++++--- crates/bitwarden/src/crypto/enc_string.rs | 12 ++- crates/bitwarden/src/crypto/master_key.rs | 11 ++- crates/bitwarden/src/crypto/rsa.rs | 4 +- 4 files changed, 110 insertions(+), 17 deletions(-) diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 132718349..3deedabd8 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -13,10 +13,9 @@ use aes::cipher::{ BlockEncryptMut, KeyIvInit, }; use hmac::Mac; -use rand::RngCore; use crate::{ - crypto::{EncString, PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, + crypto::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, error::{CryptoError, Result}, }; @@ -63,10 +62,11 @@ pub fn decrypt_aes256_hmac( /// /// A AesCbc256_B64 EncString #[allow(unused)] -pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> Result { - let (iv, data) = encrypt_aes256_internal(data_dec, key); +pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { + let rng = rand::thread_rng(); + let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); - Ok(EncString::AesCbc256_B64 { iv, data }) + (iv, data) } /// Encrypt using AES-256 in CBC mode with MAC. @@ -80,11 +80,12 @@ pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, key: GenericArray, -) -> Result { - let (iv, data) = encrypt_aes256_internal(data_dec, key); +) -> Result<([u8; 16], [u8; 32], Vec)> { + let rng = rand::thread_rng(); + let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); let mac = validate_mac(&mac_key, &iv, &data)?; - Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) + Ok((iv, mac, data)) } /// Encrypt using AES-256 in CBC mode. @@ -92,9 +93,13 @@ pub fn encrypt_aes256_hmac( /// Used internally by: /// - [encrypt_aes256] /// - [encrypt_aes256_hmac] -fn encrypt_aes256_internal(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { +fn encrypt_aes256_internal( + mut rng: impl rand::RngCore, + data_dec: &[u8], + key: GenericArray, +) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; - rand::thread_rng().fill_bytes(&mut iv); + rng.fill_bytes(&mut iv); let data = cbc::Encryptor::::new(&key, &iv.into()) .encrypt_padded_vec_mut::(data_dec); @@ -112,3 +117,78 @@ fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { Ok(mac) } + +#[cfg(test)] +mod tests { + use aes::cipher::generic_array::sequence::GenericSequence; + use base64::Engine; + use rand::SeedableRng; + + use crate::util::BASE64_ENGINE; + + use super::*; + + /// Helper function for generating a `GenericArray` of size 32 with each element being + /// a multiple of a given increment, starting from a given offset. + fn generate_generic_array(offset: u8, increment: u8) -> GenericArray { + GenericArray::generate(|i| offset + i as u8 * increment) + } + + /// Helper function for generating a vector of a given size with each element being + /// a multiple of a given increment, starting from a given offset. + fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec { + (0..length).map(|i| offset + i as u8 * increment).collect() + } + + #[test] + fn test_encrypt_aes256_internal() { + let key = generate_generic_array(0, 1); + + let rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + let result = encrypt_aes256_internal(rng, "EncryptMe!".as_bytes(), key); + assert_eq!( + result, + ( + [62, 0, 239, 47, 137, 95, 64, 214, 127, 91, 184, 232, 31, 9, 165, 161], + vec![214, 76, 187, 97, 58, 146, 212, 140, 95, 164, 177, 204, 179, 133, 172, 148] + ) + ); + } + + #[test] + fn test_validate_mac() { + let mac_key = generate_vec(16, 0, 16); + + let iv = generate_vec(16, 0, 16); + let data = generate_vec(16, 0, 16); + + let result = validate_mac(&mac_key, &iv, &data); + + assert!(result.is_ok()); + let mac = result.unwrap(); + assert_eq!(mac.len(), 32); + } + + #[test] + fn test_decrypt_aes256() { + let iv = generate_vec(16, 0, 1); + let iv: &[u8; 16] = iv.as_slice().try_into().unwrap(); + let key = generate_generic_array(0, 1); + let data = BASE64_ENGINE.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); + + let decrypted = decrypt_aes256(iv, data, key).unwrap(); + + assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); + } + + #[test] + fn test_encrypt_decrypt_aes256() { + let key = generate_generic_array(0, 1); + let data = "EncryptMe!"; + + let (iv, encrypted) = encrypt_aes256(data.as_bytes(), key); + let decrypted = decrypt_aes256(&iv, encrypted, key).unwrap(); + + assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); + } +} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index ac7f3fc6b..09f877c50 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -1,5 +1,6 @@ use std::{fmt::Display, str::FromStr}; +use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; use serde::{de::Visitor, Deserialize}; @@ -331,6 +332,15 @@ impl serde::Serialize for EncString { } impl EncString { + pub(crate) fn encrypt_aes256_hmac( + data_dec: &[u8], + mac_key: GenericArray, + key: GenericArray, + ) -> Result { + let (iv, mac, data) = super::encrypt_aes256_hmac(data_dec, mac_key, key)?; + Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) + } + /// The numerical representation of the encryption type of the [EncString]. const fn enc_type(&self) -> u8 { match self { @@ -357,7 +367,7 @@ fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError impl LocateKey for EncString {} impl KeyEncryptable for &[u8] { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { - super::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + EncString::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) } } diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index b2c8e6e5f..fdcf93dde 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -4,8 +4,8 @@ use rand::Rng; use sha2::Digest; use super::{ - encrypt_aes256_hmac, hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, - SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, + hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, + PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -61,8 +61,11 @@ fn make_user_key( rng.fill(&mut user_key); let stretched_key = stretch_master_key(master_key)?; - let protected = - encrypt_aes256_hmac(&user_key, stretched_key.mac_key.unwrap(), stretched_key.key)?; + let protected = EncString::encrypt_aes256_hmac( + &user_key, + stretched_key.mac_key.unwrap(), + stretched_key.key, + )?; let u: &[u8] = &user_key; Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden/src/crypto/rsa.rs index 0d2d135b9..f105dbfe2 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden/src/crypto/rsa.rs @@ -5,7 +5,7 @@ use rsa::{ }; use crate::{ - crypto::{encrypt_aes256_hmac, EncString, SymmetricCryptoKey}, + crypto::{EncString, SymmetricCryptoKey}, error::{Error, Result}, util::BASE64_ENGINE, }; @@ -33,7 +33,7 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_pkcs8_der() .map_err(|_| Error::Internal("unable to create private key"))?; - let protected = encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; + let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; Ok(RsaKeyPair { public: b64, From 24f0dfdbb09dbc5ff0ca879b89948d7be7d7ae1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 23 Nov 2023 12:49:46 +0100 Subject: [PATCH 043/378] [PM-4695] Implement unlock with user key and update examples to use biometrics (#330) ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Enable the SDK to export the decrypted user key and expose a way to initialize the SDK with it. The Android and iOS examples have been revamped to allow choosing how to unlock the client. Some small notes: - The iOS example is directly storing the user key in a biometric protected keychain, while that doesn't seem possible in Android. Instead, we generate a key in the secure keystore and use it to encrypt/decrypt the user key. - The iOS example biometrics don't seem to work on the simulator and require a real device for testing. This depends on the refactor done on #329 --- crates/bitwarden-uniffi/src/crypto.rs | 13 + crates/bitwarden/src/client/client.rs | 17 + .../src/client/encryption_settings.rs | 38 +- crates/bitwarden/src/mobile/client_crypto.rs | 8 +- crates/bitwarden/src/mobile/crypto.rs | 24 +- languages/kotlin/app/build.gradle | 1 + .../com/bitwarden/myapplication/Biometrics.kt | 132 ++++++ .../bitwarden/myapplication/MainActivity.kt | 369 +++++++++++----- languages/kotlin/doc.md | 32 ++ .../swift/iOS/App.xcodeproj/project.pbxproj | 12 +- languages/swift/iOS/App/Biometrics.swift | 92 ++++ languages/swift/iOS/App/ContentView.swift | 405 +++++++++++------- 12 files changed, 848 insertions(+), 295 deletions(-) create mode 100644 languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt create mode 100644 languages/swift/iOS/App/Biometrics.swift diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 1792a5bbc..804202e2f 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -32,4 +32,17 @@ impl ClientCrypto { .initialize_org_crypto(req) .await?) } + + /// Get the uses's decrypted encryption key. Note: It's very important + /// to keep this key safe, as it can be used to decrypt all of the user's data + pub async fn get_user_encryption_key(&self) -> Result { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .get_user_encryption_key() + .await?) + } } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 213a12fb2..960ca9bda 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -222,6 +222,23 @@ impl Client { Ok(self.encryption_settings.as_ref().unwrap()) } + #[cfg(feature = "mobile")] + pub(crate) fn initialize_user_crypto_decrypted_key( + &mut self, + decrypted_user_key: &str, + private_key: EncString, + ) -> Result<&EncryptionSettings> { + let user_key = decrypted_user_key.parse::()?; + self.encryption_settings = Some(EncryptionSettings::new_decrypted_key( + user_key, + private_key, + )?); + Ok(self + .encryption_settings + .as_ref() + .expect("It was initialized on the previous line")) + } + pub(crate) fn initialize_crypto_single_key( &mut self, key: SymmetricCryptoKey, diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 6533c7d2e..7c16725e7 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -27,6 +27,7 @@ impl std::fmt::Debug for EncryptionSettings { } impl EncryptionSettings { + /// Initialize the encryption settings with the user password and their encrypted keys #[cfg(feature = "internal")] pub(crate) fn new( login_method: &UserLoginMethod, @@ -45,24 +46,33 @@ impl EncryptionSettings { // Decrypt the user key let user_key = master_key.decrypt_user_key(user_key)?; - // Decrypt the private key with the user key - let private_key = { - let dec: Vec = private_key.decrypt_with_key(&user_key)?; - Some( - rsa::RsaPrivateKey::from_pkcs8_der(&dec) - .map_err(|_| CryptoError::InvalidKey)?, - ) - }; - - Ok(EncryptionSettings { - user_key, - private_key, - org_keys: HashMap::new(), - }) + Self::new_decrypted_key(user_key, private_key) } } } + /// Initialize the encryption settings with the decrypted user key and the encrypted user private key + /// This should only be used when unlocking the vault via biometrics or when the vault is set to lock: "never" + /// Otherwise handling the decrypted user key is dangerous and discouraged + #[cfg(feature = "internal")] + pub(crate) fn new_decrypted_key( + user_key: SymmetricCryptoKey, + private_key: EncString, + ) -> Result { + let private_key = { + let dec: Vec = private_key.decrypt_with_key(&user_key)?; + Some(rsa::RsaPrivateKey::from_pkcs8_der(&dec).map_err(|_| CryptoError::InvalidKey)?) + }; + + Ok(EncryptionSettings { + user_key, + private_key, + org_keys: HashMap::new(), + }) + } + + /// Initialize the encryption settings with only a single decrypted key. + /// This is used only for logging in Secrets Manager with an access token pub(crate) fn new_single_key(key: SymmetricCryptoKey) -> Self { EncryptionSettings { user_key: key, diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index c0edb1982..118e02726 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -3,7 +3,8 @@ use crate::Client; use crate::{ error::Result, mobile::crypto::{ - initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoRequest, + get_user_encryption_key, initialize_org_crypto, initialize_user_crypto, + InitOrgCryptoRequest, InitUserCryptoRequest, }, }; @@ -21,6 +22,11 @@ impl<'a> ClientCrypto<'a> { pub async fn initialize_org_crypto(&mut self, req: InitOrgCryptoRequest) -> Result<()> { initialize_org_crypto(self.client, req).await } + + #[cfg(feature = "internal")] + pub async fn get_user_encryption_key(&mut self) -> Result { + get_user_encryption_key(self.client).await + } } impl<'a> Client { diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 2cf850279..9c2c8478f 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -3,7 +3,12 @@ use std::collections::HashMap; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{client::kdf::Kdf, crypto::EncString, error::Result, Client}; +use crate::{ + client::kdf::Kdf, + crypto::EncString, + error::{Error, Result}, + Client, +}; #[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -31,6 +36,10 @@ pub enum InitUserCryptoMethod { /// The user's encrypted symmetric crypto key user_key: String, }, + DecryptedKey { + /// The user's decrypted encryption key, obtained using `get_user_encryption_key` + decrypted_user_key: String, + }, } #[cfg(feature = "internal")] @@ -49,6 +58,9 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ let user_key: EncString = user_key.parse()?; client.initialize_user_crypto(&password, user_key, private_key)?; } + InitUserCryptoMethod::DecryptedKey { decrypted_user_key } => { + client.initialize_user_crypto_decrypted_key(&decrypted_user_key, private_key)?; + } } Ok(()) @@ -69,3 +81,13 @@ pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoReques client.initialize_org_crypto(organization_keys)?; Ok(()) } + +#[cfg(feature = "internal")] +pub async fn get_user_encryption_key(client: &mut Client) -> Result { + let user_key = client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + + Ok(user_key.to_base64()) +} diff --git a/languages/kotlin/app/build.gradle b/languages/kotlin/app/build.gradle index 709e32889..ef42d43bb 100644 --- a/languages/kotlin/app/build.gradle +++ b/languages/kotlin/app/build.gradle @@ -60,6 +60,7 @@ dependencies { implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' + implementation "androidx.biometric:biometric:1.1.0" implementation "io.ktor:ktor-client-core:2.3.3" implementation "io.ktor:ktor-client-cio:2.3.3" implementation "io.ktor:ktor-client-content-negotiation:2.3.3" diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt new file mode 100644 index 000000000..8f8115e8d --- /dev/null +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/Biometrics.kt @@ -0,0 +1,132 @@ +package com.bitwarden.myapplication + +import android.os.Build +import android.security.keystore.KeyGenParameterSpec +import android.security.keystore.KeyProperties +import android.util.Log +import androidx.biometric.BiometricManager +import androidx.biometric.BiometricManager.Authenticators +import androidx.biometric.BiometricPrompt +import androidx.biometric.BiometricPrompt.CryptoObject +import androidx.core.content.ContextCompat +import androidx.fragment.app.FragmentActivity +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import java.security.KeyStore +import java.util.Base64 +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.SecretKey +import javax.crypto.spec.GCMParameterSpec + +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the biometric unlock functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +class Biometric(private var activity: FragmentActivity) { + private var promptInfo: BiometricPrompt.PromptInfo = + BiometricPrompt.PromptInfo.Builder().setTitle("Unlock") + .setSubtitle("Bitwarden biometric unlock") + .setDescription("Confirm biometric to continue").setConfirmationRequired(true) + .setNegativeButtonText("Use account password").build() + + suspend fun encryptString( + keyName: String, plaintext: String, callback: (String, String) -> Unit + ) { + if (canAuthenticate()) { + val cipher = getCipher() + cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(keyName)) + + val bio = createBiometricPrompt { + val ciphertext = it.cipher!!.doFinal(plaintext.toByteArray()) + callback( + String(Base64.getEncoder().encode(ciphertext)), + String(Base64.getEncoder().encode(cipher.iv)) + ) + } + CoroutineScope(Dispatchers.Main).async { + bio.authenticate(promptInfo, CryptoObject(cipher)) + }.await() + } + } + + suspend fun decryptString( + keyName: String, encrypted: String, initializationVector: String, callback: (String) -> Unit + ) { + if (canAuthenticate()) { + val enc = Base64.getDecoder().decode(encrypted) + val iv = Base64.getDecoder().decode(initializationVector) + + val cipher = getCipher() + cipher.init(Cipher.DECRYPT_MODE, getSecretKey(keyName), GCMParameterSpec(128, iv)) + + val bio = createBiometricPrompt { + callback(String(it.cipher!!.doFinal(enc))) + } + + CoroutineScope(Dispatchers.Main).async { + bio.authenticate(promptInfo, CryptoObject(cipher)) + }.await() + } + } + + private fun canAuthenticate() = BiometricManager.from(activity) + .canAuthenticate(Authenticators.BIOMETRIC_STRONG) == BiometricManager.BIOMETRIC_SUCCESS + + private fun createBiometricPrompt(processData: (CryptoObject) -> Unit): BiometricPrompt { + return BiometricPrompt(activity, + ContextCompat.getMainExecutor(activity), + object : BiometricPrompt.AuthenticationCallback() { + override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { + super.onAuthenticationError(errorCode, errString) + Log.e("Biometric", "$errorCode :: $errString") + } + + override fun onAuthenticationFailed() { + super.onAuthenticationFailed() + Log.e("Biometric", "Authentication failed for an unknown reason") + } + + override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) { + super.onAuthenticationSucceeded(result) + processData(result.cryptoObject!!) + } + }) + } + + private fun getCipher(): Cipher { + val transform = + "${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_GCM}/${KeyProperties.ENCRYPTION_PADDING_NONE}" + return Cipher.getInstance(transform) + } + + private fun getSecretKey(keyName: String): SecretKey { + // If the SecretKey exists, return it + val keyStore = KeyStore.getInstance("AndroidKeyStore") + keyStore.load(null) + keyStore.getKey(keyName, null)?.let { return it as SecretKey } + + // Otherwise, we generate a new one + val keyGenParams = KeyGenParameterSpec.Builder( + keyName, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT + ).apply { + setBlockModes(KeyProperties.BLOCK_MODE_GCM) + setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + setKeySize(256) + setUserAuthenticationRequired(true) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) + } + }.build() + + val keyGenerator = + KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") + keyGenerator.init(keyGenParams) + return keyGenerator.generateKey() + } +} diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 13dec7d0e..3c03c6bca 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -1,15 +1,27 @@ package com.bitwarden.myapplication +import android.content.Context import android.os.Bundle -import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Checkbox +import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.fragment.app.FragmentActivity import com.bitwarden.core.DateTime import com.bitwarden.core.Folder import com.bitwarden.core.InitOrgCryptoRequest @@ -44,151 +56,272 @@ import java.security.cert.X509Certificate import java.util.Base64 import javax.net.ssl.X509TrustManager -class MainActivity : ComponentActivity() { +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +const val SERVER_URL = "https://10.0.2.2:8080/" +const val API_URL = SERVER_URL + "api/" +const val IDENTITY_URL = SERVER_URL + "identity/" + +const val EMAIL = "test@bitwarden.com" +const val PASSWORD = "asdfasdfasdf" + +// We should separate keys for each user by appending the user_id +const val BIOMETRIC_KEY = "biometric_key" + +class MainActivity : FragmentActivity() { + private lateinit var biometric: Biometric + private lateinit var client: Client + private lateinit var http: HttpClient + + private var accessToken = "" + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + biometric = Biometric(this) + client = Client(null) + http = httpClient() + + setContent { + MyApplicationTheme { + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally + ) { - val SERVER_URL = "https://10.0.2.2:8080/" - val API_URL = SERVER_URL + "api/" - val IDENTITY_URL = SERVER_URL + "identity/" + val setupBiometrics = remember { mutableStateOf(true) } + val outputText = remember { mutableStateOf("") } - val EMAIL = "test@bitwarden.com" - val PASSWORD = "asdfasdfasdf" + Row { + Checkbox(checked = setupBiometrics.value, + onCheckedChange = { isChecked -> + setupBiometrics.value = isChecked + }) + Text( + "Setup biometric unlock after login", + modifier = Modifier.align(CenterVertically) + ) + } - GlobalScope.launch { - var client = Client(null) - val http = httpClient() + Button({ + GlobalScope.launch { + clientExamplePassword( + client, http, outputText, setupBiometrics.value + ) + } + }) { + Text("Login with username + password") + } - ///////////////////////////// Get master password hash ///////////////////////////// - @Serializable - data class PreloginRequest(val email: String) + Divider( + color = Color.Black, + thickness = 1.dp, + modifier = Modifier.padding(30.dp) + ) - @Serializable - data class PreloginResponse( - val kdf: UInt, - val kdfIterations: UInt, - val kdfMemory: UInt?, - val kdfParallelism: UInt? - ) + Button({ + GlobalScope.launch { + clientExampleBiometrics(client, http, outputText) + } + }) { + Text("Unlock with biometrics") + } - val prelogin_body = http.post(IDENTITY_URL + "accounts/prelogin") { - contentType(ContentType.Application.Json) - setBody(PreloginRequest(EMAIL)) - }.body() - val kdf = if (prelogin_body.kdf == 0u) { - Kdf.Pbkdf2(prelogin_body.kdfIterations) - } else { - Kdf.Argon2id( - prelogin_body.kdfIterations, - prelogin_body.kdfMemory!!, - prelogin_body.kdfParallelism!! - ) + Button({ + GlobalScope.launch { + client.destroy() + client = Client(null) + outputText.value = "OK" + } + }) { + Text("Lock & reset client") + } + + Text( + "Output: " + outputText.value, + modifier = Modifier.padding(vertical = 10.dp) + ) + } + } } - val masterPasswordHash = client.auth().hashPassword(EMAIL, PASSWORD, kdf) + } + } + + private suspend fun clientExamplePassword( + client: Client, http: HttpClient, outputText: MutableState, setupBiometrics: Boolean + ) { + println("### Logging in with username and password ###") + ///////////////////////////// Get master password hash ///////////////////////////// + @Serializable + data class PreloginRequest(val email: String) - ///////////////////////////// Login ///////////////////////////// + @Serializable + data class PreloginResponse( + val kdf: UInt, val kdfIterations: UInt, val kdfMemory: UInt?, val kdfParallelism: UInt? + ) - @Serializable - data class LoginResponse( - val Key: String, - val PrivateKey: String, - val access_token: String, - val refresh_token: String, + val prelogin_body = http.post(IDENTITY_URL + "accounts/prelogin") { + contentType(ContentType.Application.Json) + setBody(PreloginRequest(EMAIL)) + }.body() + val kdf = if (prelogin_body.kdf == 0u) { + Kdf.Pbkdf2(prelogin_body.kdfIterations) + } else { + Kdf.Argon2id( + prelogin_body.kdfIterations, + prelogin_body.kdfMemory!!, + prelogin_body.kdfParallelism!! ) + } + val masterPasswordHash = client.auth().hashPassword(EMAIL, PASSWORD, kdf) - val loginBody = http.post(IDENTITY_URL + "connect/token") { - contentType(ContentType.Application.Json) - header("Auth-Email", Base64.getEncoder().encodeToString(EMAIL.toByteArray())) - setBody(FormDataContent(Parameters.build { - append("scope", "api offline_access") - append("client_id", "web") - append("deviceType", "12") - append("deviceIdentifier", "0745d426-8dab-484a-9816-4959721d77c7") - append("deviceName", "edge") - - append("grant_type", "password") - append("username", EMAIL) - append("password", masterPasswordHash) - })) - }.body() - - ///////////////////////////// Sync ///////////////////////////// - - val syncBody = http.get(API_URL + "sync?excludeDomains=true") { - bearerAuth(loginBody.access_token) - }.body() - - val folders = (syncBody["folders"] as JsonArray).map { - val o = it as JsonObject - Folder( - (o["id"] as JsonPrimitive).content, - (o["name"] as JsonPrimitive).content, - DateTime.parse( - (o["revisionDate"] as JsonPrimitive).content - ) - ) - } + ///////////////////////////// Login ///////////////////////////// - ///////////////////////////// Initialize crypto ///////////////////////////// - val orgs = ((syncBody["profile"] as JsonObject)["organizations"]) as JsonArray - val orgKeys = HashMap() + @Serializable + data class LoginResponse( + val Key: String, + val PrivateKey: String, + val access_token: String, + val refresh_token: String, + ) - for (org in orgs) { - val o = org as JsonObject - orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content - } + val loginBody = http.post(IDENTITY_URL + "connect/token") { + contentType(ContentType.Application.Json) + header("Auth-Email", Base64.getEncoder().encodeToString(EMAIL.toByteArray())) + setBody(FormDataContent(Parameters.build { + append("scope", "api offline_access") + append("client_id", "web") + append("deviceType", "12") + append("deviceIdentifier", "0745d426-8dab-484a-9816-4959721d77c7") + append("deviceName", "edge") - client.crypto().initializeUserCrypto( - InitUserCryptoRequest( - kdfParams = kdf, - email = EMAIL, - privateKey = loginBody.PrivateKey, - method = InitUserCryptoMethod.Password( - password = PASSWORD, - userKey = loginBody.Key - ) - ) - ) + append("grant_type", "password") + append("username", EMAIL) + append("password", masterPasswordHash) + })) + }.body() - client.crypto().initializeOrgCrypto( - InitOrgCryptoRequest( - organizationKeys = orgKeys + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( + kdfParams = kdf, + email = EMAIL, + privateKey = loginBody.PrivateKey, + method = InitUserCryptoMethod.Password( + password = PASSWORD, userKey = loginBody.Key ) ) + ) - ///////////////////////////// Decrypt some folders ///////////////////////////// + accessToken = loginBody.access_token - val decryptedFolders = client.vault().folders().decryptList(folders) + decryptVault(client, http, outputText) - println(decryptedFolders) + if (setupBiometrics) { + // Save values for future logins + val sharedPref = getPreferences(Context.MODE_PRIVATE) + with(sharedPref.edit()) { + putString("accessToken", accessToken) + putString("privateKey", loginBody.PrivateKey) - } + putInt("kdfType", prelogin_body.kdf.toInt()) + putInt("kdfIterations", prelogin_body.kdfIterations.toInt()) + putInt("kdfMemory", (prelogin_body.kdfMemory ?: 0u).toInt()) + putInt("kdfParallelism", (prelogin_body.kdfParallelism ?: 0u).toInt()) - setContent { - MyApplicationTheme { - // A surface container using the 'background' color from the theme - Surface( - modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background - ) { - Greeting("Hey") + // TODO: This should be protected by Android's secure KeyStore + val decryptedKey = client.crypto().getUserEncryptionKey() + + biometric.encryptString(BIOMETRIC_KEY, decryptedKey) { key, iv -> + putString("encryptedUserKey", key) + putString("encryptedUserKeyIv", iv) + apply() } } } } -} -@Composable -fun Greeting(name: String, modifier: Modifier = Modifier) { - Text( - text = "Hello $name!", modifier = modifier - ) -} + private suspend fun clientExampleBiometrics( + client: Client, http: HttpClient, outputText: MutableState + ) { + println("### Unlocking with Biometrics ###") + + val pref = getPreferences(Context.MODE_PRIVATE) + accessToken = pref.getString("accessToken", "").orEmpty() + val privateKey = pref.getString("privateKey", "") + + val kdf = if (pref.getInt("kdfType", 0) == 0) { + Kdf.Pbkdf2(pref.getInt("kdfIterations", 0).toUInt()) + } else { + Kdf.Argon2id( + pref.getInt("kdfIterations", 0).toUInt(), + pref.getInt("kdfMemory", 0).toUInt(), + pref.getInt("kdfParallelism", 0).toUInt() + ) + } + + val encryptedUserKey = pref.getString("encryptedUserKey", "")!! + val encryptedUserKeyIv = pref.getString("encryptedUserKeyIv", "")!! + + biometric.decryptString( + BIOMETRIC_KEY, encryptedUserKey, encryptedUserKeyIv + ) { key -> + GlobalScope.launch { + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( + kdfParams = kdf, + email = EMAIL, + privateKey = privateKey!!, + method = InitUserCryptoMethod.DecryptedKey(decryptedUserKey = key) + ) + ) + + decryptVault(client, http, outputText) + } + } + } + + suspend fun decryptVault(client: Client, http: HttpClient, outputText: MutableState) { + ///////////////////////////// Sync ///////////////////////////// + + val syncBody = http.get(API_URL + "sync?excludeDomains=true") { + bearerAuth(accessToken) + }.body() + + val folders = (syncBody["folders"] as JsonArray).map { + val o = it as JsonObject + Folder( + (o["id"] as JsonPrimitive).content, + (o["name"] as JsonPrimitive).content, + DateTime.parse( + (o["revisionDate"] as JsonPrimitive).content + ) + ) + } + + ///////////////////////////// Initialize org crypto ///////////////////////////// + val orgs = ((syncBody["profile"] as JsonObject)["organizations"]) as JsonArray + val orgKeys = HashMap() + + for (org in orgs) { + val o = org as JsonObject + orgKeys[(o["id"] as JsonPrimitive).content] = (o["key"] as JsonPrimitive).content + } + + client.crypto().initializeOrgCrypto(InitOrgCryptoRequest(organizationKeys = orgKeys)) + + ///////////////////////////// Decrypt some folders ///////////////////////////// -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - MyApplicationTheme { - Greeting("Sdk") + val decryptedFolders = client.vault().folders().decryptList(folders) + outputText.value = decryptedFolders.toString() + println(decryptedFolders) } } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 70446bd8f..fd65c7b71 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -205,6 +205,17 @@ Initialization method for the organization crypto. Needs to be called after **Output**: std::result::Result<,BitwardenError> +### `get_user_encryption_key` + +Get the uses's decrypted encryption key. Note: It's very important to keep this key safe, +as it can be used to decrypt all of the user's data + +**Arguments**: + +- self: + +**Output**: std::result::Result + ## ClientExporters ### `export_vault` @@ -906,6 +917,27 @@ implementations. + + decryptedKey + object + + + + + + + + + + + + + + + +
KeyTypeDescription
decrypted_user_keystringThe user's decrypted encryption key, obtained using `get_user_encryption_key`
+ + ## `InitUserCryptoRequest` diff --git a/languages/swift/iOS/App.xcodeproj/project.pbxproj b/languages/swift/iOS/App.xcodeproj/project.pbxproj index 003c09c0d..e8b3519fd 100644 --- a/languages/swift/iOS/App.xcodeproj/project.pbxproj +++ b/languages/swift/iOS/App.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 33F2B0502B0511C700E1E91C /* Biometrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33F2B04F2B0511C700E1E91C /* Biometrics.swift */; }; 55B6153E2A8678B300BE93F4 /* testApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B6153D2A8678B300BE93F4 /* testApp.swift */; }; 55B615402A8678B300BE93F4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55B6153F2A8678B300BE93F4 /* ContentView.swift */; }; 55B615422A8678B400BE93F4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55B615412A8678B400BE93F4 /* Assets.xcassets */; }; @@ -15,6 +16,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 33F2B04F2B0511C700E1E91C /* Biometrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Biometrics.swift; sourceTree = ""; }; 55B6153A2A8678B300BE93F4 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55B6153D2A8678B300BE93F4 /* testApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = testApp.swift; sourceTree = ""; }; 55B6153F2A8678B300BE93F4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -60,6 +62,7 @@ 55B6153F2A8678B300BE93F4 /* ContentView.swift */, 55B615412A8678B400BE93F4 /* Assets.xcassets */, 55B615432A8678B400BE93F4 /* Preview Content */, + 33F2B04F2B0511C700E1E91C /* Biometrics.swift */, ); path = App; sourceTree = ""; @@ -118,7 +121,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1420; + LastUpgradeCheck = 1500; TargetAttributes = { 55B615392A8678B300BE93F4 = { CreatedOnToolsVersion = 14.2; @@ -160,6 +163,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 33F2B0502B0511C700E1E91C /* Biometrics.swift in Sources */, 55B615402A8678B300BE93F4 /* ContentView.swift in Sources */, 55B6153E2A8678B300BE93F4 /* testApp.swift in Sources */, ); @@ -172,6 +176,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -204,6 +209,7 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -232,6 +238,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -264,6 +271,7 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -293,6 +301,7 @@ DEVELOPMENT_TEAM = LTZ2PFU5D6; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSFaceIDUsageDescription = "Unlock vault with biometrics"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; @@ -323,6 +332,7 @@ DEVELOPMENT_TEAM = LTZ2PFU5D6; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSFaceIDUsageDescription = "Unlock vault with biometrics"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; diff --git a/languages/swift/iOS/App/Biometrics.swift b/languages/swift/iOS/App/Biometrics.swift new file mode 100644 index 000000000..2fc5ef2a3 --- /dev/null +++ b/languages/swift/iOS/App/Biometrics.swift @@ -0,0 +1,92 @@ +// +// Biometrics.swift +// App +// +// Created by Dani on 15/11/23. +// + +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the biometric unlock functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ + +import Foundation +import LocalAuthentication + +let SERVICE: String = "com.example.app" + +// We should separate keys for each user by appending the user_id +let KEY: String = "biometric_key" + + +func biometricStoreValue(value: String) { + var error: Unmanaged? + let accessControl = SecAccessControlCreateWithFlags( + nil, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + .biometryCurrentSet, + &error) + + guard accessControl != nil && error == nil else { + fatalError("SecAccessControlCreateWithFlags failed") + } + + let query = [ + kSecClass: kSecClassGenericPassword, + kSecAttrService: SERVICE, + kSecAttrAccount: KEY, + kSecValueData: value.data(using: .utf8)!, + kSecAttrAccessControl: accessControl as Any + ] as CFDictionary + + // Try to delete the previous secret, if it exists + // Otherwise we get `errSecDuplicateItem` + SecItemDelete(query) + + let status = SecItemAdd(query, nil) + guard status == errSecSuccess else { + fatalError("Unable to store the secret: " + errToString(status: status)) + } +} + +private func errToString(status: OSStatus) -> String { + if let err = SecCopyErrorMessageString(status, nil) as String? { + err + } else { + "Unknown error" + } +} + +func biometricRetrieveValue() -> String? { + let searchQuery = [ + kSecClass: kSecClassGenericPassword, + kSecAttrService: SERVICE, + kSecAttrAccount: KEY, + kSecMatchLimit: kSecMatchLimitOne, + kSecReturnData: true, + kSecReturnAttributes: true, + ] as CFDictionary + + var item: AnyObject? + let status = SecItemCopyMatching(searchQuery, &item) + + // If the item is not found, we just return nil + if status == errSecItemNotFound { + return nil + } + + // TODO: We probably want to handle these errors better + guard status == noErr else { + fatalError("Unable to retrieve the secret: " + errToString(status: status)) + } + + if let resultDictionary = item as? [String: Any], + let data = resultDictionary[kSecValueData as String] as? Data { + return String(decoding: data, as: UTF8.self) + } + + return nil +} diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index 484caf14f..5df7dc3fd 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -8,176 +8,261 @@ import BitwardenSdk import SwiftUI -struct ContentView: View { - - @State private var msg: String - - init() { - let client = Client(settings: nil) +/** + * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. + */ - _msg = State(initialValue: client.echo(msg: "Sdk")) +let SERVER_URL = "https://localhost:8080/" +let API_URL = SERVER_URL + "api/" +let IDENTITY_URL = SERVER_URL + "identity/" - let SERVER_URL = "https://localhost:8080/" - let API_URL = SERVER_URL + "api/" - let IDENTITY_URL = SERVER_URL + "identity/" - - let EMAIL = "test@bitwarden.com" - let PASSWORD = "asdfasdfasdf" +let EMAIL = "test@bitwarden.com" +let PASSWORD = "asdfasdfasdf" +struct ContentView: View { + private var http: URLSession + + @State private var client: Client + + @State private var accessToken: String = "" + + init() { // Disable SSL Cert validation. Don't do this in production - let ignoreHttpsDelegate = IgnoreHttpsDelegate() - let http = URLSession( - configuration: URLSessionConfiguration.default, delegate: ignoreHttpsDelegate, + http = URLSession( + configuration: URLSessionConfiguration.default, delegate: IgnoreHttpsDelegate(), delegateQueue: nil) - - Task { - - ////////////////////////////// Get master password hash ////////////////////////////// - - struct PreloginRequest: Codable { let email: String } - struct PreloginResponse: Codable { - let kdf: UInt32 - let kdfIterations: UInt32 - let kdfMemory: UInt32? - let kdfParallelism: UInt32? - - } - - let (preloginDataJson, _) = try await http.data( - for: request( - method: "POST", url: IDENTITY_URL + "accounts/prelogin", - fn: { r in - r.setValue("application/json", forHTTPHeaderField: "Content-Type") - r.httpBody = try JSONEncoder().encode(PreloginRequest(email: EMAIL)) - })) - let preloginData = try JSONDecoder().decode( - PreloginResponse.self, from: preloginDataJson) - - let kdf: Kdf - if preloginData.kdf == 0 { - kdf = Kdf.pbkdf2(iterations: preloginData.kdfIterations) - } else { - kdf = Kdf.argon2id( - iterations: preloginData.kdfIterations, memory: preloginData.kdfMemory!, - parallelism: preloginData.kdfParallelism!) - } - - let passwordHash = try await client.auth().hashPassword( - email: EMAIL, password: PASSWORD, kdfParams: kdf) - - ///////////////////////////// Login ///////////////////////////// - - struct LoginResponse: Codable { - let Key: String - let PrivateKey: String - let access_token: String - let refresh_token: String - } - - let (loginDataJson, _) = try await http.data( - for: request( - method: "POST", url: IDENTITY_URL + "connect/token", - fn: { r in - r.setValue( - EMAIL.data(using: .utf8)?.base64EncodedString(), - forHTTPHeaderField: "Auth-Email") - r.setValue( - "application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") - - var comp = URLComponents() - comp.queryItems = [ - URLQueryItem(name: "scope", value: "api offline_access"), - URLQueryItem(name: "client_id", value: "web"), - URLQueryItem(name: "deviceType", value: "12"), - URLQueryItem( - name: "deviceIdentifier", - value: "0745d426-8dab-484a-9816-4959721d77c7"), - URLQueryItem(name: "deviceName", value: "edge"), - URLQueryItem(name: "grant_type", value: "password"), - URLQueryItem(name: "username", value: EMAIL), - URLQueryItem(name: "password", value: passwordHash), - ] - r.httpBody = comp.percentEncodedQuery! - .replacingOccurrences(of: "@", with: "%40") - .replacingOccurrences(of: "+", with: "%2B") - .data(using: .utf8) - })) - let loginData = try JSONDecoder().decode(LoginResponse.self, from: loginDataJson) - - ///////////////////////////// Sync ///////////////////////////// - - struct SyncOrganization: Codable { - let id: String - let key: String - } - struct SyncProfile: Codable { - let organizations: [SyncOrganization] - - } - struct SyncFolder: Codable { - let id: String - let name: String - let revisionDate: String - } - struct SyncResponse: Codable { - let profile: SyncProfile - let folders: [SyncFolder] - } - - let (syncDataJson, _) = try await http.data( - for: request( - method: "GET", url: API_URL + "sync?excludeDomains=true", - fn: { r in - r.setValue( - "Bearer " + loginData.access_token, forHTTPHeaderField: "Authorization") - })) - - let syncData = try JSONDecoder().decode(SyncResponse.self, from: syncDataJson) - - ///////////////////////////// Initialize crypto ///////////////////////////// - - try await client.crypto().initializeUserCrypto( - req: InitUserCryptoRequest( - kdfParams: kdf, - email: EMAIL, - privateKey: loginData.PrivateKey, - method: InitUserCryptoMethod.password( - password: PASSWORD, - userKey: loginData.Key - ) - )) - - try await client.crypto().initializeOrgCrypto( - req: InitOrgCryptoRequest( - organizationKeys: Dictionary.init( - uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } - ) - )) - - ///////////////////////////// Decrypt some folders ///////////////////////////// - - let dateFormatter = ISO8601DateFormatter() - dateFormatter.formatOptions = [.withFractionalSeconds] - - let decryptedFolders = try await client.vault().folders().decryptList( - folders: syncData.folders.map { - Folder( - id: $0.id, name: $0.name, - revisionDate: dateFormatter.date(from: $0.revisionDate)!) - }) - print(decryptedFolders) - } + + client = Client(settings: nil) } - + + @State var setupBiometrics: Bool = true + @State var outputText: String = "" + var body: some View { VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello " + msg) + Toggle("Setup biometric unlock after login", isOn: $setupBiometrics).padding(.init(top: 0, leading: 20, bottom: 0, trailing: 20)) + + Button(action: { + Task { + do { + try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + } catch { + print("ERROR:", error) + } + } + }, label: { + Text("Login with username + password") + }) + + Divider().padding(30) + + Button(action: { + Task { + do { + try await clientExampleBiometrics(clientCrypto: client.crypto()) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + } catch { + print("ERROR:", error) + } + } + }, label: { + Text("Unlock with biometrics") + }) + + Button(action: { + client = Client(settings: nil) + }, label: { + Text("Lock & reset client") + }).padding() + + Text("Output: " + outputText).padding(.top) } .padding() } + + func clientExamplePassword(clientAuth: ClientAuthProtocol, clientCrypto: ClientCryptoProtocol, setupBiometrics: Bool) async throws { + ////////////////////////////// Get master password hash ////////////////////////////// + + struct PreloginRequest: Codable { let email: String } + struct PreloginResponse: Codable { + let kdf: UInt32 + let kdfIterations: UInt32 + let kdfMemory: UInt32? + let kdfParallelism: UInt32? + + } + + let (preloginDataJson, _) = try await http.data( + for: request( + method: "POST", url: IDENTITY_URL + "accounts/prelogin", + fn: { r in + r.setValue("application/json", forHTTPHeaderField: "Content-Type") + r.httpBody = try JSONEncoder().encode(PreloginRequest(email: EMAIL)) + })) + let preloginData = try JSONDecoder().decode( + PreloginResponse.self, from: preloginDataJson) + + let kdf: Kdf + if preloginData.kdf == 0 { + kdf = Kdf.pbkdf2(iterations: preloginData.kdfIterations) + } else { + kdf = Kdf.argon2id( + iterations: preloginData.kdfIterations, memory: preloginData.kdfMemory!, + parallelism: preloginData.kdfParallelism!) + } + + let passwordHash = try await clientAuth.hashPassword( + email: EMAIL, password: PASSWORD, kdfParams: kdf) + + ///////////////////////////// Login ///////////////////////////// + + struct LoginResponse: Codable { + let Key: String + let PrivateKey: String + let access_token: String + let refresh_token: String + } + + let (loginDataJson, _) = try await http.data( + for: request( + method: "POST", url: IDENTITY_URL + "connect/token", + fn: { r in + r.setValue( + EMAIL.data(using: .utf8)?.base64EncodedString(), + forHTTPHeaderField: "Auth-Email") + r.setValue( + "application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") + + var comp = URLComponents() + comp.queryItems = [ + URLQueryItem(name: "scope", value: "api offline_access"), + URLQueryItem(name: "client_id", value: "web"), + URLQueryItem(name: "deviceType", value: "12"), + URLQueryItem( + name: "deviceIdentifier", + value: "0745d426-8dab-484a-9816-4959721d77c7"), + URLQueryItem(name: "deviceName", value: "edge"), + URLQueryItem(name: "grant_type", value: "password"), + URLQueryItem(name: "username", value: EMAIL), + URLQueryItem(name: "password", value: passwordHash), + ] + r.httpBody = comp.percentEncodedQuery! + .replacingOccurrences(of: "@", with: "%40") + .replacingOccurrences(of: "+", with: "%2B") + .data(using: .utf8) + })) + let loginData = try JSONDecoder().decode(LoginResponse.self, from: loginDataJson) + + try await clientCrypto.initializeUserCrypto( + req: InitUserCryptoRequest( + kdfParams: kdf, + email: EMAIL, + privateKey: loginData.PrivateKey, + method: InitUserCryptoMethod.password( + password: PASSWORD, + userKey: loginData.Key + ) + )) + + accessToken = loginData.access_token + + if (setupBiometrics) { + let defaults = UserDefaults.standard + defaults.set(loginData.PrivateKey, forKey: "privateKey") + defaults.set(preloginData.kdf, forKey: "kdfType") + defaults.set(preloginData.kdfIterations, forKey: "kdfIterations") + defaults.set(preloginData.kdfMemory, forKey: "kdfMemory") + defaults.set(preloginData.kdfParallelism, forKey: "kdfParallelism") + defaults.synchronize() + + let key = try await clientCrypto.getUserEncryptionKey() + biometricStoreValue(value: key) + } + } + + func clientExampleBiometrics(clientCrypto: ClientCryptoProtocol) async throws { + let defaults = UserDefaults.standard + let privateKey = defaults.string(forKey: "privateKey")! + let kdf = if defaults.integer(forKey: "kdfType") == 0 { + Kdf.pbkdf2(iterations: UInt32(defaults.integer(forKey: "kdfIterations"))) + } else { + Kdf.argon2id( + iterations: UInt32(defaults.integer(forKey: "kdfIterations")), + memory: UInt32(defaults.integer(forKey: "kdfMemory")), + parallelism: UInt32(defaults.integer(forKey: "kdfParallelism")) + ) + } + + let key = biometricRetrieveValue()! + + try await clientCrypto.initializeUserCrypto(req: InitUserCryptoRequest( + kdfParams: kdf, + email: EMAIL, + privateKey: privateKey, + method: InitUserCryptoMethod.decryptedKey( + decryptedUserKey: key + ) + )) + } + + func decryptVault(clientCrypto: ClientCryptoProtocol, clientVault: ClientVaultProtocol) async throws { + ///////////////////////////// Sync ///////////////////////////// + + struct SyncOrganization: Codable { + let id: String + let key: String + } + struct SyncProfile: Codable { + let organizations: [SyncOrganization] + + } + struct SyncFolder: Codable { + let id: String + let name: String + let revisionDate: String + } + struct SyncResponse: Codable { + let profile: SyncProfile + let folders: [SyncFolder] + } + + let (syncDataJson, _) = try await http.data( + for: request( + method: "GET", url: API_URL + "sync?excludeDomains=true", + fn: { r in + r.setValue( + "Bearer " + accessToken, forHTTPHeaderField: "Authorization") + })) + + let syncData = try JSONDecoder().decode(SyncResponse.self, from: syncDataJson) + + ///////////////////////////// Initialize org crypto ///////////////////////////// + + try await clientCrypto.initializeOrgCrypto( + req: InitOrgCryptoRequest( + organizationKeys: Dictionary.init( + uniqueKeysWithValues: syncData.profile.organizations.map { ($0.id, $0.key) } + ) + )) + + ///////////////////////////// Decrypt some folders ///////////////////////////// + + let dateFormatter = ISO8601DateFormatter() + dateFormatter.formatOptions = [.withFractionalSeconds] + + let decryptedFolders = try await clientVault.folders().decryptList( + folders: syncData.folders.map { + Folder( + id: $0.id, name: $0.name, + revisionDate: dateFormatter.date(from: $0.revisionDate)!) + }) + print(decryptedFolders) + } } struct ContentView_Previews: PreviewProvider { @@ -202,7 +287,7 @@ extension IgnoreHttpsDelegate: URLSessionDelegate { ) { //Trust the certificate even if not valid let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!) - + completionHandler(.useCredential, urlCredential) } } From 47e1a5de5ee220eda5cff77fb0cad8009a3f3b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 23 Nov 2023 16:38:56 +0100 Subject: [PATCH 044/378] Improve MAC validation (#333) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Change the name of the function `validate_mac` to the more appropiate `generate_mac`, and change the mac comparison to be constant time with the use of the `subtle` crate. Note that `hmac.finalize()` returns a type `CtOutput` that supports constant time comparison by using the `subtle` crate internally, but `CtOutput` doesn't allow getting a reference to the internal array which would complicate the implementation of `EncString`, so I chose to use the `subtle` constant time comparison directly. --- Cargo.lock | 1 + crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/crypto/aes_ops.rs | 15 ++++++++------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c040eb279..fb1768bee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -351,6 +351,7 @@ dependencies = [ "serde_repr", "sha1", "sha2", + "subtle", "thiserror", "tokio", "uniffi", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index fea9a2fd7..31e39c350 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -42,6 +42,7 @@ pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } argon2 = { version = ">=0.5.0, <0.6", features = [ "alloc", ], default-features = false } +subtle = ">=2.5.0, <3.0" rand = ">=0.8.5, <0.9" num-bigint = ">=0.4, <0.5" num-traits = ">=0.2.15, <0.3" diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 3deedabd8..182986c3b 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -13,6 +13,7 @@ use aes::cipher::{ BlockEncryptMut, KeyIvInit, }; use hmac::Mac; +use subtle::ConstantTimeEq; use crate::{ crypto::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, @@ -47,8 +48,8 @@ pub fn decrypt_aes256_hmac( mac_key: GenericArray, key: GenericArray, ) -> Result> { - let res = validate_mac(&mac_key, iv, &data)?; - if res != *mac { + let res = generate_mac(&mac_key, iv, &data)?; + if res.ct_ne(mac).into() { return Err(CryptoError::InvalidMac.into()); } decrypt_aes256(iv, data, key) @@ -83,7 +84,7 @@ pub fn encrypt_aes256_hmac( ) -> Result<([u8; 16], [u8; 32], Vec)> { let rng = rand::thread_rng(); let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); - let mac = validate_mac(&mac_key, &iv, &data)?; + let mac = generate_mac(&mac_key, &iv, &data)?; Ok((iv, mac, data)) } @@ -106,8 +107,8 @@ fn encrypt_aes256_internal( (iv, data) } -/// Validate a MAC using HMAC-SHA256. -fn validate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { +/// Generate a MAC using HMAC-SHA256. +fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); hmac.update(iv); hmac.update(data); @@ -156,13 +157,13 @@ mod tests { } #[test] - fn test_validate_mac() { + fn test_generate_mac() { let mac_key = generate_vec(16, 0, 16); let iv = generate_vec(16, 0, 16); let data = generate_vec(16, 0, 16); - let result = validate_mac(&mac_key, &iv, &data); + let result = generate_mac(&mac_key, &iv, &data); assert!(result.is_ok()); let mac = result.unwrap(); From a026cdaf44025900062a197251281e4a1ff88022 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 23 Nov 2023 17:46:11 +0100 Subject: [PATCH 045/378] Sync renovate config to be inline with other repos (#342) --- .github/renovate.json | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 71e131e43..16222e52c 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -2,44 +2,26 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base", - "schedule:weekends", ":combinePatchMinorReleases", ":dependencyDashboard", ":maintainLockFilesWeekly", ":prConcurrentLimit10", ":rebaseStalePrs", - ":separateMajorReleases" + ":separateMajorReleases", + "group:monorepos", + "schedule:weekends" ], "separateMajorMinor": true, "enabledManagers": ["cargo", "github-actions", "npm", "nuget"], + "commitMessagePrefix": "[deps]:", + "commitMessageTopic": "{{depName}}", "packageRules": [ - { - "groupName": "npm minor", - "matchManagers": ["npm"], - "matchUpdateTypes": ["minor", "patch"] - }, - { - "matchManagers": ["cargo"], - "matchUpdateTypes": ["patch"], - "enabled": false - }, - { - "matchManagers": ["cargo"], - "matchUpdateTypes": ["minor"], - "matchCurrentVersion": ">=1.0.0", - "enabled": false - }, { "matchManagers": ["cargo"], "matchPackagePatterns": ["pyo3*"], "matchUpdateTypes": ["minor", "patch"], "groupName": "pyo3 non-major" }, - { - "groupName": "nuget minor", - "matchManagers": ["nuget"], - "matchUpdateTypes": ["minor", "patch"] - }, { "groupName": "gh minor", "matchManagers": ["github-actions"], From 2f04f8c3223f4dd1ac9a59d76c2dd8a82b7ec3c8 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 23 Nov 2023 17:49:50 +0100 Subject: [PATCH 046/378] Use reqwest header constants (#343) --- crates/bitwarden/src/auth/api/request/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden/src/auth/api/request/mod.rs b/crates/bitwarden/src/auth/api/request/mod.rs index 1277fa969..85b36a983 100644 --- a/crates/bitwarden/src/auth/api/request/mod.rs +++ b/crates/bitwarden/src/auth/api/request/mod.rs @@ -35,10 +35,10 @@ async fn send_identity_connect_request( &configurations.identity.base_path )) .header( - "Content-Type", + reqwest::header::CONTENT_TYPE, "application/x-www-form-urlencoded; charset=utf-8", ) - .header("Accept", "application/json") + .header(reqwest::header::ACCEPT, "application/json") .header("Device-Type", configurations.device_type as usize); if let Some(ref user_agent) = configurations.identity.user_agent { From 94dae37ca20279f5c139a6e88f0f3462088c8ba8 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 23 Nov 2023 18:29:15 +0100 Subject: [PATCH 047/378] Sort cargo.toml files (#344) --- crates/bitwarden-c/Cargo.toml | 1 - crates/bitwarden-json/Cargo.toml | 2 +- crates/bitwarden-napi/Cargo.toml | 6 ++-- crates/bitwarden-py/Cargo.toml | 1 - crates/bitwarden-uniffi/Cargo.toml | 2 +- crates/bitwarden-wasm/Cargo.toml | 9 +++--- crates/bitwarden/Cargo.toml | 52 ++++++++++++++---------------- crates/bw/Cargo.toml | 8 ++--- crates/bws/Cargo.toml | 7 ++-- crates/sdk-schemas/Cargo.toml | 4 +-- 10 files changed, 43 insertions(+), 49 deletions(-) diff --git a/crates/bitwarden-c/Cargo.toml b/crates/bitwarden-c/Cargo.toml index 9181bedae..20f3f5229 100644 --- a/crates/bitwarden-c/Cargo.toml +++ b/crates/bitwarden-c/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" rust-version = "1.57" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] crate-type = ["lib", "staticlib", "cdylib"] bench = false diff --git a/crates/bitwarden-json/Cargo.toml b/crates/bitwarden-json/Cargo.toml index 579a8bdab..f7c0fd58d 100644 --- a/crates/bitwarden-json/Cargo.toml +++ b/crates/bitwarden-json/Cargo.toml @@ -18,9 +18,9 @@ internal = ["bitwarden/internal"] # Internal testing methods secrets = ["bitwarden/secrets"] # Secrets manager API [dependencies] +log = ">=0.4.18, <0.5" schemars = ">=0.8.12, <0.9" serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" -log = ">=0.4.18, <0.5" bitwarden = { path = "../bitwarden" } diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 505b68e57..2e86fefe2 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -16,10 +16,10 @@ rust-version = "1.57" crate-type = ["cdylib", "rlib"] [dependencies] -napi = {version="2", features=["async"]} -napi-derive = "2" +env_logger = "0.10.0" log = "0.4.18" -env_logger="0.10.0" +napi = { version = "2", features = ["async"] } +napi-derive = "2" bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = ["secrets"] } diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 613203c84..5c1fa5cac 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" rust-version = "1.57" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] name = "bitwarden_py" crate-type = ["cdylib"] diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 53da0eb8d..098c5b2bf 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -18,8 +18,8 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } env_logger = "0.10.0" -uniffi = "=0.25.1" schemars = { version = ">=0.8, <0.9", optional = true } +uniffi = "=0.25.1" bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index add03f0f3..fcb0c2b15 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -4,18 +4,17 @@ version = "0.1.0" edition = "2021" rust-version = "1.57" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] crate-type = ["cdylib", "rlib"] [dependencies] -js-sys = "0.3.63" -serde = {version = "1.0.163", features = ["derive"] } -wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.36" console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } +js-sys = "0.3.63" log = "0.4.18" +serde = { version = "1.0.163", features = ["derive"] } +wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } +wasm-bindgen-futures = "0.4.36" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 31e39c350..b0135dfa3 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -20,44 +20,42 @@ internal = [] # Internal testing methods mobile = ["uniffi", "internal"] # Mobile-specific features [dependencies] +aes = ">=0.8.2, <0.9" +argon2 = { version = ">=0.5.0, <0.6", features = [ + "alloc", +], default-features = false } +assert_matches = ">=1.5.0, <2.0" base64 = ">=0.21.2, <0.22" +bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } +bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } +cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } +chrono = { version = ">=0.4.26, <0.5", features = [ + "serde", + "std", +], default-features = false } +# We don't use this directly (it's used by rand), but we need it here to enable WASM support +getrandom = { version = ">=0.2.9", features = ["js"] } +hkdf = ">=0.12.3, <0.13" +hmac = ">=0.12.1, <0.13" lazy_static = ">=1.4.0, <2.0" +log = ">=0.4.18, <0.5" +num-bigint = ">=0.4, <0.5" +num-traits = ">=0.2.15, <0.3" +pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } +rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = ["json"] } +rsa = ">=0.9.2, <0.10" +schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" serde_qs = ">=0.12.0, <0.13" serde_repr = ">=0.1.12, <0.2" -schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } -log = ">=0.4.18, <0.5" -assert_matches = ">=1.5.0, <2.0" -thiserror = ">=1.0.40, <2.0" -aes = ">=0.8.2, <0.9" -cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } -hkdf = ">=0.12.3, <0.13" -hmac = ">=0.12.1, <0.13" -rsa = ">=0.9.2, <0.10" sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" -pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } -argon2 = { version = ">=0.5.0, <0.6", features = [ - "alloc", -], default-features = false } subtle = ">=2.5.0, <3.0" -rand = ">=0.8.5, <0.9" -num-bigint = ">=0.4, <0.5" -num-traits = ">=0.2.15, <0.3" -uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } -chrono = { version = ">=0.4.26, <0.5", features = [ - "serde", - "std", -], default-features = false } +thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.1", optional = true } - -# We don't use this directly (it's used by rand), but we need it here to enable WASM support -getrandom = { version = ">=0.2.9", features = ["js"] } - -bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } -bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } +uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 0793470b3..349087818 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -12,15 +12,13 @@ Bitwarden Password Manager CLI """ keywords = ["bitwarden", "password-manager", "cli"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] clap = { version = "4.3.0", features = ["derive", "env"] } -tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } -log = "0.4.18" -env_logger = "0.10.0" color-eyre = "0.6" +env_logger = "0.10.0" inquire = "0.6.2" +log = "0.4.18" +tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ "internal", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 9ccd5c546..91d75de69 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -12,8 +12,6 @@ Bitwarden Secrets Manager CLI """ keywords = ["bitwarden", "secrets-manager", "cli"] -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] bat = { version = "0.24.0", features = [ "regex-onig", @@ -29,6 +27,10 @@ comfy-table = "^7.0.1" directories = "5.0.1" env_logger = "0.10.0" log = "0.4.18" +regex = { version = "1.10.2", features = [ + "std", + "perf", +], default-features = false } serde = "^1.0.163" serde_json = "^1.0.96" serde_yaml = "0.9" @@ -37,7 +39,6 @@ thiserror = "1.0.40" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } -regex = { version = "1.10.2", features=["std", "perf"], default-features=false } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 64ce34274..86a73cd19 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -12,10 +12,10 @@ internal = [ ] [dependencies] -schemars = { version = "0.8.12", features = ["preserve_order"] } -serde_json = "1.0.96" anyhow = "1.0.71" itertools = "0.12.0" +schemars = { version = "0.8.12", features = ["preserve_order"] } +serde_json = "1.0.96" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From 62c7c1932532eeba68e278c11c9b6c0a2e4de062 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:47:53 +0100 Subject: [PATCH 048/378] [deps]: Update Rust crate thiserror to 1.0.50 (#345) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 91d75de69..fe94dfcb2 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -35,7 +35,7 @@ serde = "^1.0.163" serde_json = "^1.0.96" serde_yaml = "0.9" supports-color = "2.0.0" -thiserror = "1.0.40" +thiserror = "1.0.50" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } toml = "0.8.0" uuid = { version = "^1.3.3", features = ["serde"] } From 03c5d6b57713c0c2a56168e12e1a72f315580794 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Nov 2023 11:48:06 +0100 Subject: [PATCH 049/378] [deps]: Update Rust crate toml to 0.8.8 (#346) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index fe94dfcb2..225c99bcd 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -37,7 +37,7 @@ serde_yaml = "0.9" supports-color = "2.0.0" thiserror = "1.0.50" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } -toml = "0.8.0" +toml = "0.8.8" uuid = { version = "^1.3.3", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } From 5407db721214d35b7498a46a99c71a05087e4929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 24 Nov 2023 18:27:01 +0100 Subject: [PATCH 050/378] Fix VSCode tasks (#347) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Fix invalid path in VSCode tasks --- .vscode/tasks.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 55dc10eb2..fa97b8fc7 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,7 +6,7 @@ "command": "build", "problemMatcher": ["$rustc"], "options": { - "cwd": "${workspaceFolder}/bitwarden-c/" + "cwd": "${workspaceFolder}/crates/bitwarden-c/" }, "group": { "kind": "build", @@ -19,7 +19,7 @@ "command": "build", "args": ["--release"], "options": { - "cwd": "${workspaceFolder}/bitwarden-c/" + "cwd": "${workspaceFolder}/crates/bitwarden-c/" }, "problemMatcher": ["$rustc"], "label": "rust: bitwarden-c release build" From 422a9e4cfb5aa7d3e7f022d6a1fc539f709019d4 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 27 Nov 2023 11:15:58 +0100 Subject: [PATCH 051/378] Change all dependencies to be ranges (#357) --- crates/bitwarden-api-api/Cargo.toml | 14 +++++++------- crates/bitwarden-api-identity/Cargo.toml | 14 +++++++------- crates/bitwarden/Cargo.toml | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index 518cc33ed..2e05088e0 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -13,14 +13,14 @@ categories = ["api-bindings"] edition = "2018" [dependencies] -serde = "^1.0.163" -serde_derive = "^1.0.163" -serde_json = "^1.0.96" -serde_repr = "^0.1.12" -url = "^2.3.1" -uuid = { version = "^1.3.3", features = ["serde"] } +serde = ">=1.0.163, <2" +serde_derive = ">=1.0.163, <2" +serde_json = ">=1.0.96, <2" +serde_repr = ">=0.1.12, <0.2" +url = ">=2.3.1, <3" +uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] -version = "^0.11.18" +version = ">=0.11.18, <0.12" features = ["json", "multipart"] [dev-dependencies] diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 70be0560b..7207c5f8e 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -13,14 +13,14 @@ categories = ["api-bindings"] edition = "2018" [dependencies] -serde = "^1.0.163" -serde_derive = "^1.0.163" -serde_json = "^1.0.96" -serde_repr = "^0.1.12" -url = "^2.3.1" -uuid = { version = "^1.3.3", features = ["serde"] } +serde = ">=1.0.163, <2" +serde_derive = ">=1.0.163, <2" +serde_json = ">=1.0.96, <2" +serde_repr = ">=0.1.12, <0.2" +url = ">=2.3.1, <3" +uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] -version = "^0.11.18" +version = ">=0.11.18, <0.12" features = ["json", "multipart"] [dev-dependencies] diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index b0135dfa3..e52c03723 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -34,7 +34,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "std", ], default-features = false } # We don't use this directly (it's used by rand), but we need it here to enable WASM support -getrandom = { version = ">=0.2.9", features = ["js"] } +getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } hkdf = ">=0.12.3, <0.13" hmac = ">=0.12.1, <0.13" lazy_static = ">=1.4.0, <2.0" @@ -59,5 +59,5 @@ uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" -tokio = { version = "1.28.2", features = ["rt", "macros"] } -wiremock = "0.5.18" +tokio = { version = "1.34.0", features = ["rt", "macros"] } +wiremock = "0.5.21" From afe290dae16adee7ca543418059f3bcb1f1e85e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:16:24 +0100 Subject: [PATCH 052/378] [deps]: Update Rust crate log to 0.4.20 (#352) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/Cargo.toml | 2 +- crates/bitwarden-wasm/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 2e86fefe2..5139d17ca 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -17,7 +17,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] env_logger = "0.10.0" -log = "0.4.18" +log = "0.4.20" napi = { version = "2", features = ["async"] } napi-derive = "2" diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index fcb0c2b15..0c8a60c56 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"] console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.63" -log = "0.4.18" +log = "0.4.20" serde = { version = "1.0.163", features = ["derive"] } wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.36" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 349087818..85df34109 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -17,7 +17,7 @@ clap = { version = "4.3.0", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.0" inquire = "0.6.2" -log = "0.4.18" +log = "0.4.20" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 225c99bcd..a35d7f642 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -26,7 +26,7 @@ color-eyre = "0.6" comfy-table = "^7.0.1" directories = "5.0.1" env_logger = "0.10.0" -log = "0.4.18" +log = "0.4.20" regex = { version = "1.10.2", features = [ "std", "perf", From 8815cfd1ddcd0f32c339c7bbd5ff6d9d96ceffbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:17:17 +0000 Subject: [PATCH 053/378] [deps]: Update Rust crate anyhow to 1.0.75 (#348) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/sdk-schemas/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 86a73cd19..017d74a10 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -12,7 +12,7 @@ internal = [ ] [dependencies] -anyhow = "1.0.71" +anyhow = "1.0.75" itertools = "0.12.0" schemars = { version = "0.8.12", features = ["preserve_order"] } serde_json = "1.0.96" From 736f2d03780cf7feb2aef36b4b928eef849dc888 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:17:33 +0000 Subject: [PATCH 054/378] [deps]: Update Rust crate chrono to 0.4.31 (#349) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index a35d7f642..ebf917ab1 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -16,7 +16,7 @@ keywords = ["bitwarden", "secrets-manager", "cli"] bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } -chrono = { version = "0.4.26", features = [ +chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } From 8073952c0c5c5376832bb34624462a9df3abce40 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:27:22 +0100 Subject: [PATCH 055/378] [deps]: Update Rust crate env_logger to 0.10.1 (#350) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/Cargo.toml | 2 +- crates/bitwarden-uniffi/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 5139d17ca..8ab71c56d 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -16,7 +16,7 @@ rust-version = "1.57" crate-type = ["cdylib", "rlib"] [dependencies] -env_logger = "0.10.0" +env_logger = "0.10.1" log = "0.4.20" napi = { version = "2", features = ["async"] } napi-derive = "2" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 098c5b2bf..474f5f299 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -17,7 +17,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -env_logger = "0.10.0" +env_logger = "0.10.1" schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.25.1" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 85df34109..244ecf51e 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["bitwarden", "password-manager", "cli"] [dependencies] clap = { version = "4.3.0", features = ["derive", "env"] } color-eyre = "0.6" -env_logger = "0.10.0" +env_logger = "0.10.1" inquire = "0.6.2" log = "0.4.20" tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index ebf917ab1..bf91adda8 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -25,7 +25,7 @@ clap_complete = "4.3.2" color-eyre = "0.6" comfy-table = "^7.0.1" directories = "5.0.1" -env_logger = "0.10.0" +env_logger = "0.10.1" log = "0.4.20" regex = { version = "1.10.2", features = [ "std", From 9b752bafcd5a32c0ceb671f435d7355e71180e93 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:27:33 +0100 Subject: [PATCH 056/378] [deps]: Update Rust crate schemars to 0.8.16 (#354) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/sdk-schemas/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 017d74a10..f3e70c04c 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -14,7 +14,7 @@ internal = [ [dependencies] anyhow = "1.0.75" itertools = "0.12.0" -schemars = { version = "0.8.12", features = ["preserve_order"] } +schemars = { version = "0.8.16", features = ["preserve_order"] } serde_json = "1.0.96" bitwarden = { path = "../bitwarden" } From b88ce1341cfbb683b006046a8bd25d434439a74a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:33:35 +0100 Subject: [PATCH 057/378] [deps]: Update Rust crate tokio to 1.34.0 (#358) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-py/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 5c1fa5cac..94e9e6a43 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -18,7 +18,7 @@ bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3-build-config = { version = "0.20.0" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] -tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 244ecf51e..4659caac8 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" log = "0.4.20" -tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ "internal", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index bf91adda8..649015b10 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -36,7 +36,7 @@ serde_json = "^1.0.96" serde_yaml = "0.9" supports-color = "2.0.0" thiserror = "1.0.50" -tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.3.3", features = ["serde"] } From 6f84712b7a611c3aeaf2ce7c1cc5e0f843391770 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:34:58 +0100 Subject: [PATCH 058/378] [deps]: Update Rust crate clap to 4.4.8 (#359) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 606e24856..bedf57e58 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.3.0", features = ["derive"] } +clap = { version = "4.4.8", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.0.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 4659caac8..4c2d6b012 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.3.0", features = ["derive", "env"] } +clap = { version = "4.4.8", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 649015b10..770f5f6db 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.3.0", features = ["derive", "env", "string"] } +clap = { version = "4.4.8", features = ["derive", "env", "string"] } clap_complete = "4.3.2" color-eyre = "0.6" comfy-table = "^7.0.1" From a2597217349c3fac94ed8606fdfdee2bcfa091fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:35:22 +0100 Subject: [PATCH 059/378] [deps]: Update Rust crate tempfile to 3.8.1 (#362) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 4c2d6b012..9ceb2b153 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -27,4 +27,4 @@ bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } [dev-dependencies] -tempfile = "3.5.0" +tempfile = "3.8.1" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 770f5f6db..c8afd73e4 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -43,7 +43,7 @@ uuid = { version = "^1.3.3", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } [dev-dependencies] -tempfile = "3.5.0" +tempfile = "3.8.1" [target.'cfg(target_os = "linux")'.dependencies] openssl = { version = "0.10", features = ["vendored"] } From 78c5fa23174902dd33eaccf12cb25d076e560758 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:36:13 +0000 Subject: [PATCH 060/378] [deps]: Update Rust crate serde_json to v1.0.108 (#355) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index c8afd73e4..2a1561b8e 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -32,7 +32,7 @@ regex = { version = "1.10.2", features = [ "perf", ], default-features = false } serde = "^1.0.163" -serde_json = "^1.0.96" +serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.0.0" thiserror = "1.0.50" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index f3e70c04c..2e7706200 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -15,7 +15,7 @@ internal = [ anyhow = "1.0.75" itertools = "0.12.0" schemars = { version = "0.8.16", features = ["preserve_order"] } -serde_json = "1.0.96" +serde_json = "1.0.108" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From 520608dbe0e4fa245cd9414d3b909295195e85d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:36:36 +0100 Subject: [PATCH 061/378] [deps]: Update Rust crate supports-color to 2.1.0 (#361) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index bedf57e58..0966f7885 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -8,4 +8,4 @@ rust-version = "1.57" clap = { version = "4.4.8", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" -supports-color = "2.0.0" +supports-color = "2.1.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 2a1561b8e..32a189988 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -34,7 +34,7 @@ regex = { version = "1.10.2", features = [ serde = "^1.0.163" serde_json = "^1.0.108" serde_yaml = "0.9" -supports-color = "2.0.0" +supports-color = "2.1.0" thiserror = "1.0.50" tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" From 57352eb3bf13a445da6f0dfe297748be8d5f0393 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:40:15 +0100 Subject: [PATCH 062/378] [deps]: Update Rust crate clap_complete to 4.4.4 (#360) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 32a189988..39cf92a85 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.31", features = [ "std", ], default-features = false } clap = { version = "4.4.8", features = ["derive", "env", "string"] } -clap_complete = "4.3.2" +clap_complete = "4.4.4" color-eyre = "0.6" comfy-table = "^7.0.1" directories = "5.0.1" From 7a216991aefdec3e2e6b02f38436eb8c68dae91f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:42:15 +0100 Subject: [PATCH 063/378] [deps]: Update Rust crate uuid to ^1.6.1 (#365) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fb1768bee..232b823b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3618,9 +3618,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58fe91d841bc04822c9801002db4ea904b9e4b8e6bbad25127b46eff8dc516b" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "serde", ] diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 39cf92a85..3580446b9 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -38,7 +38,7 @@ supports-color = "2.1.0" thiserror = "1.0.50" tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" -uuid = { version = "^1.3.3", features = ["serde"] } +uuid = { version = "^1.6.1", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } From cd93d42ae3bd82b353005d5b1af28f047da769a7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:42:47 +0100 Subject: [PATCH 064/378] [deps]: Update Rust crate comfy-table to ^7.1.0 (#363) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 3580446b9..c0dfc7bac 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -23,7 +23,7 @@ chrono = { version = "0.4.31", features = [ clap = { version = "4.4.8", features = ["derive", "env", "string"] } clap_complete = "4.4.4" color-eyre = "0.6" -comfy-table = "^7.0.1" +comfy-table = "^7.1.0" directories = "5.0.1" env_logger = "0.10.1" log = "0.4.20" From b9ca9e5928441beb98d3ad98ee2b2a66a0d0faf7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 12:38:14 +0100 Subject: [PATCH 065/378] [deps]: Update Rust crate napi-build to 2.1.0 (#364) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 8ab71c56d..63eae2b8b 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -24,7 +24,7 @@ napi-derive = "2" bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = ["secrets"] } [build-dependencies] -napi-build = "2.0.1" +napi-build = "2.1.0" [profile.release] lto = true From 2c01cd3ff4d2fca565e14dfa479e44ee3d68cce7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:07:30 +0100 Subject: [PATCH 066/378] [deps]: Update Rust crate serde to v1.0.193 (#367) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bitwarden-wasm/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 232b823b4..ff741ead5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2778,18 +2778,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 0c8a60c56..7ad0d1c3e 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -12,7 +12,7 @@ console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.63" log = "0.4.20" -serde = { version = "1.0.163", features = ["derive"] } +serde = { version = "1.0.193", features = ["derive"] } wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.36" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index c0dfc7bac..95dbef003 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -31,7 +31,7 @@ regex = { version = "1.10.2", features = [ "std", "perf", ], default-features = false } -serde = "^1.0.163" +serde = "^1.0.193" serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" From af31957425d007926f0ec72a9ae1b5c434244f5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:07:56 +0100 Subject: [PATCH 067/378] [deps]: Update Rust crate async-lock to 3.1.2 (#368) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 16 ++++++++-------- crates/bitwarden-uniffi/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff741ead5..2a4d3b6aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,11 +203,11 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655b9c7fe787d3b25cc0f804a1a8401790f0c5bc395beb5a64dc77d8de079105" +checksum = "dea8b3453dd7cc96711834b75400d671b73e3656975fa68d9f277163b7f7e316" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.0", "event-listener-strategy", "pin-project-lite", ] @@ -1065,9 +1065,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "3.1.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" dependencies = [ "concurrent-queue", "parking", @@ -1076,11 +1076,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96b852f1345da36d551b9473fa1e2b1eb5c5195585c6c018118bc92a8d91160" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 3.1.0", + "event-listener 4.0.0", "pin-project-lite", ] diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 474f5f299..405642d71 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "3.0.0" +async-lock = "3.1.2" chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", From 92a67b194e59ba445531abbdd76971c250d56f3e Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Mon, 27 Nov 2023 11:00:44 -0500 Subject: [PATCH 068/378] SM-874: Fix Python Integration (#229) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective The Python integration is out of date and is not currently working. This PR fixes the Python integration by adding the ability to log in via access token, which is currently the supported way to interact with the Bitwarden Secrets Manager SDK. This PR also adds a `ProjectsClient` to `bitwarden_client.py` for easy use, and updates the error handling on Project or Secret deletes in the SDK. ## Code changes - **crates/sdk-schemas/src/main.rs:** We need the `AccessTokenLoginResponse` struct to be generated so access token auth is available to integrations - **languages/python/BitwardenClient/bitwarden_client.py:** - Import the following from `.schemas`: - `AccessTokenLoginRequest` - `AccessTokenLoginResponse` - `ResponseForAccessTokenLoginResponse` - Define a new function `access_token_login` to support authenticating with an access token - Add the `project_ids` parameter to the `create` and `update` functions for `SecretsClient` - Add a `ProjectsClient` class and `projects()` to the `BitwardenClient` - Removed the password login methods, as they are not supported - Removed the imports that are not needed, and add one that are (like `sys`, etc.) - **languages/python/README.md:** Update the readme instructions, give more examples - **languages/python/login.py:** Renamed `login.py` to `example.py` - **languages/python/example.py:** Update the example to showcase auth with an access token ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/sdk-schemas/src/main.rs | 1 + .../BitwardenClient/bitwarden_client.py | 90 +++++++++++++------ languages/python/README.md | 6 +- languages/python/example.py | 44 +++++++++ languages/python/login.py | 24 ----- 5 files changed, 115 insertions(+), 50 deletions(-) create mode 100644 languages/python/example.py delete mode 100644 languages/python/login.py diff --git a/crates/sdk-schemas/src/main.rs b/crates/sdk-schemas/src/main.rs index 9d7e52a47..ef7a2db83 100644 --- a/crates/sdk-schemas/src/main.rs +++ b/crates/sdk-schemas/src/main.rs @@ -99,6 +99,7 @@ fn main() -> Result<()> { write_schema_for_response! { bitwarden::auth::login::ApiKeyLoginResponse, bitwarden::auth::login::PasswordLoginResponse, + bitwarden::auth::login::AccessTokenLoginResponse, bitwarden::secrets_manager::secrets::SecretIdentifiersResponse, bitwarden::secrets_manager::secrets::SecretResponse, bitwarden::secrets_manager::secrets::SecretsResponse, diff --git a/languages/python/BitwardenClient/bitwarden_client.py b/languages/python/BitwardenClient/bitwarden_client.py index 6a0a77ed8..cb669a40e 100644 --- a/languages/python/BitwardenClient/bitwarden_client.py +++ b/languages/python/BitwardenClient/bitwarden_client.py @@ -1,8 +1,8 @@ import json -from typing import Any, List +from typing import Any, List, Optional +from uuid import UUID import bitwarden_py -from .schemas import ClientSettings, Command, PasswordLoginRequest, PasswordLoginResponse, ResponseForPasswordLoginResponse, ResponseForSecretIdentifiersResponse, ResponseForSecretResponse, ResponseForSecretsDeleteResponse, ResponseForSyncResponse, ResponseForUserAPIKeyResponse, SecretCreateRequest, SecretGetRequest, SecretIdentifiersRequest, SecretIdentifiersResponse, SecretPutRequest, SecretResponse, SecretVerificationRequest, SecretsCommand, SecretsDeleteRequest, SecretsDeleteResponse, SyncRequest, SyncResponse, UserAPIKeyResponse - +from .schemas import ClientSettings, Command, ResponseForSecretIdentifiersResponse, ResponseForSecretResponse, ResponseForSecretsDeleteResponse, SecretCreateRequest, SecretGetRequest, SecretIdentifiersRequest, SecretIdentifiersResponse, SecretPutRequest, SecretResponse, SecretsCommand, SecretsDeleteRequest, SecretsDeleteResponse, AccessTokenLoginRequest, AccessTokenLoginResponse, ResponseForAccessTokenLoginResponse, ResponseForProjectResponse, ProjectsCommand, ProjectCreateRequest, ProjectGetRequest, ProjectPutRequest, ProjectsListRequest, ResponseForProjectsResponse, ResponseForProjectsDeleteResponse, ProjectsDeleteRequest class BitwardenClient: def __init__(self, settings: ClientSettings = None): @@ -12,32 +12,25 @@ def __init__(self, settings: ClientSettings = None): settings_json = json.dumps(settings.to_dict()) self.inner = bitwarden_py.BitwardenClient(settings_json) - def password_login(self, email: str, password: str) -> ResponseForPasswordLoginResponse: - result = self._run_command( - Command(password_login=PasswordLoginRequest(email, password)) - ) - return ResponseForPasswordLoginResponse.from_dict(result) - - def get_user_api_key(self, secret: str, is_otp: bool = False) -> ResponseForUserAPIKeyResponse: - result = self._run_command( - Command(get_user_api_key=SecretVerificationRequest( - secret if not is_otp else None, secret if is_otp else None)) + def access_token_login(self, access_token: str): + self._run_command( + Command(access_token_login=AccessTokenLoginRequest(access_token)) ) - return ResponseForUserAPIKeyResponse.from_dict(result) - - def sync(self, exclude_subdomains: bool = False) -> ResponseForSyncResponse: - result = self._run_command( - Command(sync=SyncRequest(exclude_subdomains)) - ) - return ResponseForSyncResponse.from_dict(result) def secrets(self): return SecretsClient(self) + def projects(self): + return ProjectsClient(self) + def _run_command(self, command: Command) -> Any: response_json = self.inner.run_command(json.dumps(command.to_dict())) - return json.loads(response_json) + response = json.loads(response_json) + if response["success"] == False: + raise Exception(response["errorMessage"]) + + return response class SecretsClient: def __init__(self, client: BitwardenClient): @@ -52,10 +45,12 @@ def get(self, id: str) -> ResponseForSecretResponse: def create(self, key: str, note: str, organization_id: str, - value: str) -> ResponseForSecretResponse: + value: str, + project_ids: Optional[List[UUID]] = None + ) -> ResponseForSecretResponse: result = self.client._run_command( Command(secrets=SecretsCommand( - create=SecretCreateRequest(key, note, organization_id, value))) + create=SecretCreateRequest(key, note, organization_id, value, project_ids))) ) return ResponseForSecretResponse.from_dict(result) @@ -70,10 +65,12 @@ def update(self, id: str, key: str, note: str, organization_id: str, - value: str) -> ResponseForSecretResponse: + value: str, + project_ids: Optional[List[UUID]] = None + ) -> ResponseForSecretResponse: result = self.client._run_command( Command(secrets=SecretsCommand(update=SecretPutRequest( - id, key, note, organization_id, value))) + id, key, note, organization_id, value, project_ids))) ) return ResponseForSecretResponse.from_dict(result) @@ -82,3 +79,46 @@ def delete(self, ids: List[str]) -> ResponseForSecretsDeleteResponse: Command(secrets=SecretsCommand(delete=SecretsDeleteRequest(ids))) ) return ResponseForSecretsDeleteResponse.from_dict(result) + +class ProjectsClient: + def __init__(self, client: BitwardenClient): + self.client = client + + def get(self, id: str) -> ResponseForProjectResponse: + result = self.client._run_command( + Command(projects=ProjectsCommand(get=ProjectGetRequest(id))) + ) + return ResponseForProjectResponse.from_dict(result) + + def create(self, + name: str, + organization_id: str, + ) -> ResponseForProjectResponse: + result = self.client._run_command( + Command(projects=ProjectsCommand( + create=ProjectCreateRequest(name, organization_id))) + ) + return ResponseForProjectResponse.from_dict(result) + + def list(self, organization_id: str) -> ResponseForProjectsResponse: + result = self.client._run_command( + Command(projects=ProjectsCommand( + list=ProjectsListRequest(organization_id))) + ) + return ResponseForProjectsResponse.from_dict(result) + + def update(self, id: str, + name: str, + organization_id: str, + ) -> ResponseForProjectResponse: + result = self.client._run_command( + Command(projects=ProjectsCommand(update=ProjectPutRequest( + id, name, organization_id))) + ) + return ResponseForProjectResponse.from_dict(result) + + def delete(self, ids: List[str]) -> ResponseForProjectsDeleteResponse: + result = self.client._run_command( + Command(projects=ProjectsCommand(delete=ProjectsDeleteRequest(ids))) + ) + return ResponseForProjectsDeleteResponse.from_dict(result) diff --git a/languages/python/README.md b/languages/python/README.md index 03a4ce572..871be274f 100644 --- a/languages/python/README.md +++ b/languages/python/README.md @@ -9,6 +9,10 @@ ```bash pip install setuptools_rust ``` +- dateutil + ```bash + pip install python-dateutil + ``` # Installation @@ -18,7 +22,7 @@ From the `languages/python/` directory, python3 ./setup.py develop ``` -Move the the resulting `.so` file to `bitwarden_py.so`, if it isn't already there. +Rename the the resulting `.so` file to `bitwarden_py.so`, if it isn't already there. # Run diff --git a/languages/python/example.py b/languages/python/example.py new file mode 100644 index 000000000..2ee1cb280 --- /dev/null +++ b/languages/python/example.py @@ -0,0 +1,44 @@ +import json +import logging +import sys +from BitwardenClient.bitwarden_client import BitwardenClient +from BitwardenClient.schemas import client_settings_from_dict, DeviceType + +# Create the BitwardenClient, which is used to interact with the SDK +client = BitwardenClient(client_settings_from_dict({ + "apiUrl": "http://localhost:4000", + "deviceType": DeviceType.SDK, + "identityUrl": "http://localhost:33656", + "userAgent": "Python", +})) + +# Add some logging & set the org id +logging.basicConfig(level=logging.DEBUG) +organization_id = "org_id_here" + +# Attempt to authenticate with the Secrets Manager Access Token +client.access_token_login("access_token_here") + +# -- Example Project Commands -- + +project = client.projects().create("ProjectName", organization_id) +project2 = client.projects().create("Project - Don't Delete Me!", organization_id) +updated_project = client.projects().update(project.data.id, "Cool New Project Name", organization_id) +get_that_project = client.projects().get(project.data.id) + +input("Press Enter to delete the project...") +client.projects().delete([project.data.id]) + +print(client.projects().list(organization_id)) + +# -- Example Secret Commands -- + +secret = client.secrets().create("TEST_SECRET", "This is a test secret", organization_id, "Secret1234!", [project2.data.id]) +secret2 = client.secrets().create("Secret - Don't Delete Me!", "This is a test secret that will stay", organization_id, "Secret1234!", [project2.data.id]) +secret_updated = client.secrets().update(secret.data.id, "TEST_SECRET_UPDATED", "This as an updated test secret", organization_id, "Secret1234!_updated", [project2.data.id]) +secret_retrieved = client.secrets().get(secret.data.id) + +input("Press Enter to delete the secret...") +client.secrets().delete([secret.data.id]) + +print(client.secrets().list(organization_id)) diff --git a/languages/python/login.py b/languages/python/login.py deleted file mode 100644 index 9b756a005..000000000 --- a/languages/python/login.py +++ /dev/null @@ -1,24 +0,0 @@ -import json -import logging -from BitwardenClient.bitwarden_client import BitwardenClient -from BitwardenClient.schemas import client_settings_from_dict - -client = BitwardenClient(client_settings_from_dict({ - "api_url": "http://localhost:4000", - "identity_url": "http://localhost:33656", - "user_agent": "Python", -})) - -logging.basicConfig(level=logging.DEBUG) - -result = client.password_login("test@bitwarden.com", "asdfasdf") -print(result) -print(client.get_user_api_key("asdfasdf")) - -sync = client.sync() - -secret = client.secrets().create("TEST_SECRET", "This is a test secret", - sync.data.profile.organizations[0].id, "Secret1234!") -print(secret) - -client.secrets().delete([secret.data.id]) From 56fb552b312c47340122ad7c6181c55e878ae929 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 28 Nov 2023 15:06:50 +0100 Subject: [PATCH 069/378] Lock SDK to 6.0.100 and ignore with Renovate updates (#294) --- .github/renovate.json | 3 ++- languages/csharp/global.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 16222e52c..42f5f93f2 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -27,5 +27,6 @@ "matchManagers": ["github-actions"], "matchUpdateTypes": ["minor", "patch"] } - ] + ], + "ignoreDeps": ["dotnet-sdk"] } diff --git a/languages/csharp/global.json b/languages/csharp/global.json index 527fd31d3..10b65be86 100644 --- a/languages/csharp/global.json +++ b/languages/csharp/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "6.0.413", + "version": "6.0.100", "rollForward": "latestFeature" } } From f18020de098c43ce30fbc81a6424a707f1aa593e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:06:16 -0500 Subject: [PATCH 070/378] [deps]: Update gh minor (#366) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/release-napi.yml | 2 +- .github/workflows/version-bump.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 110e3758b..d04d15a45 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -102,7 +102,7 @@ jobs: run: ./build-schemas.sh - name: Publish - uses: gradle/gradle-build-action@842c587ad8aa4c68eeba24c396e15af4c2e9f30a # v2.9.0 + uses: gradle/gradle-build-action@87a9a15658c426a54dd469d4fc7dc1a73ca9d4a6 # v2.10.0 with: arguments: sdk:publish build-root-directory: languages/kotlin diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 468570cd8..b5a03ad47 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -103,7 +103,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 4c52529e8..9ef782b7f 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -128,7 +128,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index daa450c0b..1e7b2e022 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -126,7 +126,7 @@ jobs: run: npm run tsc - name: Login to Azure - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index d902c5700..9fb441fa9 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -43,7 +43,7 @@ jobs: run: cargo install cargo-edit - name: Login to Azure - Prod Subscription - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} From 31c005f9d53656b39088f700a798789add32b1b7 Mon Sep 17 00:00:00 2001 From: Luka Potkonjak <46886659+lukpotSym@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:59:07 +0100 Subject: [PATCH 071/378] Java wrapper for SDK (#179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Added a Maven-based Java project that wraps native C library for the SDK and exposed its commands through BitwardenClient class. ## Code changes - Updated schemas.ts to generate Java classes for the API - difference with current generators is that it creates multiple files - Added BitWardenClient class as a wrapper for the native SDK library - BitwardenLibrary inteface uses JNA to link to the native lib - AutoCloseable inteface implemented to deal with freeing memory, client can be used with try-with-resources or close() can be called explicitly (finalize() method is deprecated in newer Java versions) --------- Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> Co-authored-by: Daniel García Co-authored-by: Oscar Hinton --- .github/workflows/build-java.yml | 68 +++++ .github/workflows/generate_schemas.yml | 7 + .gitignore | 1 + .vscode/tasks.json | 11 + languages/java/.gitignore | 3 + languages/java/README.md | 73 +++++ languages/java/build.gradle | 90 +++++++ .../java/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63721 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + languages/java/gradlew | 249 ++++++++++++++++++ languages/java/gradlew.bat | 92 +++++++ languages/java/settings.gradle | 5 + .../com/bitwarden/sdk/BitwardenClient.java | 87 ++++++ .../sdk/BitwardenClientException.java | 8 + .../com/bitwarden/sdk/BitwardenLibrary.java | 13 + .../com/bitwarden/sdk/BitwardenSettings.java | 32 +++ .../java/com/bitwarden/sdk/CommandRunner.java | 45 ++++ .../com/bitwarden/sdk/ExampleProgram.java | 42 +++ .../com/bitwarden/sdk/ProjectsClient.java | 109 ++++++++ .../java/com/bitwarden/sdk/SecretsClient.java | 115 ++++++++ .../com/bitwarden/sdk/ThrowingFunction.java | 7 + support/scripts/schemas.ts | 25 +- 22 files changed, 1088 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-java.yml create mode 100644 languages/java/.gitignore create mode 100644 languages/java/README.md create mode 100644 languages/java/build.gradle create mode 100644 languages/java/gradle/wrapper/gradle-wrapper.jar create mode 100644 languages/java/gradle/wrapper/gradle-wrapper.properties create mode 100755 languages/java/gradlew create mode 100644 languages/java/gradlew.bat create mode 100644 languages/java/settings.gradle create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/BitwardenClient.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/BitwardenClientException.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/BitwardenLibrary.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/BitwardenSettings.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/CommandRunner.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/ProjectsClient.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/SecretsClient.java create mode 100644 languages/java/src/main/java/com/bitwarden/sdk/ThrowingFunction.java diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml new file mode 100644 index 000000000..e500424dd --- /dev/null +++ b/.github/workflows/build-java.yml @@ -0,0 +1,68 @@ +name: Build Java SDK + +on: + pull_request: + branches: + - master + +jobs: + generate_schemas: + uses: ./.github/workflows/generate_schemas.yml + + build_rust: + uses: ./.github/workflows/build-rust-cross-platform.yml + + build_java: + name: Build Java + runs-on: ubuntu-22.04 + needs: + - generate_schemas + - build_rust + + steps: + - name: Checkout Repository + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + + - name: Download Java schemas artifact + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: sdk-schemas-java + path: languages/java/src/main/java/bit/sdk/schema/ + + - name: Setup Java + uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0 + with: + distribution: temurin + java-version: 17 + + - name: Download x86_64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-apple-darwin + path: languages/java/src/main/resources/darwin-x64 + + - name: Download aarch64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-aarch64-apple-darwin + path: languages/java/src/main/resources/darwin-aarch64 + + - name: Download x86_64-unknown-linux-gnu files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-unknown-linux-gnu + path: languages/java/src/main/resources/ubuntu-x64 + + - name: Download x86_64-pc-windows-msvc files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-pc-windows-msvc + path: languages/java/src/main/resources/windows-x64 + + - name: Publish Maven + uses: gradle/gradle-build-action@b5126f31dbc19dd434c3269bf8c28c315e121da2 # v2.8.1 + with: + arguments: publish + build-root-directory: languages/java + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 5f5742da0..675f53c1e 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -63,3 +63,10 @@ jobs: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error + + - name: Upload java schemas artifact + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: sdk-schemas-java + path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* + if-no-files-found: error diff --git a/.gitignore b/.gitignore index 3f459493b..38b074349 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,4 @@ crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts languages/csharp/Bitwarden.Sdk/schemas.cs languages/js_webassembly/bitwarden_client/schemas.ts languages/python/BitwardenClient/schemas.py +languages/java/src/main/java/com/bitwarden/sdk/schema diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fa97b8fc7..71400c06e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -46,6 +46,17 @@ "options": { "cwd": "${workspaceFolder}/languages/python" } + }, + { + "label": "buildJava", + "type": "shell", + "command": "gradle", + "args": ["build"], + "dependsOrder": "sequence", + "dependsOn": ["rust: bitwarden-c build"], + "options": { + "cwd": "${workspaceFolder}/languages/java" + } } ] } diff --git a/languages/java/.gitignore b/languages/java/.gitignore new file mode 100644 index 000000000..b5b6c5697 --- /dev/null +++ b/languages/java/.gitignore @@ -0,0 +1,3 @@ +target +.gradle +src/main/resources diff --git a/languages/java/README.md b/languages/java/README.md new file mode 100644 index 000000000..06f1ffec3 --- /dev/null +++ b/languages/java/README.md @@ -0,0 +1,73 @@ +# Bitwarden Secrets Manager SDK + +Java bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some +functionality. + +## Create access token + +Review the help documentation on [Access Tokens] + +## Usage code snippets + +### Create new Bitwarden client + +```java +BitwardenSettings bitwardenSettings = new BitwardenSettings(); +bitwardenSettings.setApiUrl("https://api.bitwarden.com"); +bitwardenSettings.setIdentityUrl("https://identity.bitwarden.com"); +BitwardenClient bitwardenClient = new BitwardenClient(bitwardenSettings); +bitwardenClient.accessTokenLogin(""); +``` + +### Create new project + +```java +UUID organizationId = UUID.fromString(""); +var projectResponse = bitwardenClient.projects().create(organizationId, "TestProject"); +``` + +### List all projects + +```java +var projectsResponse = bitwardenClient.projects().list(organizationId); +``` + +### Update project + +```java +UUID projectId = projectResponse.getID(); +projectResponse = bitwardenClient.projects().get(projectId); +projectResponse = bitwardenClient.projects.update(projectId, organizationId, "TestProjectUpdated"); +``` + +### Add new secret + +```java +String key = "key"; +String value = "value"; +String note = "note"; +var secretResponse = bitwardenClient.secrets().create(key, value, note, organizationId, new UUID[]{projectId}); +UUID secretId = secretResponse.getID(); +``` + +### Update secret + +```java +bitwardenClient.secrets().update(secretId, key2, value2, note2, organizationId, new UUID[]{projectId}); +``` + +### List secrets + +```java +var secretIdentifiersResponse secretIdentifiersResponse = bitwardenClient.secrets().list(organizationId); +``` + +# Delete secret or project + +```java +bitwardenClient.secrets().delete(new UUID[]{secretId}); +bitwardenClient.projects().delete(new UUID[]{projectId}); +``` + +[Access Tokens]: https://bitwarden.com/help/access-tokens/ +[Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ \ No newline at end of file diff --git a/languages/java/build.gradle b/languages/java/build.gradle new file mode 100644 index 000000000..dc17386c4 --- /dev/null +++ b/languages/java/build.gradle @@ -0,0 +1,90 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +plugins { + id 'java-library' + id 'maven-publish' +} + +repositories { + mavenLocal() + maven { + url = uri('https://repo.maven.apache.org/maven2/') + } + + dependencies { + api 'com.fasterxml.jackson.core:jackson-core:2.9.10' + api 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.10' + api 'net.java.dev.jna:jna-platform:5.12.1' + } + + description = 'BitwardenSDK' + java.sourceCompatibility = JavaVersion.VERSION_1_8 + + publishing { + publications { + maven(MavenPublication) { + groupId = 'com.bitwarden' + artifactId = 'sdk' + + // Determine the version from the git history. + // + // PRs: use the branch name. + // Master: Grab it from `crates/bitwarden/Cargo.toml` + + def branchName = "git branch --show-current".execute().text.trim() + + if (branchName == "master") { + def content = ['grep', '-o', '^version = ".*"', '../../crates/bitwarden/Cargo.toml'].execute().text.trim() + def match = ~/version = "(.*)"/ + def matcher = match.matcher(content) + matcher.find() + + version = "${matcher.group(1)}-SNAPSHOT" + } else { + // branchName-SNAPSHOT + version = "${branchName.replaceAll('/', '-')}-SNAPSHOT" + } + + afterEvaluate { + from components.java + } + } + } + repositories { + maven { + name = "GitHubPackages" + url = "https://maven.pkg.github.com/bitwarden/sdk" + credentials { + username = System.getenv("GITHUB_ACTOR") + password = System.getenv("GITHUB_TOKEN") + } + } + } + } +} + +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} + +tasks.withType(Javadoc) { + options.encoding = 'UTF-8' +} + +// Gradle build requires GitHub workflow to copy native library to resources +// Uncomment copyNativeLib and jar tasks to use the local build (modify architecture if needed) +//tasks.register('copyNativeLib', Copy) { +// delete 'src/main/resources/darwin-aarch64' +// from '../../target/debug' +// include '*libbitwarden_c*.dylib' +// include '*libbitwarden_c*.so' +// include '*bitwarden_c*.dll' +// into 'src/main/resources/darwin-aarch64' +//} +// +//jar { +// dependsOn tasks.named("copyNativeLib").get() +// from 'src/main/resources' +//} diff --git a/languages/java/gradle/wrapper/gradle-wrapper.jar b/languages/java/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..7f93135c49b765f8051ef9d0a6055ff8e46073d8 GIT binary patch literal 63721 zcmb5Wb9gP!wgnp7wrv|bwr$&XvSZt}Z6`anZSUAlc9NHKf9JdJ;NJVr`=eI(_pMp0 zy1VAAG3FfAOI`{X1O)&90s;U4K;XLp008~hCjbEC_fbYfS%6kTR+JtXK>nW$ZR+`W ze|#J8f4A@M|F5BpfUJb5h>|j$jOe}0oE!`Zf6fM>CR?!y@zU(cL8NsKk`a z6tx5mAkdjD;J=LcJ;;Aw8p!v#ouk>mUDZF@ zK>yvw%+bKu+T{Nk@LZ;zkYy0HBKw06_IWcMHo*0HKpTsEFZhn5qCHH9j z)|XpN&{`!0a>Vl+PmdQc)Yg4A(AG-z!+@Q#eHr&g<9D?7E)_aEB?s_rx>UE9TUq|? z;(ggJt>9l?C|zoO@5)tu?EV0x_7T17q4fF-q3{yZ^ipUbKcRZ4Qftd!xO(#UGhb2y>?*@{xq%`(-`2T^vc=#< zx!+@4pRdk&*1ht2OWk^Z5IAQ0YTAXLkL{(D*$gENaD)7A%^XXrCchN&z2x+*>o2FwPFjWpeaL=!tzv#JOW#( z$B)Nel<+$bkH1KZv3&-}=SiG~w2sbDbAWarg%5>YbC|}*d9hBjBkR(@tyM0T)FO$# zPtRXukGPnOd)~z=?avu+4Co@wF}1T)-uh5jI<1$HLtyDrVak{gw`mcH@Q-@wg{v^c zRzu}hMKFHV<8w}o*yg6p@Sq%=gkd~;`_VGTS?L@yVu`xuGy+dH6YOwcP6ZE`_0rK% zAx5!FjDuss`FQ3eF|mhrWkjux(Pny^k$u_)dyCSEbAsecHsq#8B3n3kDU(zW5yE|( zgc>sFQywFj5}U*qtF9Y(bi*;>B7WJykcAXF86@)z|0-Vm@jt!EPoLA6>r)?@DIobIZ5Sx zsc@OC{b|3%vaMbyeM|O^UxEYlEMHK4r)V-{r)_yz`w1*xV0|lh-LQOP`OP`Pk1aW( z8DSlGN>Ts|n*xj+%If~+E_BxK)~5T#w6Q1WEKt{!Xtbd`J;`2a>8boRo;7u2M&iOop4qcy<)z023=oghSFV zST;?S;ye+dRQe>ygiJ6HCv4;~3DHtJ({fWeE~$H@mKn@Oh6Z(_sO>01JwH5oA4nvK zr5Sr^g+LC zLt(i&ecdmqsIJGNOSUyUpglvhhrY8lGkzO=0USEKNL%8zHshS>Qziu|`eyWP^5xL4 zRP122_dCJl>hZc~?58w~>`P_s18VoU|7(|Eit0-lZRgLTZKNq5{k zE?V=`7=R&ro(X%LTS*f+#H-mGo_j3dm@F_krAYegDLk6UV{`UKE;{YSsn$ z(yz{v1@p|p!0>g04!eRSrSVb>MQYPr8_MA|MpoGzqyd*$@4j|)cD_%^Hrd>SorF>@ zBX+V<@vEB5PRLGR(uP9&U&5=(HVc?6B58NJT_igiAH*q~Wb`dDZpJSKfy5#Aag4IX zj~uv74EQ_Q_1qaXWI!7Vf@ZrdUhZFE;L&P_Xr8l@GMkhc#=plV0+g(ki>+7fO%?Jb zl+bTy7q{w^pTb{>(Xf2q1BVdq?#f=!geqssXp z4pMu*q;iiHmA*IjOj4`4S&|8@gSw*^{|PT}Aw~}ZXU`6=vZB=GGeMm}V6W46|pU&58~P+?LUs%n@J}CSrICkeng6YJ^M? zS(W?K4nOtoBe4tvBXs@@`i?4G$S2W&;$z8VBSM;Mn9 zxcaEiQ9=vS|bIJ>*tf9AH~m&U%2+Dim<)E=}KORp+cZ^!@wI`h1NVBXu{@%hB2Cq(dXx_aQ9x3mr*fwL5!ZryQqi|KFJuzvP zK1)nrKZ7U+B{1ZmJub?4)Ln^J6k!i0t~VO#=q1{?T)%OV?MN}k5M{}vjyZu#M0_*u z8jwZKJ#Df~1jcLXZL7bnCEhB6IzQZ-GcoQJ!16I*39iazoVGugcKA{lhiHg4Ta2fD zk1Utyc5%QzZ$s3;p0N+N8VX{sd!~l*Ta3|t>lhI&G`sr6L~G5Lul`>m z{!^INm?J|&7X=;{XveF!(b*=?9NAp4y&r&N3(GKcW4rS(Ejk|Lzs1PrxPI_owB-`H zg3(Rruh^&)`TKA6+_!n>RdI6pw>Vt1_j&+bKIaMTYLiqhZ#y_=J8`TK{Jd<7l9&sY z^^`hmi7^14s16B6)1O;vJWOF$=$B5ONW;;2&|pUvJlmeUS&F;DbSHCrEb0QBDR|my zIs+pE0Y^`qJTyH-_mP=)Y+u^LHcuZhsM3+P||?+W#V!_6E-8boP#R-*na4!o-Q1 zVthtYhK{mDhF(&7Okzo9dTi03X(AE{8cH$JIg%MEQca`S zy@8{Fjft~~BdzWC(di#X{ny;!yYGK9b@=b|zcKZ{vv4D8i+`ilOPl;PJl{!&5-0!w z^fOl#|}vVg%=n)@_e1BrP)`A zKPgs`O0EO}Y2KWLuo`iGaKu1k#YR6BMySxQf2V++Wo{6EHmK>A~Q5o73yM z-RbxC7Qdh0Cz!nG+7BRZE>~FLI-?&W_rJUl-8FDIaXoNBL)@1hwKa^wOr1($*5h~T zF;%f^%<$p8Y_yu(JEg=c_O!aZ#)Gjh$n(hfJAp$C2he555W5zdrBqjFmo|VY+el;o z=*D_w|GXG|p0**hQ7~9-n|y5k%B}TAF0iarDM!q-jYbR^us(>&y;n^2l0C%@2B}KM zyeRT9)oMt97Agvc4sEKUEy%MpXr2vz*lb zh*L}}iG>-pqDRw7ud{=FvTD?}xjD)w{`KzjNom-$jS^;iw0+7nXSnt1R@G|VqoRhE%12nm+PH?9`(4rM0kfrZzIK9JU=^$YNyLvAIoxl#Q)xxDz!^0@zZ zSCs$nfcxK_vRYM34O<1}QHZ|hp4`ioX3x8(UV(FU$J@o%tw3t4k1QPmlEpZa2IujG&(roX_q*%e`Hq|);0;@k z0z=fZiFckp#JzW0p+2A+D$PC~IsakhJJkG(c;CqAgFfU0Z`u$PzG~-9I1oPHrCw&)@s^Dc~^)#HPW0Ra}J^=|h7Fs*<8|b13ZzG6MP*Q1dkoZ6&A^!}|hbjM{2HpqlSXv_UUg1U4gn z3Q)2VjU^ti1myodv+tjhSZp%D978m~p& z43uZUrraHs80Mq&vcetqfQpQP?m!CFj)44t8Z}k`E798wxg&~aCm+DBoI+nKq}&j^ zlPY3W$)K;KtEajks1`G?-@me7C>{PiiBu+41#yU_c(dITaqE?IQ(DBu+c^Ux!>pCj zLC|HJGU*v+!it1(;3e`6igkH(VA)-S+k(*yqxMgUah3$@C zz`7hEM47xr>j8^g`%*f=6S5n>z%Bt_Fg{Tvmr+MIsCx=0gsu_sF`q2hlkEmisz#Fy zj_0;zUWr;Gz}$BS%Y`meb(=$d%@Crs(OoJ|}m#<7=-A~PQbyN$x%2iXP2@e*nO0b7AwfH8cCUa*Wfu@b)D_>I*%uE4O3 z(lfnB`-Xf*LfC)E}e?%X2kK7DItK6Tf<+M^mX0Ijf_!IP>7c8IZX%8_#0060P{QMuV^B9i<^E`_Qf0pv9(P%_s8D`qvDE9LK9u-jB}J2S`(mCO&XHTS04Z5Ez*vl^T%!^$~EH8M-UdwhegL>3IQ*)(MtuH2Xt1p!fS4o~*rR?WLxlA!sjc2(O znjJn~wQ!Fp9s2e^IWP1C<4%sFF}T4omr}7+4asciyo3DntTgWIzhQpQirM$9{EbQd z3jz9vS@{aOqTQHI|l#aUV@2Q^Wko4T0T04Me4!2nsdrA8QY1%fnAYb~d2GDz@lAtfcHq(P7 zaMBAGo}+NcE-K*@9y;Vt3*(aCaMKXBB*BJcD_Qnxpt75r?GeAQ}*|>pYJE=uZb73 zC>sv)18)q#EGrTG6io*}JLuB_jP3AU1Uiu$D7r|2_zlIGb9 zjhst#ni)Y`$)!fc#reM*$~iaYoz~_Cy7J3ZTiPm)E?%`fbk`3Tu-F#`{i!l5pNEn5 zO-Tw-=TojYhzT{J=?SZj=Z8#|eoF>434b-DXiUsignxXNaR3 zm_}4iWU$gt2Mw5NvZ5(VpF`?X*f2UZDs1TEa1oZCif?Jdgr{>O~7}-$|BZ7I(IKW`{f;@|IZFX*R8&iT= zoWstN8&R;}@2Ka%d3vrLtR|O??ben;k8QbS-WB0VgiCz;<$pBmIZdN!aalyCSEm)crpS9dcD^Y@XT1a3+zpi-`D}e#HV<} z$Y(G&o~PvL-xSVD5D?JqF3?B9rxGWeb=oEGJ3vRp5xfBPlngh1O$yI95EL+T8{GC@ z98i1H9KhZGFl|;`)_=QpM6H?eDPpw~^(aFQWwyXZ8_EEE4#@QeT_URray*mEOGsGc z6|sdXtq!hVZo=d#+9^@lm&L5|q&-GDCyUx#YQiccq;spOBe3V+VKdjJA=IL=Zn%P} zNk=_8u}VhzFf{UYZV0`lUwcD&)9AFx0@Fc6LD9A6Rd1=ga>Mi0)_QxM2ddCVRmZ0d z+J=uXc(?5JLX3=)e)Jm$HS2yF`44IKhwRnm2*669_J=2LlwuF5$1tAo@ROSU@-y+;Foy2IEl2^V1N;fk~YR z?&EP8#t&m0B=?aJeuz~lHjAzRBX>&x=A;gIvb>MD{XEV zV%l-+9N-)i;YH%nKP?>f`=?#`>B(`*t`aiPLoQM(a6(qs4p5KFjDBN?8JGrf3z8>= zi7sD)c)Nm~x{e<^jy4nTx${P~cwz_*a>%0_;ULou3kHCAD7EYkw@l$8TN#LO9jC( z1BeFW`k+bu5e8Ns^a8dPcjEVHM;r6UX+cN=Uy7HU)j-myRU0wHd$A1fNI~`4;I~`zC)3ul#8#^rXVSO*m}Ag>c%_;nj=Nv$rCZ z*~L@C@OZg%Q^m)lc-kcX&a*a5`y&DaRxh6O*dfhLfF+fU5wKs(1v*!TkZidw*)YBP za@r`3+^IHRFeO%!ai%rxy;R;;V^Fr=OJlpBX;(b*3+SIw}7= zIq$*Thr(Zft-RlY)D3e8V;BmD&HOfX+E$H#Y@B3?UL5L~_fA-@*IB-!gItK7PIgG9 zgWuGZK_nuZjHVT_Fv(XxtU%)58;W39vzTI2n&)&4Dmq7&JX6G>XFaAR{7_3QB6zsT z?$L8c*WdN~nZGiscY%5KljQARN;`w$gho=p006z;n(qIQ*Zu<``TMO3n0{ARL@gYh zoRwS*|Niw~cR!?hE{m*y@F`1)vx-JRfqET=dJ5_(076st(=lFfjtKHoYg`k3oNmo_ zNbQEw8&sO5jAYmkD|Zaz_yUb0rC})U!rCHOl}JhbYIDLzLvrZVw0~JO`d*6f;X&?V=#T@ND*cv^I;`sFeq4 z##H5;gpZTb^0Hz@3C*~u0AqqNZ-r%rN3KD~%Gw`0XsIq$(^MEb<~H(2*5G^<2(*aI z%7}WB+TRlMIrEK#s0 z93xn*Ohb=kWFc)BNHG4I(~RPn-R8#0lqyBBz5OM6o5|>x9LK@%HaM}}Y5goCQRt2C z{j*2TtT4ne!Z}vh89mjwiSXG=%DURar~=kGNNaO_+Nkb+tRi~Rkf!7a$*QlavziD( z83s4GmQ^Wf*0Bd04f#0HX@ua_d8 z23~z*53ePD6@xwZ(vdl0DLc=>cPIOPOdca&MyR^jhhKrdQO?_jJh`xV3GKz&2lvP8 zEOwW6L*ufvK;TN{=S&R@pzV^U=QNk^Ec}5H z+2~JvEVA{`uMAr)?Kf|aW>33`)UL@bnfIUQc~L;TsTQ6>r-<^rB8uoNOJ>HWgqMI8 zSW}pZmp_;z_2O5_RD|fGyTxaxk53Hg_3Khc<8AUzV|ZeK{fp|Ne933=1&_^Dbv5^u zB9n=*)k*tjHDRJ@$bp9mrh}qFn*s}npMl5BMDC%Hs0M0g-hW~P*3CNG06G!MOPEQ_ zi}Qs-6M8aMt;sL$vlmVBR^+Ry<64jrm1EI1%#j?c?4b*7>)a{aDw#TfTYKq+SjEFA z(aJ&z_0?0JB83D-i3Vh+o|XV4UP+YJ$9Boid2^M2en@APw&wx7vU~t$r2V`F|7Qfo z>WKgI@eNBZ-+Og<{u2ZiG%>YvH2L3fNpV9J;WLJoBZda)01Rn;o@){01{7E#ke(7U zHK>S#qZ(N=aoae*4X!0A{)nu0R_sKpi1{)u>GVjC+b5Jyl6#AoQ-1_3UDovNSo`T> z?c-@7XX*2GMy?k?{g)7?Sv;SJkmxYPJPs!&QqB12ejq`Lee^-cDveVWL^CTUldb(G zjDGe(O4P=S{4fF=#~oAu>LG>wrU^z_?3yt24FOx>}{^lCGh8?vtvY$^hbZ)9I0E3r3NOlb9I?F-Yc=r$*~l`4N^xzlV~N zl~#oc>U)Yjl0BxV>O*Kr@lKT{Z09OXt2GlvE38nfs+DD7exl|&vT;)>VFXJVZp9Np zDK}aO;R3~ag$X*|hRVY3OPax|PG`@_ESc8E!mHRByJbZQRS38V2F__7MW~sgh!a>98Q2%lUNFO=^xU52|?D=IK#QjwBky-C>zOWlsiiM&1n z;!&1((Xn1$9K}xabq~222gYvx3hnZPg}VMF_GV~5ocE=-v>V=T&RsLBo&`)DOyIj* zLV{h)JU_y*7SdRtDajP_Y+rBkNN*1_TXiKwHH2&p51d(#zv~s#HwbNy?<+(=9WBvo zw2hkk2Dj%kTFhY+$T+W-b7@qD!bkfN#Z2ng@Pd=i3-i?xYfs5Z*1hO?kd7Sp^9`;Y zM2jeGg<-nJD1er@Pc_cSY7wo5dzQX44=%6rn}P_SRbpzsA{6B+!$3B0#;}qwO37G^ zL(V_5JK`XT?OHVk|{_$vQ|oNEpab*BO4F zUTNQ7RUhnRsU`TK#~`)$icsvKh~(pl=3p6m98@k3P#~upd=k*u20SNcb{l^1rUa)>qO997)pYRWMncC8A&&MHlbW?7i^7M`+B$hH~Y|J zd>FYOGQ;j>Zc2e7R{KK7)0>>nn_jYJy&o@sK!4G>-rLKM8Hv)f;hi1D2fAc$+six2 zyVZ@wZ6x|fJ!4KrpCJY=!Mq0;)X)OoS~{Lkh6u8J`eK%u0WtKh6B>GW_)PVc zl}-k`p09qwGtZ@VbYJC!>29V?Dr>>vk?)o(x?!z*9DJ||9qG-&G~#kXxbw{KKYy}J zQKa-dPt~M~E}V?PhW0R26xdA%1T*%ra6SguGu50YHngOTIv)@N|YttEXo#OZfgtP7;H?EeZZxo<}3YlYxtBq znJ!WFR^tmGf0Py}N?kZ(#=VtpC@%xJkDmfcCoBTxq zr_|5gP?u1@vJZbxPZ|G0AW4=tpb84gM2DpJU||(b8kMOV1S3|(yuwZJ&rIiFW(U;5 zUtAW`O6F6Zy+eZ1EDuP~AAHlSY-+A_eI5Gx)%*uro5tljy}kCZU*_d7)oJ>oQSZ3* zneTn`{gnNC&uJd)0aMBzAg021?YJ~b(fmkwZAd696a=0NzBAqBN54KuNDwa*no(^O z6p05bioXUR^uXjpTol*ppHp%1v9e)vkoUAUJyBx3lw0UO39b0?^{}yb!$yca(@DUn zCquRF?t=Zb9`Ed3AI6|L{eX~ijVH`VzSMheKoP7LSSf4g>md>`yi!TkoG5P>Ofp+n z(v~rW+(5L96L{vBb^g51B=(o)?%%xhvT*A5btOpw(TKh^g^4c zw>0%X!_0`{iN%RbVk+A^f{w-4-SSf*fu@FhruNL##F~sF24O~u zyYF<3el2b$$wZ_|uW#@Ak+VAGk#e|kS8nL1g>2B-SNMjMp^8;-FfeofY2fphFHO!{ z*!o4oTb{4e;S<|JEs<1_hPsmAlVNk?_5-Fp5KKU&d#FiNW~Y+pVFk@Cua1I{T+1|+ zHx6rFMor)7L)krbilqsWwy@T+g3DiH5MyVf8Wy}XbEaoFIDr~y;@r&I>FMW{ z?Q+(IgyebZ)-i4jNoXQhq4Muy9Fv+OxU;9_Jmn+<`mEC#%2Q_2bpcgzcinygNI!&^ z=V$)o2&Yz04~+&pPWWn`rrWxJ&}8khR)6B(--!9Q zubo}h+1T)>a@c)H^i``@<^j?|r4*{;tQf78(xn0g39IoZw0(CwY1f<%F>kEaJ zp9u|IeMY5mRdAlw*+gSN^5$Q)ShM<~E=(c8QM+T-Qk)FyKz#Sw0EJ*edYcuOtO#~Cx^(M7w5 z3)rl#L)rF|(Vun2LkFr!rg8Q@=r>9p>(t3Gf_auiJ2Xx9HmxYTa|=MH_SUlYL`mz9 zTTS$`%;D-|Jt}AP1&k7PcnfFNTH0A-*FmxstjBDiZX?}%u%Yq94$fUT&z6od+(Uk> zuqsld#G(b$G8tus=M!N#oPd|PVFX)?M?tCD0tS%2IGTfh}3YA3f&UM)W$_GNV8 zQo+a(ml2Km4o6O%gKTCSDNq+#zCTIQ1*`TIJh~k6Gp;htHBFnne))rlFdGqwC6dx2+La1&Mnko*352k0y z+tQcwndQlX`nc6nb$A9?<-o|r*%aWXV#=6PQic0Ok_D;q>wbv&j7cKc!w4~KF#-{6 z(S%6Za)WpGIWf7jZ3svNG5OLs0>vCL9{V7cgO%zevIVMH{WgP*^D9ws&OqA{yr|m| zKD4*07dGXshJHd#e%x%J+qmS^lS|0Bp?{drv;{@{l9ArPO&?Q5=?OO9=}h$oVe#3b z3Yofj&Cb}WC$PxmRRS)H%&$1-)z7jELS}!u!zQ?A^Y{Tv4QVt*vd@uj-^t2fYRzQj zfxGR>-q|o$3sGn^#VzZ!QQx?h9`njeJry}@x?|k0-GTTA4y3t2E`3DZ!A~D?GiJup z)8%PK2^9OVRlP(24P^4_<|D=H^7}WlWu#LgsdHzB%cPy|f8dD3|A^mh4WXxhLTVu_ z@abE{6Saz|Y{rXYPd4$tfPYo}ef(oQWZ=4Bct-=_9`#Qgp4ma$n$`tOwq#&E18$B; z@Bp)bn3&rEi0>fWWZ@7k5WazfoX`SCO4jQWwVuo+$PmSZn^Hz?O(-tW@*DGxuf)V1 zO_xm&;NVCaHD4dqt(-MlszI3F-p?0!-e$fbiCeuaw66h^TTDLWuaV<@C-`=Xe5WL) zwooG7h>4&*)p3pKMS3O!4>-4jQUN}iAMQ)2*70?hP~)TzzR?-f@?Aqy$$1Iy8VGG$ zMM?8;j!pUX7QQD$gRc_#+=raAS577ga-w?jd`vCiN5lu)dEUkkUPl9!?{$IJNxQys z*E4e$eF&n&+AMRQR2gcaFEjAy*r)G!s(P6D&TfoApMFC_*Ftx0|D0@E-=B7tezU@d zZ{hGiN;YLIoSeRS;9o%dEua4b%4R3;$SugDjP$x;Z!M!@QibuSBb)HY!3zJ7M;^jw zlx6AD50FD&p3JyP*>o+t9YWW8(7P2t!VQQ21pHJOcG_SXQD;(5aX#M6x##5H_Re>6lPyDCjxr*R(+HE%c&QN+b^tbT zXBJk?p)zhJj#I?&Y2n&~XiytG9!1ox;bw5Rbj~)7c(MFBb4>IiRATdhg zmiEFlj@S_hwYYI(ki{}&<;_7(Z0Qkfq>am z&LtL=2qc7rWguk3BtE4zL41@#S;NN*-jWw|7Kx7H7~_%7fPt;TIX}Ubo>;Rmj94V> zNB1=;-9AR7s`Pxn}t_6^3ahlq53e&!Lh85uG zec0vJY_6e`tg7LgfrJ3k!DjR)Bi#L@DHIrZ`sK=<5O0Ip!fxGf*OgGSpP@Hbbe&$9 z;ZI}8lEoC2_7;%L2=w?tb%1oL0V+=Z`7b=P&lNGY;yVBazXRYu;+cQDKvm*7NCxu&i;zub zAJh#11%?w>E2rf2e~C4+rAb-&$^vsdACs7 z@|Ra!OfVM(ke{vyiqh7puf&Yp6cd6{DptUteYfIRWG3pI+5< zBVBI_xkBAc<(pcb$!Y%dTW(b;B;2pOI-(QCsLv@U-D1XJ z(Gk8Q3l7Ws46Aktuj>|s{$6zA&xCPuXL-kB`CgYMs}4IeyG*P51IDwW?8UNQd+$i~ zlxOPtSi5L|gJcF@DwmJA5Ju8HEJ>o{{upwIpb!f{2(vLNBw`7xMbvcw<^{Fj@E~1( z?w`iIMieunS#>nXlmUcSMU+D3rX28f?s7z;X=se6bo8;5vM|O^(D6{A9*ChnGH!RG zP##3>LDC3jZPE4PH32AxrqPk|yIIrq~`aL-=}`okhNu9aT%q z1b)7iJ)CN=V#Ly84N_r7U^SH2FGdE5FpTO2 z630TF$P>GNMu8`rOytb(lB2};`;P4YNwW1<5d3Q~AX#P0aX}R2b2)`rgkp#zTxcGj zAV^cvFbhP|JgWrq_e`~exr~sIR$6p5V?o4Wym3kQ3HA+;Pr$bQ0(PmADVO%MKL!^q z?zAM8j1l4jrq|5X+V!8S*2Wl@=7*pPgciTVK6kS1Ge zMsd_u6DFK$jTnvVtE;qa+8(1sGBu~n&F%dh(&c(Zs4Fc#A=gG^^%^AyH}1^?|8quj zl@Z47h$){PlELJgYZCIHHL= z{U8O>Tw4x3<1{?$8>k-P<}1y9DmAZP_;(3Y*{Sk^H^A=_iSJ@+s5ktgwTXz_2$~W9>VVZsfwCm@s0sQ zeB50_yu@uS+e7QoPvdCwDz{prjo(AFwR%C?z`EL{1`|coJHQTk^nX=tvs1<0arUOJ z!^`*x&&BvTYmemyZ)2p~{%eYX=JVR?DYr(rNgqRMA5E1PR1Iw=prk=L2ldy3r3Vg@27IZx43+ywyzr-X*p*d@tZV+!U#~$-q=8c zgdSuh#r?b4GhEGNai)ayHQpk>5(%j5c@C1K3(W1pb~HeHpaqijJZa-e6vq_8t-^M^ zBJxq|MqZc?pjXPIH}70a5vt!IUh;l}<>VX<-Qcv^u@5(@@M2CHSe_hD$VG-eiV^V( zj7*9T0?di?P$FaD6oo?)<)QT>Npf6Og!GO^GmPV(Km0!=+dE&bk#SNI+C9RGQ|{~O*VC+tXK3!n`5 zHfl6>lwf_aEVV3`0T!aHNZLsj$paS$=LL(?b!Czaa5bbSuZ6#$_@LK<(7yrrl+80| z{tOFd=|ta2Z`^ssozD9BINn45NxUeCQis?-BKmU*Kt=FY-NJ+)8S1ecuFtN-M?&42 zl2$G>u!iNhAk*HoJ^4v^9#ORYp5t^wDj6|lx~5w45#E5wVqI1JQ~9l?nPp1YINf++ zMAdSif~_ETv@Er(EFBI^@L4BULFW>)NI+ejHFP*T}UhWNN`I)RRS8za? z*@`1>9ZB}An%aT5K=_2iQmfE;GcBVHLF!$`I99o5GO`O%O_zLr9AG18>&^HkG(;=V z%}c!OBQ~?MX(9h~tajX{=x)+!cbM7$YzTlmsPOdp2L-?GoW`@{lY9U3f;OUo*BwRB z8A+nv(br0-SH#VxGy#ZrgnGD(=@;HME;yd46EgWJ`EL%oXc&lFpc@Y}^>G(W>h_v_ zlN!`idhX+OjL+~T?19sroAFVGfa5tX-D49w$1g2g_-T|EpHL6}K_aX4$K=LTvwtlF zL*z}j{f+Uoe7{-px3_5iKPA<_7W=>Izkk)!l9ez2w%vi(?Y;i8AxRNLSOGDzNoqoI zP!1uAl}r=_871(G?y`i&)-7{u=%nxk7CZ_Qh#!|ITec zwQn`33GTUM`;D2POWnkqngqJhJRlM>CTONzTG}>^Q0wUunQyn|TAiHzyX2_%ATx%P z%7gW)%4rA9^)M<_%k@`Y?RbC<29sWU&5;@|9thf2#zf8z12$hRcZ!CSb>kUp=4N#y zl3hE#y6>kkA8VY2`W`g5Ip?2qC_BY$>R`iGQLhz2-S>x(RuWv)SPaGdl^)gGw7tjR zH@;jwk!jIaCgSg_*9iF|a);sRUTq30(8I(obh^|}S~}P4U^BIGYqcz;MPpC~Y@k_m zaw4WG1_vz2GdCAX!$_a%GHK**@IrHSkGoN>)e}>yzUTm52on`hYot7cB=oA-h1u|R ztH$11t?54Qg2L+i33FPFKKRm1aOjKST{l1*(nps`>sv%VqeVMWjl5+Gh+9);hIP8? zA@$?}Sc z3qIRpba+y5yf{R6G(u8Z^vkg0Fu&D-7?1s=QZU`Ub{-!Y`I?AGf1VNuc^L3v>)>i# z{DV9W$)>34wnzAXUiV^ZpYKw>UElrN_5Xj6{r_3| z$X5PK`e5$7>~9Dj7gK5ash(dvs`vwfk}&RD`>04;j62zoXESkFBklYaKm5seyiX(P zqQ-;XxlV*yg?Dhlx%xt!b0N3GHp@(p$A;8|%# zZ5m2KL|{on4nr>2_s9Yh=r5ScQ0;aMF)G$-9-Ca6%wA`Pa)i?NGFA|#Yi?{X-4ZO_ z^}%7%vkzvUHa$-^Y#aA+aiR5sa%S|Ebyn`EV<3Pc?ax_f>@sBZF1S;7y$CXd5t5=WGsTKBk8$OfH4v|0?0I=Yp}7c=WBSCg!{0n)XmiU;lfx)**zZaYqmDJelxk$)nZyx5`x$6R|fz(;u zEje5Dtm|a%zK!!tk3{i9$I2b{vXNFy%Bf{50X!x{98+BsDr_u9i>G5%*sqEX|06J0 z^IY{UcEbj6LDwuMh7cH`H@9sVt1l1#8kEQ(LyT@&+K}(ReE`ux8gb0r6L_#bDUo^P z3Ka2lRo52Hdtl_%+pwVs14=q`{d^L58PsU@AMf(hENumaxM{7iAT5sYmWh@hQCO^ zK&}ijo=`VqZ#a3vE?`7QW0ZREL17ZvDfdqKGD?0D4fg{7v%|Yj&_jcKJAB)>=*RS* zto8p6@k%;&^ZF>hvXm&$PCuEp{uqw3VPG$9VMdW5$w-fy2CNNT>E;>ejBgy-m_6`& z97L1p{%srn@O_JQgFpa_#f(_)eb#YS>o>q3(*uB;uZb605(iqM$=NK{nHY=+X2*G) zO3-_Xh%aG}fHWe*==58zBwp%&`mge<8uq8;xIxOd=P%9EK!34^E9sk|(Zq1QSz-JVeP12Fp)-`F|KY$LPwUE?rku zY@OJ)Z9A!ojfzfeyJ9;zv2EM7ZQB)AR5xGa-tMn^bl)FmoIiVyJ@!~@%{}qXXD&Ns zPnfe5U+&ohKefILu_1mPfLGuapX@btta5C#gPB2cjk5m4T}Nfi+Vfka!Yd(L?-c~5 z#ZK4VeQEXNPc4r$K00Fg>g#_W!YZ)cJ?JTS<&68_$#cZT-ME`}tcwqg3#``3M3UPvn+pi}(VNNx6y zFIMVb6OwYU(2`at$gHba*qrMVUl8xk5z-z~fb@Q3Y_+aXuEKH}L+>eW__!IAd@V}L zkw#s%H0v2k5-=vh$^vPCuAi22Luu3uKTf6fPo?*nvj$9(u)4$6tvF-%IM+3pt*cgs z_?wW}J7VAA{_~!?))?s6{M=KPpVhg4fNuU*|3THp@_(q!b*hdl{fjRVFWtu^1dV(f z6iOux9hi&+UK=|%M*~|aqFK{Urfl!TA}UWY#`w(0P!KMe1Si{8|o))Gy6d7;!JQYhgMYmXl?3FfOM2nQGN@~Ap6(G z3+d_5y@=nkpKAhRqf{qQ~k7Z$v&l&@m7Ppt#FSNzKPZM z8LhihcE6i=<(#87E|Wr~HKvVWhkll4iSK$^mUHaxgy8*K$_Zj;zJ`L$naPj+^3zTi z-3NTaaKnD5FPY-~?Tq6QHnmDDRxu0mh0D|zD~Y=vv_qig5r-cIbCpxlju&8Sya)@{ zsmv6XUSi)@(?PvItkiZEeN*)AE~I_?#+Ja-r8$(XiXei2d@Hi7Rx8+rZZb?ZLa{;@*EHeRQ-YDadz~M*YCM4&F-r;E#M+@CSJMJ0oU|PQ^ z=E!HBJDMQ2TN*Y(Ag(ynAL8%^v;=~q?s4plA_hig&5Z0x_^Oab!T)@6kRN$)qEJ6E zNuQjg|G7iwU(N8pI@_6==0CL;lRh1dQF#wePhmu@hADFd3B5KIH#dx(2A zp~K&;Xw}F_N6CU~0)QpQk7s$a+LcTOj1%=WXI(U=Dv!6 z{#<#-)2+gCyyv=Jw?Ab#PVkxPDeH|sAxyG`|Ys}A$PW4TdBv%zDz z^?lwrxWR<%Vzc8Sgt|?FL6ej_*e&rhqJZ3Y>k=X(^dytycR;XDU16}Pc9Vn0>_@H+ zQ;a`GSMEG64=JRAOg%~L)x*w{2re6DVprNp+FcNra4VdNjiaF0M^*>CdPkt(m150rCue?FVdL0nFL$V%5y6N z%eLr5%YN7D06k5ji5*p4v$UMM)G??Q%RB27IvH7vYr_^3>1D-M66#MN8tWGw>WED} z5AhlsanO=STFYFs)Il_0i)l)f<8qn|$DW7ZXhf5xI;m+7M5-%P63XFQrG9>DMqHc} zsgNU9nR`b}E^mL5=@7<1_R~j@q_2U^3h|+`7YH-?C=vme1C3m`Fe0HC>pjt6f_XMh zy~-i-8R46QNYneL4t@)<0VU7({aUO?aH`z4V2+kxgH5pYD5)wCh75JqQY)jIPN=U6 z+qi8cGiOtXG2tXm;_CfpH9ESCz#i5B(42}rBJJF$jh<1sbpj^8&L;gzGHb8M{of+} zzF^8VgML2O9nxBW7AvdEt90vp+#kZxWf@A)o9f9}vKJy9NDBjBW zSt=Hcs=YWCwnfY1UYx*+msp{g!w0HC<_SM!VL1(I2PE?CS}r(eh?{I)mQixmo5^p# zV?2R!R@3GV6hwTCrfHiK#3Orj>I!GS2kYhk1S;aFBD_}u2v;0HYFq}Iz1Z(I4oca4 zxquja8$+8JW_EagDHf$a1OTk5S97umGSDaj)gH=fLs9>_=XvVj^Xj9a#gLdk=&3tl zfmK9MNnIX9v{?%xdw7568 zNrZ|roYs(vC4pHB5RJ8>)^*OuyNC>x7ad)tB_}3SgQ96+-JT^Qi<`xi=)_=$Skwv~ zdqeT9Pa`LYvCAn&rMa2aCDV(TMI#PA5g#RtV|CWpgDYRA^|55LLN^uNh*gOU>Z=a06qJ;$C9z8;n-Pq=qZnc1zUwJ@t)L;&NN+E5m zRkQ(SeM8=l-aoAKGKD>!@?mWTW&~)uF2PYUJ;tB^my`r9n|Ly~0c%diYzqs9W#FTjy?h&X3TnH zXqA{QI82sdjPO->f=^K^f>N`+B`q9&rN0bOXO79S&a9XX8zund(kW7O76f4dcWhIu zER`XSMSFbSL>b;Rp#`CuGJ&p$s~G|76){d?xSA5wVg##_O0DrmyEYppyBr%fyWbbv zp`K84JwRNP$d-pJ!Qk|(RMr?*!wi1if-9G#0p>>1QXKXWFy)eB3ai)l3601q8!9JC zvU#ZWWDNKq9g6fYs?JQ)Q4C_cgTy3FhgKb8s&m)DdmL5zhNK#8wWg!J*7G7Qhe9VU zha?^AQTDpYcuN!B+#1dE*X{<#!M%zfUQbj=zLE{dW0XeQ7-oIsGY6RbkP2re@Q{}r_$iiH0xU%iN*ST`A)-EH6eaZB$GA#v)cLi z*MpA(3bYk$oBDKAzu^kJoSUsDd|856DApz={3u8sbQV@JnRkp2nC|)m;#T=DvIL-O zI4vh;g7824l}*`_p@MT4+d`JZ2%6NQh=N9bmgJ#q!hK@_<`HQq3}Z8Ij>3%~<*= zcv=!oT#5xmeGI92lqm9sGVE%#X$ls;St|F#u!?5Y7syhx6q#MVRa&lBmmn%$C0QzU z);*ldgwwCmzM3uglr}!Z2G+?& zf%Dpo&mD%2ZcNFiN-Z0f;c_Q;A%f@>26f?{d1kxIJD}LxsQkB47SAdwinfMILZdN3 zfj^HmTzS3Ku5BxY>ANutS8WPQ-G>v4^_Qndy==P3pDm+Xc?>rUHl-4+^%Sp5atOja z2oP}ftw-rqnb}+khR3CrRg^ibi6?QYk1*i^;kQGirQ=uB9Sd1NTfT-Rbv;hqnY4neE5H1YUrjS2m+2&@uXiAo- zrKUX|Ohg7(6F(AoP~tj;NZlV#xsfo-5reuQHB$&EIAhyZk;bL;k9ouDmJNBAun;H& zn;Of1z_Qj`x&M;5X;{s~iGzBQTY^kv-k{ksbE*Dl%Qf%N@hQCfY~iUw!=F-*$cpf2 z3wix|aLBV0b;W@z^%7S{>9Z^T^fLOI68_;l@+Qzaxo`nAI8emTV@rRhEKZ z?*z_{oGdI~R*#<2{bkz$G~^Qef}$*4OYTgtL$e9q!FY7EqxJ2`zk6SQc}M(k(_MaV zSLJnTXw&@djco1~a(vhBl^&w=$fa9{Sru>7g8SHahv$&Bl(D@(Zwxo_3r=;VH|uc5 zi1Ny)J!<(KN-EcQ(xlw%PNwK8U>4$9nVOhj(y0l9X^vP1TA>r_7WtSExIOsz`nDOP zs}d>Vxb2Vo2e5x8p(n~Y5ggAyvib>d)6?)|E@{FIz?G3PVGLf7-;BxaP;c?7ddH$z zA+{~k^V=bZuXafOv!RPsE1GrR3J2TH9uB=Z67gok+u`V#}BR86hB1xl}H4v`F+mRfr zYhortD%@IGfh!JB(NUNSDh+qDz?4ztEgCz&bIG-Wg7w-ua4ChgQR_c+z8dT3<1?uX z*G(DKy_LTl*Ea!%v!RhpCXW1WJO6F`bgS-SB;Xw9#! z<*K}=#wVu9$`Yo|e!z-CPYH!nj7s9dEPr-E`DXUBu0n!xX~&|%#G=BeM?X@shQQMf zMvr2!y7p_gD5-!Lnm|a@z8Of^EKboZsTMk%5VsJEm>VsJ4W7Kv{<|#4f-qDE$D-W>gWT%z-!qXnDHhOvLk=?^a1*|0j z{pW{M0{#1VcR5;F!!fIlLVNh_Gj zbnW(_j?0c2q$EHIi@fSMR{OUKBcLr{Y&$hrM8XhPByyZaXy|dd&{hYQRJ9@Fn%h3p7*VQolBIV@Eq`=y%5BU~3RPa^$a?ixp^cCg z+}Q*X+CW9~TL29@OOng(#OAOd!)e$d%sr}^KBJ-?-X&|4HTmtemxmp?cT3uA?md4% zT8yZ0U;6Rg6JHy3fJae{6TMGS?ZUX6+gGTT{Q{)SI85$5FD{g-eR%O0KMpWPY`4@O zx!hen1*8^E(*}{m^V_?}(b5k3hYo=T+$&M32+B`}81~KKZhY;2H{7O-M@vbCzuX0n zW-&HXeyr1%I3$@ns-V1~Lb@wIpkmx|8I~ob1Of7i6BTNysEwI}=!nU%q7(V_^+d*G z7G;07m(CRTJup!`cdYi93r^+LY+`M*>aMuHJm(A8_O8C#A*$!Xvddgpjx5)?_EB*q zgE8o5O>e~9IiSC@WtZpF{4Bj2J5eZ>uUzY%TgWF7wdDE!fSQIAWCP)V{;HsU3ap?4 znRsiiDbtN7i9hapO;(|Ew>Ip2TZSvK9Z^N21%J?OiA_&eP1{(Pu_=%JjKy|HOardq ze?zK^K zA%sjF64*Wufad%H<) z^|t>e*h+Z1#l=5wHexzt9HNDNXgM=-OPWKd^5p!~%SIl>Fo&7BvNpbf8{NXmH)o{r zO=aBJ;meX1^{O%q;kqdw*5k!Y7%t_30 zy{nGRVc&5qt?dBwLs+^Sfp;f`YVMSB#C>z^a9@fpZ!xb|b-JEz1LBX7ci)V@W+kvQ89KWA0T~Lj$aCcfW#nD5bt&Y_< z-q{4ZXDqVg?|0o)j1%l0^_it0WF*LCn-+)c!2y5yS7aZIN$>0LqNnkujV*YVes(v$ zY@_-!Q;!ZyJ}Bg|G-~w@or&u0RO?vlt5*9~yeoPV_UWrO2J54b4#{D(D>jF(R88u2 zo#B^@iF_%S>{iXSol8jpmsZuJ?+;epg>k=$d`?GSegAVp3n$`GVDvK${N*#L_1`44 z{w0fL{2%)0|E+qgZtjX}itZz^KJt4Y;*8uSK}Ft38+3>j|K(PxIXXR-t4VopXo#9# zt|F{LWr-?34y`$nLBVV_*UEgA6AUI65dYIbqpNq9cl&uLJ0~L}<=ESlOm?Y-S@L*d z<7vt}`)TW#f%Rp$Q}6@3=j$7Tze@_uZO@aMn<|si{?S}~maII`VTjs&?}jQ4_cut9$)PEqMukwoXobzaKx^MV z2fQwl+;LSZ$qy%Tys0oo^K=jOw$!YwCv^ei4NBVauL)tN%=wz9M{uf{IB(BxK|lT*pFkmNK_1tV`nb%jH=a0~VNq2RCKY(rG7jz!-D^k)Ec)yS%17pE#o6&eY+ z^qN(hQT$}5F(=4lgNQhlxj?nB4N6ntUY6(?+R#B?W3hY_a*)hnr4PA|vJ<6p`K3Z5Hy z{{8(|ux~NLUW=!?9Qe&WXMTAkQnLXg(g=I@(VG3{HE13OaUT|DljyWXPs2FE@?`iU z4GQlM&Q=T<4&v@Fe<+TuXiZQT3G~vZ&^POfmI1K2h6t4eD}Gk5XFGpbj1n_g*{qmD6Xy z`6Vv|lLZtLmrnv*{Q%xxtcWVj3K4M%$bdBk_a&ar{{GWyu#ljM;dII;*jP;QH z#+^o-A4np{@|Mz+LphTD0`FTyxYq#wY)*&Ls5o{0z9yg2K+K7ZN>j1>N&;r+Z`vI| zDzG1LJZ+sE?m?>x{5LJx^)g&pGEpY=fQ-4}{x=ru;}FL$inHemOg%|R*ZXPodU}Kh zFEd5#+8rGq$Y<_?k-}r5zgQ3jRV=ooHiF|@z_#D4pKVEmn5CGV(9VKCyG|sT9nc=U zEoT67R`C->KY8Wp-fEcjjFm^;Cg(ls|*ABVHq8clBE(;~K^b+S>6uj70g? z&{XQ5U&!Z$SO7zfP+y^8XBbiu*Cv-yJG|l-oe*!s5$@Lh_KpxYL2sx`B|V=dETN>5K+C+CU~a_3cI8{vbu$TNVdGf15*>D zz@f{zIlorkY>TRh7mKuAlN9A0>N>SV`X)+bEHms=mfYTMWt_AJtz_h+JMmrgH?mZt zm=lfdF`t^J*XLg7v+iS)XZROygK=CS@CvUaJo&w2W!Wb@aa?~Drtf`JV^cCMjngVZ zv&xaIBEo8EYWuML+vxCpjjY^s1-ahXJzAV6hTw%ZIy!FjI}aJ+{rE&u#>rs)vzuxz z+$5z=7W?zH2>Eb32dvgHYZtCAf!=OLY-pb4>Ae79rd68E2LkVPj-|jFeyqtBCCwiW zkB@kO_(3wFq)7qwV}bA=zD!*@UhT`geq}ITo%@O(Z5Y80nEX~;0-8kO{oB6|(4fQh z);73T!>3@{ZobPwRv*W?7m0Ml9GmJBCJd&6E?hdj9lV= z4flNfsc(J*DyPv?RCOx!MSvk(M952PJ-G|JeVxWVjN~SNS6n-_Ge3Q;TGE;EQvZg86%wZ`MB zSMQua(i*R8a75!6$QRO^(o7sGoomb+Y{OMy;m~Oa`;P9Yqo>?bJAhqXxLr7_3g_n>f#UVtxG!^F#1+y@os6x(sg z^28bsQ@8rw%Gxk-stAEPRbv^}5sLe=VMbkc@Jjimqjvmd!3E7+QnL>|(^3!R} zD-l1l7*Amu@j+PWLGHXXaFG0Ct2Q=}5YNUxEQHCAU7gA$sSC<5OGylNnQUa>>l%sM zyu}z6i&({U@x^hln**o6r2s-(C-L50tQvz|zHTqW!ir?w&V23tuYEDJVV#5pE|OJu z7^R!A$iM$YCe?8n67l*J-okwfZ+ZTkGvZ)tVPfR;|3gyFjF)8V zyXXN=!*bpyRg9#~Bg1+UDYCt0 ztp4&?t1X0q>uz;ann$OrZs{5*r`(oNvw=$7O#rD|Wuv*wIi)4b zGtq4%BX+kkagv3F9Id6~-c+1&?zny%w5j&nk9SQfo0k4LhdSU_kWGW7axkfpgR`8* z!?UTG*Zi_baA1^0eda8S|@&F z{)Rad0kiLjB|=}XFJhD(S3ssKlveFFmkN{Vl^_nb!o5M!RC=m)V&v2%e?ZoRC@h3> zJ(?pvToFd`*Zc@HFPL#=otWKwtuuQ_dT-Hr{S%pQX<6dqVJ8;f(o)4~VM_kEQkMR+ zs1SCVi~k>M`u1u2xc}>#D!V&6nOOh-E$O&SzYrjJdZpaDv1!R-QGA141WjQe2s0J~ zQ;AXG)F+K#K8_5HVqRoRM%^EduqOnS(j2)|ctA6Q^=|s_WJYU;Z%5bHp08HPL`YF2 zR)Ad1z{zh`=sDs^&V}J z%$Z$!jd7BY5AkT?j`eqMs%!Gm@T8)4w3GYEX~IwgE~`d|@T{WYHkudy(47brgHXx& zBL1yFG6!!!VOSmDxBpefy2{L_u5yTwja&HA!mYA#wg#bc-m%~8aRR|~AvMnind@zs zy>wkShe5&*un^zvSOdlVu%kHsEo>@puMQ`b1}(|)l~E{5)f7gC=E$fP(FC2=F<^|A zxeIm?{EE!3sO!Gr7e{w)Dx(uU#3WrFZ>ibmKSQ1tY?*-Nh1TDHLe+k*;{Rp!Bmd_m zb#^kh`Y*8l|9Cz2e{;RL%_lg{#^Ar+NH|3z*Zye>!alpt{z;4dFAw^^H!6ING*EFc z_yqhr8d!;%nHX9AKhFQZBGrSzfzYCi%C!(Q5*~hX>)0N`vbhZ@N|i;_972WSx*>LH z87?en(;2_`{_JHF`Sv6Wlps;dCcj+8IJ8ca6`DsOQCMb3n# z3)_w%FuJ3>fjeOOtWyq)ag|PmgQbC-s}KRHG~enBcIwqIiGW8R8jFeBNY9|YswRY5 zjGUxdGgUD26wOpwM#8a!Nuqg68*dG@VM~SbOroL_On0N6QdT9?)NeB3@0FCC?Z|E0 z6TPZj(AsPtwCw>*{eDEE}Gby>0q{*lI+g2e&(YQrsY&uGM{O~}(oM@YWmb*F zA0^rr5~UD^qmNljq$F#ARXRZ1igP`MQx4aS6*MS;Ot(1L5jF2NJ;de!NujUYg$dr# z=TEL_zTj2@>ZZN(NYCeVX2==~=aT)R30gETO{G&GM4XN<+!&W&(WcDP%oL8PyIVUC zs5AvMgh6qr-2?^unB@mXK*Dbil^y-GTC+>&N5HkzXtozVf93m~xOUHn8`HpX=$_v2 z61H;Z1qK9o;>->tb8y%#4H)765W4E>TQ1o0PFj)uTOPEvv&}%(_mG0ISmyhnQV33Z$#&yd{ zc{>8V8XK$3u8}04CmAQ#I@XvtmB*s4t8va?-IY4@CN>;)mLb_4!&P3XSw4pA_NzDb zORn!blT-aHk1%Jpi>T~oGLuh{DB)JIGZ9KOsciWs2N7mM1JWM+lna4vkDL?Q)z_Ct z`!mi0jtr+4*L&N7jk&LodVO#6?_qRGVaucqVB8*us6i3BTa^^EI0x%EREQSXV@f!lak6Wf1cNZ8>*artIJ(ADO*=<-an`3zB4d*oO*8D1K!f z*A@P1bZCNtU=p!742MrAj%&5v%Xp_dSX@4YCw%F|%Dk=u|1BOmo)HsVz)nD5USa zR~??e61sO(;PR)iaxK{M%QM_rIua9C^4ppVS$qCT9j2%?*em?`4Z;4@>I(c%M&#cH z>4}*;ej<4cKkbCAjjDsyKS8rIm90O)Jjgyxj5^venBx&7B!xLmzxW3jhj7sR(^3Fz z84EY|p1NauwXUr;FfZjdaAfh%ivyp+^!jBjJuAaKa!yCq=?T_)R!>16?{~p)FQ3LDoMyG%hL#pR!f@P%*;#90rs_y z@9}@r1BmM-SJ#DeuqCQk=J?ixDSwL*wh|G#us;dd{H}3*-Y7Tv5m=bQJMcH+_S`zVtf;!0kt*(zwJ zs+kedTm!A}cMiM!qv(c$o5K%}Yd0|nOd0iLjus&;s0Acvoi-PFrWm?+q9f^FslxGi z6ywB`QpL$rJzWDg(4)C4+!2cLE}UPCTBLa*_=c#*$b2PWrRN46$y~yST3a2$7hEH= zNjux+wna^AzQ=KEa_5#9Ph=G1{S0#hh1L3hQ`@HrVnCx{!fw_a0N5xV(iPdKZ-HOM za)LdgK}1ww*C_>V7hbQnTzjURJL`S%`6nTHcgS+dB6b_;PY1FsrdE8(2K6FN>37!62j_cBlui{jO^$dPkGHV>pXvW0EiOA zqW`YaSUBWg_v^Y5tPJfWLcLpsA8T zG)!x>pKMpt!lv3&KV!-um= zKCir6`bEL_LCFx4Z5bAFXW$g3Cq`?Q%)3q0r852XI*Der*JNuKUZ`C{cCuu8R8nkt z%pnF>R$uY8L+D!V{s^9>IC+bmt<05h**>49R*#vpM*4i0qRB2uPbg8{{s#9yC;Z18 zD7|4m<9qneQ84uX|J&f-g8a|nFKFt34@Bt{CU`v(SYbbn95Q67*)_Esl_;v291s=9 z+#2F2apZU4Tq=x+?V}CjwD(P=U~d<=mfEFuyPB`Ey82V9G#Sk8H_Ob_RnP3s?)S_3 zr%}Pb?;lt_)Nf>@zX~D~TBr;-LS<1I##8z`;0ZCvI_QbXNh8Iv)$LS=*gHr;}dgb=w5$3k2la1keIm|=7<-JD>)U%=Avl0Vj@+&vxn zt-)`vJxJr88D&!}2^{GPXc^nmRf#}nb$4MMkBA21GzB`-Or`-3lq^O^svO7Vs~FdM zv`NvzyG+0T!P8l_&8gH|pzE{N(gv_tgDU7SWeiI-iHC#0Ai%Ixn4&nt{5y3(GQs)i z&uA;~_0shP$0Wh0VooIeyC|lak__#KVJfxa7*mYmZ22@(<^W}FdKjd*U1CqSjNKW% z*z$5$=t^+;Ui=MoDW~A7;)Mj%ibX1_p4gu>RC}Z_pl`U*{_z@+HN?AF{_W z?M_X@o%w8fgFIJ$fIzBeK=v#*`mtY$HC3tqw7q^GCT!P$I%=2N4FY7j9nG8aIm$c9 zeKTxVKN!UJ{#W)zxW|Q^K!3s;(*7Gbn;e@pQBCDS(I|Y0euK#dSQ_W^)sv5pa%<^o zyu}3d?Lx`)3-n5Sy9r#`I{+t6x%I%G(iewGbvor&I^{lhu-!#}*Q3^itvY(^UWXgvthH52zLy&T+B)Pw;5>4D6>74 zO_EBS)>l!zLTVkX@NDqyN2cXTwsUVao7$HcqV2%t$YzdAC&T)dwzExa3*kt9d(}al zA~M}=%2NVNUjZiO7c>04YH)sRelXJYpWSn^aC$|Ji|E13a^-v2MB!Nc*b+=KY7MCm zqIteKfNkONq}uM;PB?vvgQvfKLPMB8u5+Am=d#>g+o&Ysb>dX9EC8q?D$pJH!MTAqa=DS5$cb+;hEvjwVfF{4;M{5U&^_+r zvZdu_rildI!*|*A$TzJ&apQWV@p{!W`=?t(o0{?9y&vM)V)ycGSlI3`;ps(vf2PUq zX745#`cmT*ra7XECC0gKkpu2eyhFEUb?;4@X7weEnLjXj_F~?OzL1U1L0|s6M+kIhmi%`n5vvDALMagi4`wMc=JV{XiO+^ z?s9i7;GgrRW{Mx)d7rj)?(;|b-`iBNPqdwtt%32se@?w4<^KU&585_kZ=`Wy^oLu9 z?DQAh5z%q;UkP48jgMFHTf#mj?#z|=w= z(q6~17Vn}P)J3M?O)x))%a5+>TFW3No~TgP;f}K$#icBh;rSS+R|}l鯊%1Et zwk~hMkhq;MOw^Q5`7oC{CUUyTw9x>^%*FHx^qJw(LB+E0WBX@{Ghw;)6aA-KyYg8p z7XDveQOpEr;B4je@2~usI5BlFadedX^ma{b{ypd|RNYqo#~d*mj&y`^iojR}s%~vF z(H!u`yx68D1Tj(3(m;Q+Ma}s2n#;O~bcB1`lYk%Irx60&-nWIUBr2x&@}@76+*zJ5 ze&4?q8?m%L9c6h=J$WBzbiTf1Z-0Eb5$IZs>lvm$>1n_Mezp*qw_pr8<8$6f)5f<@ zyV#tzMCs51nTv_5ca`x`yfE5YA^*%O_H?;tWYdM_kHPubA%vy47i=9>Bq) zRQ&0UwLQHeswmB1yP)+BiR;S+Vc-5TX84KUA;8VY9}yEj0eESSO`7HQ4lO z4(CyA8y1G7_C;6kd4U3K-aNOK!sHE}KL_-^EDl(vB42P$2Km7$WGqNy=%fqB+ zSLdrlcbEH=T@W8V4(TgoXZ*G1_aq$K^@ek=TVhoKRjw;HyI&coln|uRr5mMOy2GXP zwr*F^Y|!Sjr2YQXX(Fp^*`Wk905K%$bd03R4(igl0&7IIm*#f`A!DCarW9$h$z`kYk9MjjqN&5-DsH@8xh63!fTNPxWsFQhNv z#|3RjnP$Thdb#Ys7M+v|>AHm0BVTw)EH}>x@_f4zca&3tXJhTZ8pO}aN?(dHo)44Z z_5j+YP=jMlFqwvf3lq!57-SAuRV2_gJ*wsR_!Y4Z(trO}0wmB9%f#jNDHPdQGHFR; zZXzS-$`;7DQ5vF~oSgP3bNV$6Z(rwo6W(U07b1n3UHqml>{=6&-4PALATsH@Bh^W? z)ob%oAPaiw{?9HfMzpGb)@Kys^J$CN{uf*HX?)z=g`J(uK1YO^8~s1(ZIbG%Et(|q z$D@_QqltVZu9Py4R0Ld8!U|#`5~^M=b>fnHthzKBRr=i+w@0Vr^l|W;=zFT#PJ?*a zbC}G#It}rQP^Ait^W&aa6B;+0gNvz4cWUMzpv(1gvfw-X4xJ2Sv;mt;zb2Tsn|kSS zo*U9N?I{=-;a-OybL4r;PolCfiaL=y@o9{%`>+&FI#D^uy#>)R@b^1ue&AKKwuI*` zx%+6r48EIX6nF4o;>)zhV_8(IEX})NGU6Vs(yslrx{5fII}o3SMHW7wGtK9oIO4OM&@@ECtXSICLcPXoS|{;=_yj>hh*%hP27yZwOmj4&Lh z*Nd@OMkd!aKReoqNOkp5cW*lC)&C$P?+H3*%8)6HcpBg&IhGP^77XPZpc%WKYLX$T zsSQ$|ntaVVOoRat$6lvZO(G-QM5s#N4j*|N_;8cc2v_k4n6zx9c1L4JL*83F-C1Cn zaJhd;>rHXB%%ZN=3_o3&Qd2YOxrK~&?1=UuN9QhL$~OY-Qyg&})#ez*8NpQW_*a&kD&ANjedxT0Ar z<6r{eaVz3`d~+N~vkMaV8{F?RBVemN(jD@S8qO~L{rUw#=2a$V(7rLE+kGUZ<%pdr z?$DP|Vg#gZ9S}w((O2NbxzQ^zTot=89!0^~hE{|c9q1hVzv0?YC5s42Yx($;hAp*E zyoGuRyphQY{Q2ee0Xx`1&lv(l-SeC$NEyS~8iil3_aNlnqF_G|;zt#F%1;J)jnPT& z@iU0S;wHJ2$f!juqEzPZeZkjcQ+Pa@eERSLKsWf=`{R@yv7AuRh&ALRTAy z8=g&nxsSJCe!QLchJ=}6|LshnXIK)SNd zRkJNiqHwKK{SO;N5m5wdL&qK`v|d?5<4!(FAsDxR>Ky#0#t$8XCMptvNo?|SY?d8b z`*8dVBlXTUanlh6n)!EHf2&PDG8sXNAt6~u-_1EjPI1|<=33T8 zEnA00E!`4Ave0d&VVh0e>)Dc}=FfAFxpsC1u9ATfQ`-Cu;mhc8Z>2;uyXtqpLb7(P zd2F9<3cXS} znMg?{&8_YFTGRQZEPU-XPq55%51}RJpw@LO_|)CFAt62-_!u_Uq$csc+7|3+TV_!h z+2a7Yh^5AA{q^m|=KSJL+w-EWDBc&I_I1vOr^}P8i?cKMhGy$CP0XKrQzCheG$}G# zuglf8*PAFO8%xop7KSwI8||liTaQ9NCAFarr~psQt)g*pC@9bORZ>m`_GA`_K@~&% zijH0z;T$fd;-Liw8%EKZas>BH8nYTqsK7F;>>@YsE=Rqo?_8}UO-S#|6~CAW0Oz1} z3F(1=+#wrBJh4H)9jTQ_$~@#9|Bc1Pd3rAIA_&vOpvvbgDJOM(yNPhJJq2%PCcMaI zrbe~toYzvkZYQ{ea(Wiyu#4WB#RRN%bMe=SOk!CbJZv^m?Flo5p{W8|0i3`hI3Np# zvCZqY%o258CI=SGb+A3yJe~JH^i{uU`#U#fvSC~rWTq+K`E%J@ zasU07&pB6A4w3b?d?q}2=0rA#SA7D`X+zg@&zm^iA*HVi z009#PUH<%lk4z~p^l0S{lCJk1Uxi=F4e_DwlfHA`X`rv(|JqWKAA5nH+u4Da+E_p+ zVmH@lg^n4ixs~*@gm_dgQ&eDmE1mnw5wBz9Yg?QdZwF|an67Xd*x!He)Gc8&2!urh z4_uXzbYz-aX)X1>&iUjGp;P1u8&7TID0bTH-jCL&Xk8b&;;6p2op_=y^m@Nq*0{#o!!A;wNAFG@0%Z9rHo zcJs?Th>Ny6+hI`+1XoU*ED$Yf@9f91m9Y=#N(HJP^Y@ZEYR6I?oM{>&Wq4|v0IB(p zqX#Z<_3X(&{H+{3Tr|sFy}~=bv+l=P;|sBz$wk-n^R`G3p0(p>p=5ahpaD7>r|>pm zv;V`_IR@tvZreIuv2EM7ZQHhO+qUgw#kOs%*ekY^n|=1#x9&c;Ro&I~{rG-#_3ZB1 z?|9}IFdbP}^DneP*T-JaoYHt~r@EfvnPE5EKUwIxjPbsr$% zfWW83pgWST7*B(o=kmo)74$8UU)v0{@4DI+ci&%=#90}!CZz|rnH+Mz=HN~97G3~@ z;v5(9_2%eca(9iu@J@aqaMS6*$TMw!S>H(b z4(*B!|H|8&EuB%mITr~O?vVEf%(Gr)6E=>H~1VR z&1YOXluJSG1!?TnT)_*YmJ*o_Q@om~(GdrhI{$Fsx_zrkupc#y{DK1WOUR>tk>ZE) ziOLoBkhZZ?0Uf}cm>GsA>Rd6V8@JF)J*EQlQ<=JD@m<)hyElXR0`pTku*3MU`HJn| zIf7$)RlK^pW-$87U;431;Ye4Ie+l~_B3*bH1>*yKzn23cH0u(i5pXV! z4K?{3oF7ZavmmtTq((wtml)m6i)8X6ot_mrE-QJCW}Yn!(3~aUHYG=^fA<^~`e3yc z-NWTb{gR;DOUcK#zPbN^D*e=2eR^_!(!RKkiwMW@@yYtEoOp4XjOGgzi`;=8 zi3`Ccw1%L*y(FDj=C7Ro-V?q)-%p?Ob2ZElu`eZ99n14-ZkEV#y5C+{Pq87Gu3&>g zFy~Wk7^6v*)4pF3@F@rE__k3ikx(hzN3@e*^0=KNA6|jC^B5nf(XaoQaZN?Xi}Rn3 z$8&m*KmWvPaUQ(V<#J+S&zO|8P-#!f%7G+n_%sXp9=J%Z4&9OkWXeuZN}ssgQ#Tcj z8p6ErJQJWZ+fXLCco=RN8D{W%+*kko*2-LEb))xcHwNl~Xmir>kmAxW?eW50Osw3# zki8Fl$#fvw*7rqd?%E?}ZX4`c5-R&w!Y0#EBbelVXSng+kUfeUiqofPehl}$ormli zg%r)}?%=?_pHb9`Cq9Z|B`L8b>(!+8HSX?`5+5mm81AFXfnAt1*R3F z%b2RPIacKAddx%JfQ8l{3U|vK@W7KB$CdLqn@wP^?azRks@x8z59#$Q*7q!KilY-P zHUbs(IFYRGG1{~@RF;Lqyho$~7^hNC`NL3kn^Td%A7dRgr_&`2k=t+}D-o9&C!y^? z6MsQ=tc3g0xkK(O%DzR9nbNB(r@L;1zQrs8mzx&4dz}?3KNYozOW5;=w18U6$G4U2 z#2^qRLT*Mo4bV1Oeo1PKQ2WQS2Y-hv&S|C7`xh6=Pj7MNLC5K-zokZ67S)C;(F0Dd zloDK2_o1$Fmza>EMj3X9je7e%Q`$39Dk~GoOj89-6q9|_WJlSl!!+*{R=tGp z8u|MuSwm^t7K^nUe+^0G3dkGZr3@(X+TL5eah)K^Tn zXEtHmR9UIaEYgD5Nhh(s*fcG_lh-mfy5iUF3xxpRZ0q3nZ=1qAtUa?(LnT9I&~uxX z`pV?+=|-Gl(kz?w!zIieXT}o}7@`QO>;u$Z!QB${a08_bW0_o@&9cjJUXzVyNGCm8 zm=W+$H!;_Kzp6WQqxUI;JlPY&`V}9C$8HZ^m?NvI*JT@~BM=()T()Ii#+*$y@lTZBkmMMda>7s#O(1YZR+zTG@&}!EXFG{ zEWPSDI5bFi;NT>Yj*FjH((=oe%t%xYmE~AGaOc4#9K_XsVpl<4SP@E!TgC0qpe1oi zNpxU2b0(lEMcoibQ-G^cxO?ySVW26HoBNa;n0}CWL*{k)oBu1>F18X061$SP{Gu67 z-v-Fa=Fl^u3lnGY^o5v)Bux}bNZ~ z5pL+7F_Esoun8^5>z8NFoIdb$sNS&xT8_|`GTe8zSXQzs4r^g0kZjg(b0bJvz`g<70u9Z3fQILX1Lj@;@+##bP|FAOl)U^9U>0rx zGi)M1(Hce)LAvQO-pW!MN$;#ZMX?VE(22lTlJrk#pB0FJNqVwC+*%${Gt#r_tH9I_ z;+#)#8cWAl?d@R+O+}@1A^hAR1s3UcW{G+>;X4utD2d9X(jF555}!TVN-hByV6t+A zdFR^aE@GNNgSxxixS2p=on4(+*+f<8xrwAObC)D5)4!z7)}mTpb7&ofF3u&9&wPS< zB62WHLGMhmrmOAgmJ+|c>qEWTD#jd~lHNgT0?t-p{T=~#EMcB| z=AoDKOL+qXCfk~F)-Rv**V}}gWFl>liXOl7Uec_8v)(S#av99PX1sQIVZ9eNLkhq$ zt|qu0b?GW_uo}TbU8!jYn8iJeIP)r@;!Ze_7mj{AUV$GEz6bDSDO=D!&C9!M@*S2! zfGyA|EPlXGMjkH6x7OMF?gKL7{GvGfED=Jte^p=91FpCu)#{whAMw`vSLa`K#atdN zThnL+7!ZNmP{rc=Z>%$meH;Qi1=m1E3Lq2D_O1-X5C;!I0L>zur@tPAC9*7Jeh)`;eec}1`nkRP(%iv-`N zZ@ip-g|7l6Hz%j%gcAM}6-nrC8oA$BkOTz^?dakvX?`^=ZkYh%vUE z9+&)K1UTK=ahYiaNn&G5nHUY5niLGus@p5E2@RwZufRvF{@$hW{;{3QhjvEHMvduO z#Wf-@oYU4ht?#uP{N3utVzV49mEc9>*TV_W2TVC`6+oI)zAjy$KJrr=*q##&kobiQ z1vNbya&OVjK`2pdRrM?LuK6BgrLN7H_3m z!qpNKg~87XgCwb#I=Q&0rI*l$wM!qTkXrx1ko5q-f;=R2fImRMwt5Qs{P*p^z@9ex z`2#v(qE&F%MXlHpdO#QEZyZftn4f05ab^f2vjxuFaat2}jke{j?5GrF=WYBR?gS(^ z9SBiNi}anzBDBRc+QqizTTQuJrzm^bNA~A{j%ugXP7McZqJ}65l10({wk++$=e8O{ zxWjG!Qp#5OmI#XRQQM?n6?1ztl6^D40hDJr?4$Wc&O_{*OfMfxe)V0=e{|N?J#fgE>j9jAajze$iN!*yeF%jJU#G1c@@rm zolGW!j?W6Q8pP=lkctNFdfgUMg92wlM4E$aks1??M$~WQfzzzXtS)wKrr2sJeCN4X zY(X^H_c^PzfcO8Bq(Q*p4c_v@F$Y8cHLrH$`pJ2}=#*8%JYdqsqnGqEdBQMpl!Ot04tUGSXTQdsX&GDtjbWD=prcCT9(+ z&UM%lW%Q3yrl1yiYs;LxzIy>2G}EPY6|sBhL&X&RAQrSAV4Tlh2nITR?{6xO9ujGu zr*)^E`>o!c=gT*_@6S&>0POxcXYNQd&HMw6<|#{eSute2C3{&h?Ah|cw56-AP^f8l zT^kvZY$YiH8j)sk7_=;gx)vx-PW`hbSBXJGCTkpt;ap(}G2GY=2bbjABU5)ty%G#x zAi07{Bjhv}>OD#5zh#$0w;-vvC@^}F! z#X$@)zIs1L^E;2xDAwEjaXhTBw2<{&JkF*`;c3<1U@A4MaLPe{M5DGGkL}#{cHL%* zYMG+-Fm0#qzPL#V)TvQVI|?_M>=zVJr9>(6ib*#z8q@mYKXDP`k&A4A};xMK0h=yrMp~JW{L?mE~ph&1Y1a#4%SO)@{ zK2juwynUOC)U*hVlJU17%llUxAJFuKZh3K0gU`aP)pc~bE~mM!i1mi!~LTf>1Wp< zuG+ahp^gH8g8-M$u{HUWh0m^9Rg@cQ{&DAO{PTMudV6c?ka7+AO& z746QylZ&Oj`1aqfu?l&zGtJnpEQOt;OAFq19MXTcI~`ZcoZmyMrIKDFRIDi`FH)w; z8+*8tdevMDv*VtQi|e}CnB_JWs>fhLOH-+Os2Lh!&)Oh2utl{*AwR)QVLS49iTp{6 z;|172Jl!Ml17unF+pd+Ff@jIE-{Oxv)5|pOm@CkHW?{l}b@1>Pe!l}VccX#xp@xgJ zyE<&ep$=*vT=}7vtvif0B?9xw_3Gej7mN*dOHdQPtW5kA5_zGD zpA4tV2*0E^OUimSsV#?Tg#oiQ>%4D@1F5@AHwT8Kgen$bSMHD3sXCkq8^(uo7CWk`mT zuslYq`6Yz;L%wJh$3l1%SZv#QnG3=NZ=BK4yzk#HAPbqXa92;3K5?0kn4TQ`%E%X} z&>Lbt!!QclYKd6+J7Nl@xv!uD%)*bY-;p`y^ZCC<%LEHUi$l5biu!sT3TGGSTPA21 zT8@B&a0lJHVn1I$I3I1I{W9fJAYc+8 zVj8>HvD}&O`TqU2AAb={?eT;0hyL(R{|h23=4fDSZKC32;wWxsVj`P z3J3{M$PwdH!ro*Cn!D&=jnFR>BNGR<<|I8CI@+@658Dy(lhqbhXfPTVecY@L8%`3Q z1Fux2w?2C3th60jI~%OC9BtpNF$QPqcG+Pz96qZJ71_`0o0w_q7|h&O>`6U+^BA&5 zXd5Zp1Xkw~>M%RixTm&OqpNl8Q+ue=92Op_>T~_9UON?ZM2c0aGm=^A4ejrXj3dV9 zhh_bCt-b9`uOX#cFLj!vhZ#lS8Tc47OH>*)y#{O9?AT~KR9LntM|#l#Dlm^8{nZdk zjMl#>ZM%#^nK2TPzLcKxqx24P7R1FPlBy7LSBrRvx>fE$9AJ;7{PQm~^LBX^k#6Zq zw*Z(zJC|`!6_)EFR}8|n8&&Rbj8y028~P~sFXBFRt+tmqH-S3<%N;C&WGH!f3{7cm zy_fCAb9@HqaXa1Y5vFbxWf%#zg6SI$C+Uz5=CTO}e|2fjWkZ;Dx|84Ow~bkI=LW+U zuq;KSv9VMboRvs9)}2PAO|b(JCEC_A0wq{uEj|3x@}*=bOd zwr{TgeCGG>HT<@Zeq8y}vTpwDg#UBvD)BEs@1KP$^3$sh&_joQPn{hjBXmLPJ{tC) z*HS`*2+VtJO{|e$mM^|qv1R*8i(m1`%)}g=SU#T#0KlTM2RSvYUc1fP+va|4;5}Bfz98UvDCpq7}+SMV&;nX zQw~N6qOX{P55{#LQkrZk(e5YGzr|(B;Q;ju;2a`q+S9bsEH@i1{_Y0;hWYn1-79jl z5c&bytD*k)GqrVcHn6t-7kinadiD>B{Tl`ZY@`g|b~pvHh5!gKP4({rp?D0aFd_cN zhHRo4dd5^S6ViN(>(28qZT6E>??aRhc($kP`>@<+lIKS5HdhjVU;>f7<4))E*5|g{ z&d1}D|vpuV^eRj5j|xx9nwaCxXFG?Qbjn~_WSy=N}P0W>MP zG-F%70lX5Xr$a)2i6?i|iMyM|;Jtf*hO?=Jxj12oz&>P=1#h~lf%#fc73M2_(SUM- zf&qnjS80|_Y0lDgl&I?*eMumUklLe_=Td!9G@eR*tcPOgIShJipp3{A10u(4eT~DY zHezEj8V+7m!knn7)W!-5QI3=IvC^as5+TW1@Ern@yX| z7Nn~xVx&fGSr+L%4iohtS3w^{-H1A_5=r&x8}R!YZvp<2T^YFvj8G_vm}5q;^UOJf ztl=X3iL;;^^a#`t{Ae-%5Oq{?M#s6Npj+L(n-*LMI-yMR{)qki!~{5z{&`-iL}lgW zxo+tnvICK=lImjV$Z|O_cYj_PlEYCzu-XBz&XC-JVxUh9;6*z4fuBG+H{voCC;`~GYV|hj%j_&I zDZCj>Q_0RCwFauYoVMiUSB+*Mx`tg)bWmM^SwMA+?lBg12QUF_x2b)b?qb88K-YUd z0dO}3k#QirBV<5%jL$#wlf!60dizu;tsp(7XLdI=eQs?P`tOZYMjVq&jE)qK*6B^$ zBe>VvH5TO>s>izhwJJ$<`a8fakTL!yM^Zfr2hV9`f}}VVUXK39p@G|xYRz{fTI+Yq z20d=)iwjuG9RB$%$^&8#(c0_j0t_C~^|n+c`Apu|x7~;#cS-s=X1|C*YxX3ailhg_|0`g!E&GZJEr?bh#Tpb8siR=JxWKc{#w7g zWznLwi;zLFmM1g8V5-P#RsM@iX>TK$xsWuujcsVR^7TQ@!+vCD<>Bk9tdCo7Mzgq5 zv8d>dK9x8C@Qoh01u@3h0X_`SZluTb@5o;{4{{eF!-4405x8X7hewZWpz z2qEi4UTiXTvsa(0X7kQH{3VMF>W|6;6iTrrYD2fMggFA&-CBEfSqPlQDxqsa>{e2M z(R5PJ7uOooFc|9GU0ELA%m4&4Ja#cQpNw8i8ACAoK6?-px+oBl_yKmenZut#Xumjz zk8p^OV2KY&?5MUwGrBOo?ki`Sxo#?-Q4gw*Sh0k`@ zFTaYK2;}%Zk-68`#5DXU$2#=%YL#S&MTN8bF+!J2VT6x^XBci6O)Q#JfW{YMz) zOBM>t2rSj)n#0a3cjvu}r|k3od6W(SN}V-cL?bi*Iz-8uOcCcsX0L>ZXjLqk zZu2uHq5B|Kt>e+=pPKu=1P@1r9WLgYFq_TNV1p9pu0erHGd!+bBp!qGi+~4A(RsYN@CyXNrC&hxGmW)u5m35OmWwX`I+0yByglO`}HC4nGE^_HUs^&A(uaM zKPj^=qI{&ayOq#z=p&pnx@@k&I1JI>cttJcu@Ihljt?6p^6{|ds`0MoQwp+I{3l6` zB<9S((RpLG^>=Kic`1LnhpW2=Gu!x`m~=y;A`Qk!-w`IN;S8S930#vBVMv2vCKi}u z6<-VPrU0AnE&vzwV(CFC0gnZYcpa-l5T0ZS$P6(?9AM;`Aj~XDvt;Jua=jIgF=Fm? zdp=M$>`phx%+Gu};;-&7T|B1AcC#L4@mW5SV_^1BRbo6;2PWe$r+npRV`yc;T1mo& z+~_?7rA+(Um&o@Tddl zL_hxvWk~a)yY}%j`Y+200D%9$bWHy&;(yj{jpi?Rtz{J66ANw)UyPOm;t6FzY3$hx zcn)Ir79nhFvNa7^a{SHN7XH*|Vlsx`CddPnA&Qvh8aNhEA;mPVv;Ah=k<*u!Zq^7 z<=xs*iQTQOMMcg|(NA_auh@x`3#_LFt=)}%SQppP{E>mu_LgquAWvh<>L7tf9+~rO znwUDS52u)OtY<~!d$;m9+87aO+&`#2ICl@Y>&F{jI=H(K+@3M1$rr=*H^dye#~TyD z!){#Pyfn+|ugUu}G;a~!&&0aqQ59U@UT3|_JuBlYUpT$2+11;}JBJ`{+lQN9T@QFY z5+`t;6(TS0F?OlBTE!@7D`8#URDNqx2t6`GZ{ZgXeS@v%-eJzZOHz18aS|svxII$a zZeFjrJ*$IwX$f-Rzr_G>xbu@euGl)B7pC&S+CmDJBg$BoV~jxSO#>y z33`bupN#LDoW0feZe0%q8un0rYN|eRAnwDHQ6e_)xBTbtoZtTA=Fvk){q}9Os~6mQ zKB80VI_&6iSq`LnK7*kfHZoeX6?WE}8yjuDn=2#JG$+;-TOA1%^=DnXx%w{b=w}tS zQbU3XxtOI8E(!%`64r2`zog;5<0b4i)xBmGP^jiDZ2%HNSxIf3@wKs~uk4%3Mxz;~ zts_S~E4>W+YwI<-*-$U8*^HKDEa8oLbmqGg?3vewnaNg%Mm)W=)lcC_J+1ov^u*N3 zXJ?!BrH-+wGYziJq2Y#vyry6Z>NPgkEk+Ke`^DvNRdb>Q2Nlr#v%O@<5hbflI6EKE z9dWc0-ORk^T}jP!nkJ1imyjdVX@GrjOs%cpgA8-c&FH&$(4od#x6Y&=LiJZPINVyW z0snY$8JW@>tc2}DlrD3StQmA0Twck~@>8dSix9CyQOALcREdxoM$Sw*l!}bXKq9&r zysMWR@%OY24@e`?+#xV2bk{T^C_xSo8v2ZI=lBI*l{RciPwuE>L5@uhz@{!l)rtVlWC>)6(G)1~n=Q|S!{E9~6*fdpa*n z!()-8EpTdj=zr_Lswi;#{TxbtH$8*G=UM`I+icz7sr_SdnHXrv=?iEOF1UL+*6O;% zPw>t^kbW9X@oEXx<97%lBm-9?O_7L!DeD)Me#rwE54t~UBu9VZ zl_I1tBB~>jm@bw0Aljz8! zXBB6ATG6iByKIxs!qr%pz%wgqbg(l{65DP4#v(vqhhL{0b#0C8mq`bnqZ1OwFV z7mlZZJFMACm>h9v^2J9+^_zc1=JjL#qM5ZHaThH&n zXPTsR8(+)cj&>Un{6v*z?@VTLr{TmZ@-fY%*o2G}*G}#!bmqpoo*Ay@U!JI^Q@7gj;Kg-HIrLj4}#ec4~D2~X6vo;ghep-@&yOivYP zC19L0D`jjKy1Yi-SGPAn94(768Tcf$urAf{)1)9W58P`6MA{YG%O?|07!g9(b`8PXG1B1Sh0?HQmeJtP0M$O$hI z{5G`&9XzYhh|y@qsF1GnHN|~^ru~HVf#)lOTSrv=S@DyR$UKQk zjdEPFDz{uHM&UM;=mG!xKvp;xAGHOBo~>_=WFTmh$chpC7c`~7?36h)7$fF~Ii}8q zF|YXxH-Z?d+Q+27Rs3X9S&K3N+)OBxMHn1u(vlrUC6ckBY@@jl+mgr#KQUKo#VeFm zFwNYgv0<%~Wn}KeLeD9e1$S>jhOq&(e*I@L<=I5b(?G(zpqI*WBqf|Zge0&aoDUsC zngMRA_Kt0>La+Erl=Uv_J^p(z=!?XHpenzn$%EA`JIq#yYF?JLDMYiPfM(&Csr#f{ zdd+LJL1by?xz|D8+(fgzRs~(N1k9DSyK@LJygwaYX8dZl0W!I&c^K?7)z{2is;OkE zd$VK-(uH#AUaZrp=1z;O*n=b?QJkxu`Xsw&7yrX0?(CX=I-C#T;yi8a<{E~?vr3W> zQrpPqOW2M+AnZ&p{hqmHZU-;Q(7?- zP8L|Q0RM~sB0w1w53f&Kd*y}ofx@c z5Y6B8qGel+uT1JMot$nT1!Tim6{>oZzJXdyA+4euOLME?5Fd_85Uk%#E*ln%y{u8Q z$|?|R@Hpb~yTVK-Yr_S#%NUy7EBfYGAg>b({J|5b+j-PBpPy$Ns`PaJin4JdRfOaS zE|<HjH%NuJgsd2wOlv>~y=np%=2)$M9LS|>P)zJ+Fei5vYo_N~B0XCn+GM76 z)Xz3tg*FRVFgIl9zpESgdpWAavvVViGlU8|UFY{{gVJskg*I!ZjWyk~OW-Td4(mZ6 zB&SQreAAMqwp}rjy`HsG({l2&q5Y52<@AULVAu~rWI$UbFuZs>Sc*x+XI<+ez%$U)|a^unjpiW0l0 zj1!K0(b6$8LOjzRqQ~K&dfbMIE=TF}XFAi)$+h}5SD3lo z%%Qd>p9se=VtQG{kQ;N`sI)G^u|DN#7{aoEd zkksYP%_X$Rq08);-s6o>CGJ<}v`qs%eYf+J%DQ^2k68C%nvikRsN?$ap--f+vCS`K z#&~)f7!N^;sdUXu54gl3L=LN>FB^tuK=y2e#|hWiWUls__n@L|>xH{%8lIJTd5`w? zSwZbnS;W~DawT4OwSJVdAylbY+u5S+ZH{4hAi2&}Iv~W(UvHg(1GTZRPz`@{SOqzy z(8g&Dz=$PfRV=6FgxN~zo+G8OoPI&d-thcGVR*_^(R8COTM@bq?fDwY{}WhsQS1AK zF6R1t8!RdFmfocpJ6?9Yv~;WYi~XPgs(|>{5})j!AR!voO7y9&cMPo#80A(`za@t>cx<0;qxM@S*m(jYP)dMXr*?q0E`oL;12}VAep179uEr8c<=D zr5?A*C{eJ`z9Ee;E$8)MECqatHkbHH z&Y+ho0B$31MIB-xm&;xyaFCtg<{m~M-QDbY)fQ>Q*Xibb~8ytxZQ?QMf9!%cV zU0_X1@b4d+Pg#R!`OJ~DOrQz3@cpiGy~XSKjZQQ|^4J1puvwKeScrH8o{bscBsowomu z^f12kTvje`yEI3eEXDHJ6L+O{Jv$HVj%IKb|J{IvD*l6IG8WUgDJ*UGz z3!C%>?=dlfSJ>4U88)V+`U-!9r^@AxJBx8R;)J4Fn@`~k>8>v0M9xp90OJElWP&R5 zM#v*vtT}*Gm1^)Bv!s72T3PB0yVIjJW)H7a)ilkAvoaH?)jjb`MP>2z{%Y?}83 zUIwBKn`-MSg)=?R)1Q0z3b>dHE^)D8LFs}6ASG1|daDly_^lOSy&zIIhm*HXm1?VS=_iacG);_I9c zUQH1>i#*?oPIwBMJkzi_*>HoUe}_4o>2(SHWzqQ=;TyhAHS;Enr7!#8;sdlty&(>d zl%5cjri8`2X^Ds`jnw7>A`X|bl=U8n+3LKLy(1dAu8`g@9=5iw$R0qk)w8Vh_Dt^U zIglK}sn^)W7aB(Q>HvrX=rxB z+*L)3DiqpQ_%~|m=44LcD4-bxO3OO*LPjsh%p(k?&jvLp0py57oMH|*IMa(<|{m1(0S|x)?R-mqJ=I;_YUZA>J z62v*eSK;5w!h8J+6Z2~oyGdZ68waWfy09?4fU&m7%u~zi?YPHPgK6LDwphgaYu%0j zurtw)AYOpYKgHBrkX189mlJ`q)w-f|6>IER{5Lk97%P~a-JyCRFjejW@L>n4vt6#hq;!|m;hNE||LK3nw1{bJOy+eBJjK=QqNjI;Q6;Rp5 z&035pZDUZ#%Oa;&_7x0T<7!RW`#YBOj}F380Bq?MjjEhrvlCATPdkCTTl+2efTX$k zH&0zR1n^`C3ef~^sXzJK-)52(T}uTG%OF8yDhT76L~|^+hZ2hiSM*QA9*D5odI1>& z9kV9jC~twA5MwyOx(lsGD_ggYmztXPD`2=_V|ks_FOx!_J8!zM zTzh^cc+=VNZ&(OdN=y4Juw)@8-85lwf_#VMN!Ed(eQiRiLB2^2e`4dp286h@v@`O%_b)Y~A; zv}r6U?zs&@uD_+(_4bwoy7*uozNvp?bXFoB8?l8yG0qsm1JYzIvB_OH4_2G*IIOwT zVl%HX1562vLVcxM_RG*~w_`FbIc!(T=3>r528#%mwwMK}uEhJ()3MEby zQQjzqjWkwfI~;Fuj(Lj=Ug0y`>~C7`w&wzjK(rPw+Hpd~EvQ-ufQOiB4OMpyUKJhw zqEt~jle9d7S~LI~$6Z->J~QJ{Vdn3!c}g9}*KG^Kzr^(7VI5Gk(mHLL{itj_hG?&K4Ws0+T4gLfi3eu$N=`s36geNC?c zm!~}vG6lx9Uf^5M;bWntF<-{p^bruy~f?sk9 zcETAPQZLoJ8JzMMg<-=ju4keY@SY%Wo?u9Gx=j&dfa6LIAB|IrbORLV1-H==Z1zCM zeZcOYpm5>U2fU7V*h;%n`8 zN95QhfD994={1*<2vKLCNF)feKOGk`R#K~G=;rfq}|)s20&MCa65 zUM?xF5!&e0lF%|U!#rD@I{~OsS_?=;s_MQ_b_s=PuWdC)q|UQ&ea)DMRh5>fpQjXe z%9#*x=7{iRCtBKT#H>#v%>77|{4_slZ)XCY{s3j_r{tdpvb#|r|sbS^dU1x70$eJMU!h{Y7Kd{dl}9&vxQl6Jt1a` zHQZrWyY0?!vqf@u-fxU_@+}u(%Wm>0I#KP48tiAPYY!TdW(o|KtVI|EUB9V`CBBNaBLVih7+yMVF|GSoIQD0Jfb{ z!OXq;(>Z?O`1gap(L~bUcp>Lc@Jl-})^=6P%<~~9ywY=$iu8pJ0m*hOPzr~q`23eX zgbs;VOxxENe0UMVeN*>uCn9Gk!4siN-e>x)pIKAbQz!G)TcqIJ0`JBBaX>1-4_XO_-HCS^vr2vjv#7KltDZdyQ{tlWh4$Gm zB>|O1cBDC)yG(sbnc*@w6e%e}r*|IhpXckx&;sQCwGdKH+3oSG-2)Bf#x`@<4ETAr z0My%7RFh6ZLiZ_;X6Mu1YmXx7C$lSZ^}1h;j`EZd6@%JNUe=btBE z%s=Xmo1Ps?8G`}9+6>iaB8bgjUdXT?=trMu|4yLX^m0Dg{m7rpKNJey|EwHI+nN1e zL^>qN%5Fg)dGs4DO~uwIdXImN)QJ*Jhpj7$fq_^`{3fwpztL@WBB}OwQ#Epo-mqMO zsM$UgpFiG&d#)lzEQ{3Q;)&zTw;SzGOah-Dpm{!q7<8*)Ti_;xvV2TYXa}=faXZy? z3y?~GY@kl)>G&EvEijk9y1S`*=zBJSB1iet>0;x1Ai)*`^{pj0JMs)KAM=@UyOGtO z3y0BouW$N&TnwU6!%zS%nIrnANvZF&vB1~P5_d`x-giHuG zPJ;>XkVoghm#kZXRf>qxxEix;2;D1CC~NrbO6NBX!`&_$iXwP~P*c($EVV|669kDO zKoTLZNF4Cskh!Jz5ga9uZ`3o%7Pv`d^;a=cXI|>y;zC3rYPFLQkF*nv(r>SQvD*## z(Vo%^9g`%XwS0t#94zPq;mYGLKu4LU3;txF26?V~A0xZbU4Lmy`)>SoQX^m7fd^*E z+%{R4eN!rIk~K)M&UEzxp9dbY;_I^c} zOc{wlIrN_P(PPqi51k_$>Lt|X6A^|CGYgKAmoI#Li?;Wq%q~q*L7ehZkUrMxW67Jl zhsb~+U?33QS>eqyN{(odAkbopo=Q$Az?L+NZW>j;#~@wCDX?=L5SI|OxI~7!Pli;e zELMFcZtJY3!|=Gr2L4>z8yQ-{To>(f80*#;6`4IAiqUw`=Pg$%C?#1 z_g@hIGerILSU>=P>z{gM|DS91A4cT@PEIB^hSop!uhMo#2G;+tQSpDO_6nOnPWSLU zS;a9m^DFMXR4?*X=}d7l;nXuHk&0|m`NQn%d?8|Ab3A9l9Jh5s120ibWBdB z$5YwsK3;wvp!Kn@)Qae{ef`0#NwlRpQ}k^r>yos_Ne1;xyKLO?4)t_G4eK~wkUS2A&@_;)K0-03XGBzU+5f+uMDxC z(s8!8!RvdC#@`~fx$r)TKdLD6fWEVdEYtV#{ncT-ZMX~eI#UeQ-+H(Z43vVn%Yj9X zLdu9>o%wnWdvzA-#d6Z~vzj-}V3FQ5;axDIZ;i(95IIU=GQ4WuU{tl-{gk!5{l4_d zvvb&uE{%!iFwpymz{wh?bKr1*qzeZb5f6e6m_ozRF&zux2mlK=v_(_s^R6b5lu?_W4W3#<$zeG~Pd)^!4tzhs}-Sx$FJP>)ZGF(hVTH|C3(U zs0PO&*h_ zNA-&qZpTP$$LtIgfiCn07}XDbK#HIXdmv8zdz4TY;ifNIH-0jy(gMSByG2EF~Th#eb_TueZC` zE?3I>UTMpKQ})=C;6p!?G)M6w^u*A57bD?2X`m3X^6;&4%i_m(uGJ3Z5h`nwxM<)H z$I5m?wN>O~8`BGnZ=y^p6;0+%_0K}Dcg|K;+fEi|qoBqvHj(M&aHGqNF48~XqhtU? z^ogwBzRlOfpAJ+Rw7IED8lRbTdBdyEK$gPUpUG}j-M42xDj_&qEAQEtbs>D#dRd7Y z<&TpSZ(quQDHiCFn&0xsrz~4`4tz!CdL8m~HxZM_agu@IrBpyeL1Ft}V$HX_ZqDPm z-f89)pjuEzGdq-PRu`b1m+qBGY{zr_>{6Ss>F|xHZlJj9dt5HD$u`1*WZe)qEIuDSR)%z+|n zatVlhQ?$w#XRS7xUrFE;Y8vMGhQS5*T{ZnY=q1P?w5g$OKJ#M&e??tAmPWHMj3xhS ziGxapy?kn@$~2%ZY;M8Bc@%$pkl%Rvj!?o%agBvpQ-Q61n9kznC4ttrRNQ4%GFR5u zyv%Yo9~yxQJWJSfj z?#HY$y=O~F|2pZs22pu|_&Ajd+D(Mt!nPUG{|1nlvP`=R#kKH zO*s$r_%ss5h1YO7k0bHJ2CXN)Yd6CHn~W!R=SqkWe=&nAZu(Q1G!xgcUilM@YVei@2@a`8he z9@pM`)VB*=e7-MWgLlXlc)t;fF&-AwM{E-EX}pViFn0I0CNw2bNEnN2dj!^4(^zS3 zobUm1uQnpqk_4q{pl*n06=TfK_C>UgurKFjRXsK_LEn};=79`TB12tv6KzwSu*-C8 z;=~ohDLZylHQ|Mpx-?yql>|e=vI1Z!epyUpAcDCp4T|*RV&X`Q$0ogNwy6mFALo^@ z9=&(9txO8V@E!@6^(W0{*~CT>+-MA~vnJULBxCTUW>X5>r7*eXYUT0B6+w@lzw%n> z_VjJ<2qf|(d6jYq2(x$(ZDf!yVkfnbvNmb5c|hhZ^2TV_LBz`9w!e_V*W_(MiA7|= z&EeIIkw*+$Xd!)j8<@_<}A5;~A_>3JT*kX^@}cDoLd>Qj<`Se^wdUa(j0dp+Tl8EptwBm{9OGsdFEq zM`!pjf(Lm(`$e3FLOjqA5LnN5o!}z{ zNf}rJuZh@yUtq&ErjHeGzX4(!luV!jB&;FAP|!R_QHYw#^Z1LwTePAKJ6X&IDNO#; z)#I@Xnnzyij~C@UH~X51JCgQeF0&hTXnuoElz#m{heZRexWc0k4<>0+ClX7%0 zEBqCCld1tD9Zwkr4{?Nor19#E5-YKfB8d?qgR82-Ow2^AuNevly2*tHA|sK!ybYkX zm-sLQH72P&{vEAW6+z~O5d0qd=xW~rua~5a?ymYFSD@8&gV)E5@RNNBAj^C99+Z5Z zR@Pq55mbCQbz+Mn$d_CMW<-+?TU960agEk1J<>d>0K=pF19yN))a~4>m^G&tc*xR+yMD*S=yip-q=H zIlredHpsJV8H(32@Zxc@bX6a21dUV95Th--8pE6C&3F>pk=yv$yd6@Haw;$v4+Fcb zRwn{Qo@0`7aPa2LQOP}j9v>sjOo5Kqvn|`FLizX zB+@-u4Lw|jsvz{p^>n8Vo8H2peIqJJnMN}A)q6%$Tmig7eu^}K2 zrh$X?T|ZMsoh{6pdw1G$_T<`Ds-G=jc;qcGdK4{?dN2-XxjDNbb(7pk|3JUVCU4y; z)?LXR>f+AAu)JEiti_Zy#z5{RgsC}R(@jl%9YZ>zu~hKQ*AxbvhC378-I@{~#%Y`Z zy=a=9YpewPIC+gkEUUwtUL7|RU7=!^Aa}Mk^6uxOgRGA#JXjWLsjFUnix|Mau{hDT z7mn*z1m5g`vP(#tjT0Zy4eAY(br&!RiiXE=ZI!{sE1#^#%x^Z7t1U)b<;%Y}Q9=5v z;wpDCEZ@OE36TWT=|gxigT@VaW9BvHS05;_P(#s z8zI4XFQys}q)<`tkX$WnSarn{3e!s}4(J!=Yf>+Y>cP3f;vr63f2{|S^`_pWc)^5_!R z*(x-fuBxL51@xe!lnDBKi}Br$c$BMZ3%f2Sa6kLabiBS{pq*yj;q|k(86x`PiC{p6 z_bxCW{>Q2BA8~Ggz&0jkrcU+-$ANBsOop*ms>34K9lNYil@}jC;?cYP(m^P}nR6FV zk(M%48Z&%2Rx$A&FhOEirEhY0(dn;-k(qkTU)sFQ`+-ih+s@A8g?r8Pw+}2;35WYf zi}VO`jS`p(tc)$X$a>-#WXoW!phhatC*$}|rk>|wUU71eUJG^$c6_jwX?iSHM@6__ zvV|6%U*$sSXJu9SX?2%M^kK|}a2QJ8AhF{fuXrHZxXsI~O zGKX45!K7p*MCPEQ=gp?eu&#AW*pR{lhQR##P_*{c_DjMGL|3T3-bSJ(o$|M{ytU}> zAV>wq*uE*qFo9KvnA^@juy{x<-u*#2NvkV={Ly}ysKYB-k`K3@K#^S1Bb$8Y#0L0# z`6IkSG&|Z$ODy|VLS+y5pFJx&8tvPmMd8c9FhCyiU8~k6FwkakUd^(_ml8`rnl>JS zZV){9G*)xBqPz^LDqRwyS6w86#D^~xP4($150M)SOZRe9sn=>V#aG0Iy(_^YcPpIz8QYM-#s+n% z@Jd?xQq?Xk6=<3xSY7XYP$$yd&Spu{A#uafiIfy8gRC`o0nk{ezEDjb=q_qRAlR1d zFq^*9Gn)yTG4b}R{!+3hWQ+u3GT~8nwl2S1lpw`s0X_qpxv)g+JIkVKl${sYf_nV~B>Em>M;RlqGb5WVil(89 zs=ld@|#;dq1*vQGz=7--Br-|l) zZ%Xh@v8>B7P?~}?Cg$q9_={59l%m~O&*a6TKsCMAzG&vD>k2WDzJ6!tc!V)+oxF;h zJH;apM=wO?r_+*#;ulohuP=E>^zon}a$NnlcQ{1$SO*i=jnGVcQa^>QOILc)e6;eNTI>os=eaJ{*^DE+~jc zS}TYeOykDmJ=6O%>m`i*>&pO_S;qMySJIyP=}4E&J%#1zju$RpVAkZbEl+p%?ZP^C z*$$2b4t%a(e+%>a>d_f_<JjxI#J1x;=hPd1zFPx=6T$;;X1TD*2(edZ3f46zaAoW>L53vS_J*N8TMB|n+;LD| zC=GkQPpyDY#Am4l49chDv*gojhRj_?63&&8#doW`INATAo(qY#{q}%nf@eTIXmtU< zdB<7YWfyCmBs|c)cK>1)v&M#!yNj#4d$~pVfDWQc_ke1?fw{T1Nce_b`v|Vp5ig(H zJvRD^+ps46^hLX;=e2!2e;w9y1D@!D$c@Jc&%%%IL=+xzw55&2?darw=9g~>P z9>?Kdc$r?6c$m%x2S$sdpPl>GQZ{rC9mPS63*qjCVa?OIBj!fW zm|g?>CVfGXNjOfcyqImXR_(tXS(F{FcoNzKvG5R$IgGaxC@)i(e+$ME}vPVIhd|mx2IIE+f zM?9opQHIVgBWu)^A|RzXw!^??S!x)SZOwZaJkGjc<_}2l^eSBm!eAJG9T>EC6I_sy z?bxzDIAn&K5*mX)$RQzDA?s)-no-XF(g*yl4%+GBf`##bDXJ==AQk*xmnatI;SsLp zP9XTHq5mmS=iWu~9ES>b%Q=1aMa|ya^vj$@qz9S!ih{T8_PD%Sf_QrNKwgrXw9ldm zHRVR98*{C?_XNpJn{abA!oix_mowRMu^2lV-LPi;0+?-F(>^5#OHX-fPED zCu^l7u3E%STI}c4{J2!)9SUlGP_@!d?5W^QJXOI-Ea`hFMKjR7TluLvzC-ozCPn1`Tpy z!vlv@_Z58ILX6>nDjTp-1LlFMx~-%GA`aJvG$?8*Ihn;mH37eK**rmOEwqegf-Ccx zrIX4;{c~RK>XuTXxYo5kMiWMy)!IC{*DHG@E$hx?RwP@+wuad(P1{@%tRkyJRqD)3 zMHHHZ4boqDn>-=DgR5VlhQTpfVy182Gk;A_S8A1-;U1RR>+$62>(MUx@Nox$vTjHq z%QR=j!6Gdyb5wu7y(YUktwMuW5<@jl?m4cv4BODiT5o8qVdC0MBqGr@-YBIwnpZAY znX9(_uQjP}JJ=!~Ve9#5I~rUnN|P_3D$LqZcvBnywYhjlMSFHm`;u9GPla{5QD7(7*6Tb3Svr8;(nuAd81q$*uq6HC_&~je*Ca7hP4sJp0av{M8480wF zxASi7Qv+~@2U%Nu1Ud;s-G4CTVWIPyx!sg&8ZG0Wq zG_}i3C(6_1>q3w!EH7$Kwq8uBp2F2N7}l65mk1p*9v0&+;th=_E-W)E;w}P(j⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 0 HcmV?d00001 diff --git a/languages/java/gradle/wrapper/gradle-wrapper.properties b/languages/java/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..ac72c34e8 --- /dev/null +++ b/languages/java/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/languages/java/gradlew b/languages/java/gradlew new file mode 100755 index 000000000..0adc8e1a5 --- /dev/null +++ b/languages/java/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/languages/java/gradlew.bat b/languages/java/gradlew.bat new file mode 100644 index 000000000..6689b85be --- /dev/null +++ b/languages/java/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/languages/java/settings.gradle b/languages/java/settings.gradle new file mode 100644 index 000000000..961795f50 --- /dev/null +++ b/languages/java/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'BitwardenSDK' diff --git a/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClient.java b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClient.java new file mode 100644 index 000000000..9e1948184 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClient.java @@ -0,0 +1,87 @@ +package com.bitwarden.sdk; + +import com.bitwarden.sdk.schema.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.sun.jna.Native; +import com.sun.jna.Pointer; + +import java.util.function.Function; + +public class BitwardenClient implements AutoCloseable { + + private final Pointer client; + + private final BitwardenLibrary library; + + private final CommandRunner commandRunner; + + private boolean isClientOpen; + + private final ProjectsClient projects; + + private final SecretsClient secrets; + + public BitwardenClient(BitwardenSettings bitwardenSettings) { + ClientSettings clientSettings = new ClientSettings(); + clientSettings.setAPIURL(bitwardenSettings.getApiUrl()); + clientSettings.setIdentityURL(bitwardenSettings.getIdentityUrl()); + clientSettings.setDeviceType(DeviceType.SDK); + clientSettings.setUserAgent("Bitwarden JAVA-SDK"); + + library = Native.load("bitwarden_c", BitwardenLibrary.class); + + try { + client = library.init(Converter.ClientSettingsToJsonString(clientSettings)); + } catch (JsonProcessingException e) { + throw new BitwardenClientException("Error while processing client settings"); + } + + commandRunner = new CommandRunner(library, client); + projects = new ProjectsClient(commandRunner); + secrets = new SecretsClient(commandRunner); + isClientOpen = true; + } + + static Function throwingFunctionWrapper(ThrowingFunction throwingFunction) { + + return i -> { + try { + return throwingFunction.accept(i); + } catch (Exception ex) { + throw new BitwardenClientException("Response deserialization failed"); + } + }; + } + + public APIKeyLoginResponse accessTokenLogin(String accessToken) { + Command command = new Command(); + AccessTokenLoginRequest accessTokenLoginRequest = new AccessTokenLoginRequest(); + accessTokenLoginRequest.setAccessToken(accessToken); + command.setAccessTokenLogin(accessTokenLoginRequest); + + ResponseForAPIKeyLoginResponse response = commandRunner.runCommand(command, + throwingFunctionWrapper(Converter::ResponseForAPIKeyLoginResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Login failed"); + } + + return response.getData(); + } + + public ProjectsClient projects() { + return projects; + } + + public SecretsClient secrets() { + return secrets; + } + + @Override + public void close() { + if (isClientOpen) { + library.free_mem(client); + isClientOpen = false; + } + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClientException.java b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClientException.java new file mode 100644 index 000000000..7b6025be8 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenClientException.java @@ -0,0 +1,8 @@ +package com.bitwarden.sdk; + +public class BitwardenClientException extends RuntimeException { + + public BitwardenClientException(String message) { + super(message); + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/BitwardenLibrary.java b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenLibrary.java new file mode 100644 index 000000000..73d81452c --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenLibrary.java @@ -0,0 +1,13 @@ +package com.bitwarden.sdk; + +import com.sun.jna.Library; +import com.sun.jna.Pointer; + +public interface BitwardenLibrary extends Library { + + Pointer init(String clientSettings); + + void free_mem(Pointer client); + + String run_command(String command, Pointer client); +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/BitwardenSettings.java b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenSettings.java new file mode 100644 index 000000000..7112297b4 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/BitwardenSettings.java @@ -0,0 +1,32 @@ +package com.bitwarden.sdk; + +public class BitwardenSettings { + + private String apiUrl; + + private String identityUrl; + + public BitwardenSettings() { + } + + public BitwardenSettings(String apiUrl, String identityUrl) { + this.apiUrl = apiUrl; + this.identityUrl = identityUrl; + } + + public String getApiUrl() { + return apiUrl; + } + + public void setApiUrl(String apiUrl) { + this.apiUrl = apiUrl; + } + + public String getIdentityUrl() { + return identityUrl; + } + + public void setIdentityUrl(String identityUrl) { + this.identityUrl = identityUrl; + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/CommandRunner.java b/languages/java/src/main/java/com/bitwarden/sdk/CommandRunner.java new file mode 100644 index 000000000..11a100814 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/CommandRunner.java @@ -0,0 +1,45 @@ +package com.bitwarden.sdk; + +import com.bitwarden.sdk.schema.Command; +import com.bitwarden.sdk.schema.Converter; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sun.jna.Pointer; + +import java.io.IOException; +import java.util.function.Function; + +class CommandRunner { + + private final BitwardenLibrary library; + + private final Pointer client; + + CommandRunner(BitwardenLibrary library, Pointer client) { + this.library = library; + this.client = client; + } + + T runCommand(Command command, Function deserializer) { + String response = null; + + try { + response = library.run_command(commandToString(command), client); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return deserializer.apply(response); + } + + private String commandToString(Command command) throws IOException { + // Removes null properties from the generated converter output to avoid command errors + String inputJson = Converter.CommandToJsonString(command); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + Object inputObject = mapper.readValue(inputJson, Object.class); + return mapper.writeValueAsString(inputObject); + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java b/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java new file mode 100644 index 000000000..f3ad53036 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java @@ -0,0 +1,42 @@ +package com.bitwarden.sdk; + +import com.bitwarden.sdk.schema.*; + +import java.util.UUID; + +public class ExampleProgram { + + public static void main(String[] args) { + BitwardenSettings bitwardenSettings = new BitwardenSettings(); + bitwardenSettings.setApiUrl("https://api.bitwarden.com"); + bitwardenSettings.setIdentityUrl("https://identity.bitwarden.com"); + + try (BitwardenClient bitwardenClient = new BitwardenClient(bitwardenSettings)) { + APIKeyLoginResponse apiKeyLoginResponse = bitwardenClient.accessTokenLogin(""); + + UUID organizationId = UUID.fromString(""); + ProjectResponse projectResponse = bitwardenClient.projects().create(organizationId, "NewTestProject"); + UUID projectId = projectResponse.getID(); + ProjectsResponse projectsResponse = bitwardenClient.projects().list(organizationId); + projectResponse = bitwardenClient.projects().get(projectId); + projectResponse = bitwardenClient.projects().update(projectId, organizationId, "NewTestProject2"); + + String key = "key"; + String value = "value"; + String note = "note"; + SecretResponse secretResponse = bitwardenClient.secrets().create(key, value, note, organizationId, + new UUID[]{projectId}); + UUID secretId = secretResponse.getID(); + SecretIdentifiersResponse secretIdentifiersResponse = bitwardenClient.secrets().list(organizationId); + secretResponse = bitwardenClient.secrets().get(secretId); + key = "key2"; + value = "value2"; + note = "note2"; + secretResponse = bitwardenClient.secrets().update(secretId, key, value, note, organizationId, + new UUID[]{projectId}); + + SecretsDeleteResponse secretsDeleteResponse = bitwardenClient.secrets().delete(new UUID[]{secretId}); + ProjectsDeleteResponse projectsDeleteResponse = bitwardenClient.projects().delete(new UUID[]{projectId}); + } + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/ProjectsClient.java b/languages/java/src/main/java/com/bitwarden/sdk/ProjectsClient.java new file mode 100644 index 000000000..73b87440c --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/ProjectsClient.java @@ -0,0 +1,109 @@ +package com.bitwarden.sdk; + +import com.bitwarden.sdk.schema.*; + +import java.util.UUID; + +public class ProjectsClient { + + private final CommandRunner commandRunner; + + ProjectsClient(CommandRunner commandRunner) { + this.commandRunner = commandRunner; + } + + public ProjectResponse get(UUID id) { + Command command = new Command(); + ProjectsCommand projectsCommand = new ProjectsCommand(); + ProjectGetRequest projectGetRequest = new ProjectGetRequest(); + projectGetRequest.setID(id); + projectsCommand.setGet(projectGetRequest); + command.setProjects(projectsCommand); + + ResponseForProjectResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForProjectResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Project not found"); + } + + return response.getData(); + } + + public ProjectResponse create(UUID organizationId, String name) { + Command command = new Command(); + ProjectsCommand projectsCommand = new ProjectsCommand(); + ProjectCreateRequest projectCreateRequest = new ProjectCreateRequest(); + projectCreateRequest.setOrganizationID(organizationId); + projectCreateRequest.setName(name); + projectsCommand.setCreate(projectCreateRequest); + command.setProjects(projectsCommand); + + ResponseForProjectResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForProjectResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Project create failed"); + } + + return response.getData(); + } + + public ProjectResponse update(UUID id, UUID organizationId, String name) { + Command command = new Command(); + ProjectsCommand projectsCommand = new ProjectsCommand(); + ProjectPutRequest projectPutRequest = new ProjectPutRequest(); + projectPutRequest.setID(id); + projectPutRequest.setOrganizationID(organizationId); + projectPutRequest.setName(name); + projectsCommand.setUpdate(projectPutRequest); + command.setProjects(projectsCommand); + + ResponseForProjectResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForProjectResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Project update failed"); + } + + return response.getData(); + } + + public ProjectsDeleteResponse delete(UUID[] ids) { + Command command = new Command(); + ProjectsCommand projectsCommand = new ProjectsCommand(); + ProjectsDeleteRequest projectsDeleteRequest = new ProjectsDeleteRequest(); + projectsDeleteRequest.setIDS(ids); + projectsCommand.setDelete(projectsDeleteRequest); + command.setProjects(projectsCommand); + + ResponseForProjectsDeleteResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForProjectsDeleteResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? + response.getErrorMessage() : "Projects update failed"); + } + + return response.getData(); + } + + public ProjectsResponse list(UUID organizationId) { + Command command = new Command(); + ProjectsCommand projectsCommand = new ProjectsCommand(); + ProjectsListRequest projectsListRequest = new ProjectsListRequest(); + projectsListRequest.setOrganizationID(organizationId); + projectsCommand.setList(projectsListRequest); + command.setProjects(projectsCommand); + + ResponseForProjectsResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForProjectsResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? + response.getErrorMessage() : "No projects for given organization"); + } + + return response.getData(); + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/SecretsClient.java b/languages/java/src/main/java/com/bitwarden/sdk/SecretsClient.java new file mode 100644 index 000000000..f1a97fdc7 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/SecretsClient.java @@ -0,0 +1,115 @@ +package com.bitwarden.sdk; + +import com.bitwarden.sdk.schema.*; + +import java.util.UUID; + +public class SecretsClient { + + private final CommandRunner commandRunner; + + SecretsClient(CommandRunner commandRunner) { + this.commandRunner = commandRunner; + } + + public SecretResponse get(UUID id) { + Command command = new Command(); + SecretsCommand secretsCommand = new SecretsCommand(); + SecretGetRequest secretGetRequest = new SecretGetRequest(); + secretGetRequest.setID(id); + secretsCommand.setGet(secretGetRequest); + command.setSecrets(secretsCommand); + + ResponseForSecretResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForSecretResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Secret not found"); + } + + return response.getData(); + } + + public SecretResponse create(String key, String value, String note, UUID organizationId, UUID[] projectIds) { + Command command = new Command(); + SecretsCommand secretsCommand = new SecretsCommand(); + SecretCreateRequest secretCreateRequest = new SecretCreateRequest(); + secretCreateRequest.setKey(key); + secretCreateRequest.setValue(value); + secretCreateRequest.setNote(note); + secretCreateRequest.setOrganizationID(organizationId); + secretCreateRequest.setProjectIDS(projectIds); + secretsCommand.setCreate(secretCreateRequest); + command.setSecrets(secretsCommand); + + ResponseForSecretResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForSecretResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Secret create failed"); + } + + return response.getData(); + } + + public SecretResponse update(UUID id, String key, String value, String note, UUID organizationId, + UUID[] projectIds) { + Command command = new Command(); + SecretsCommand secretsCommand = new SecretsCommand(); + SecretPutRequest secretPutRequest = new SecretPutRequest(); + secretPutRequest.setID(id); + secretPutRequest.setKey(key); + secretPutRequest.setValue(value); + secretPutRequest.setNote(note); + secretPutRequest.setOrganizationID(organizationId); + secretPutRequest.setProjectIDS(projectIds); + secretsCommand.setUpdate(secretPutRequest); + command.setSecrets(secretsCommand); + + ResponseForSecretResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForSecretResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Secret update failed"); + } + + return response.getData(); + } + + public SecretsDeleteResponse delete(UUID[] ids) { + Command command = new Command(); + SecretsCommand secretsCommand = new SecretsCommand(); + SecretsDeleteRequest secretsDeleteRequest = new SecretsDeleteRequest(); + secretsDeleteRequest.setIDS(ids); + secretsCommand.setDelete(secretsDeleteRequest); + command.setSecrets(secretsCommand); + + ResponseForSecretsDeleteResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForSecretsDeleteResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? response.getErrorMessage() : "Secrets delete failed"); + } + + return response.getData(); + } + + public SecretIdentifiersResponse list(UUID organizationId) { + Command command = new Command(); + SecretsCommand secretsCommand = new SecretsCommand(); + SecretIdentifiersRequest secretIdentifiersRequest = new SecretIdentifiersRequest(); + secretIdentifiersRequest.setOrganizationID(organizationId); + secretsCommand.setList(secretIdentifiersRequest); + command.setSecrets(secretsCommand); + + ResponseForSecretIdentifiersResponse response = commandRunner.runCommand(command, + BitwardenClient.throwingFunctionWrapper(Converter::ResponseForSecretIdentifiersResponseFromJsonString)); + + if (response == null || !response.getSuccess()) { + throw new BitwardenClientException(response != null ? + response.getErrorMessage() : "No secrets for given organization"); + } + + return response.getData(); + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/ThrowingFunction.java b/languages/java/src/main/java/com/bitwarden/sdk/ThrowingFunction.java new file mode 100644 index 000000000..cab5b1041 --- /dev/null +++ b/languages/java/src/main/java/com/bitwarden/sdk/ThrowingFunction.java @@ -0,0 +1,7 @@ +package com.bitwarden.sdk; + +@FunctionalInterface +public interface ThrowingFunction { + + R accept(T t) throws E; +} diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 148b089e6..7181d6010 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -1,4 +1,10 @@ -import { quicktype, InputData, JSONSchemaInput, FetchingJSONSchemaStore } from "quicktype-core"; +import { + quicktype, + quicktypeMultiFile, + InputData, + JSONSchemaInput, + FetchingJSONSchemaStore, +} from "quicktype-core"; import fs from "fs"; import path from "path"; @@ -63,6 +69,23 @@ async function main() { }); writeToFile("./languages/csharp/Bitwarden.Sdk/schemas.cs", csharp.lines); + + const java = await quicktypeMultiFile({ + inputData, + lang: "java", + rendererOptions: { + package: "com.bitwarden.sdk.schema", + "java-version": "8", + }, + }); + + const javaDir = "./languages/java/src/main/java/com/bitwarden/sdk/schema/"; + if (!fs.existsSync(javaDir)) { + fs.mkdirSync(javaDir); + } + java.forEach((file, path) => { + writeToFile(javaDir + path, file.lines); + }); } main(); From 9f775961f2122555a5fc9e332573281d20a849f7 Mon Sep 17 00:00:00 2001 From: Vladimir Cvetic Date: Thu, 30 Nov 2023 16:25:03 +0100 Subject: [PATCH 072/378] Golang SDK (#218) ## Type of change ``` - [ ] Bug fix - [ x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective The objective is to develop a Golang wrapper for the Bitwarden client that interacts with a native rust library. This is to ensure that a consistent interface is provided, and the details of the Bitwarden rust library can be abstracted away. ## Code changes BitwardenClient.go Defines the BitwardenClient struct with dependencies and submodules for handling projects and secrets. Implements the NewBitwardenClient function that creates a new client. Implements methods for access token login and cleanup. BitwardenLibrary_native.go Implements the BitwardenLibrary interface using cgo for interacting with the native C library. Provides methods for initialization, memory release, and running commands on the client. BitwardenLibrary_custom.go An alternative implementation of the BitwardenLibrary interface, possibly for testing or alternative backends. The code is currently the same as BitwardenLibrary_native.go. CommandRunner.go Implements the CommandRunner struct that takes care of running commands via the library interface. Centralizes command-running logic. Projects.go Implements a Projects struct with methods to create, list, get, update, and delete projects. Utilizes the CommandRunner interface to run these commands. Secrets.go Implements a Secrets struct with methods to create, list, get, update, and delete secrets. Utilizes the CommandRunner interface to run these commands. *Notes* - The code is designed to be modular, separating concerns into different components (like Projects, Secrets, and CommandRunner). - Interfaces are used where possible to make it easier to mock these components for testing. - The native C API is encapsulated neatly, making it easier to switch out or update the underlying library without affecting the rest of the code. --------- Co-authored-by: Boris Bujak Co-authored-by: Boris Bujak --- .github/workflows/generate_schemas.yml | 6 + .github/workflows/golang-release.yml | 73 +++++++++++ .gitignore | 1 + languages/go/README.md | 113 +++++++++++++++++ languages/go/bitwarden_client.go | 63 ++++++++++ languages/go/command_runner.go | 37 ++++++ languages/go/example/example.go | 86 +++++++++++++ languages/go/example/go.mod | 10 ++ languages/go/example/go.sum | 2 + languages/go/go.mod | 5 + languages/go/go.sum | 2 + .../internal/cinterface/bitwarden_library.go | 55 +++++++++ languages/go/project.go | 107 ++++++++++++++++ languages/go/secrets.go | 114 ++++++++++++++++++ languages/go/util.go | 33 +++++ support/scripts/schemas.ts | 11 ++ 16 files changed, 718 insertions(+) create mode 100644 .github/workflows/golang-release.yml create mode 100644 languages/go/README.md create mode 100644 languages/go/bitwarden_client.go create mode 100644 languages/go/command_runner.go create mode 100644 languages/go/example/example.go create mode 100644 languages/go/example/go.mod create mode 100644 languages/go/example/go.sum create mode 100644 languages/go/go.mod create mode 100644 languages/go/go.sum create mode 100644 languages/go/internal/cinterface/bitwarden_library.go create mode 100644 languages/go/project.go create mode 100644 languages/go/secrets.go create mode 100644 languages/go/util.go diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 675f53c1e..7eba684c4 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -64,6 +64,12 @@ jobs: path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error + - name: Upload Go schemas artifact + uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + with: + name: schemas.go + path: ${{ github.workspace }}/languages/go/schema.go + - name: Upload java schemas artifact uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: diff --git a/.github/workflows/golang-release.yml b/.github/workflows/golang-release.yml new file mode 100644 index 000000000..6f41bcd3e --- /dev/null +++ b/.github/workflows/golang-release.yml @@ -0,0 +1,73 @@ +name: Go Release + +on: + workflow_dispatch: + inputs: + version_number: + description: "New Version" + required: true + +env: + GO111MODULE: on + GO_VERSION: "^1.18" + +jobs: + build_rust: + uses: ./.github/workflows/build-rust-cross-platform.yml + + generate-schemas: + uses: ./.github/workflows/generate_schemas.yml + + build: + name: Build + needs: + - build_rust + - generate-schemas + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Go environment + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Cache dependencies + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v ./... + + release: + name: Release + needs: build + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Go environment + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Set release version + run: echo "VERSION=${{ github.event.inputs.version_number }}" >> $GITHUB_ENV + + - name: Install Goreleaser + run: go install github.com/goreleaser/goreleaser@v1.21.2 + + - name: Run Goreleaser + run: goreleaser release --rm-dist --skip-validate + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ env.VERSION }} diff --git a/.gitignore b/.gitignore index 38b074349..37d652453 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,5 @@ crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts languages/csharp/Bitwarden.Sdk/schemas.cs languages/js_webassembly/bitwarden_client/schemas.ts languages/python/BitwardenClient/schemas.py +languages/go/schema.go languages/java/src/main/java/com/bitwarden/sdk/schema diff --git a/languages/go/README.md b/languages/go/README.md new file mode 100644 index 000000000..e57badf7e --- /dev/null +++ b/languages/go/README.md @@ -0,0 +1,113 @@ +# Bitwarden SDK in Go + +This SDK is designed to interact with Bitwarden services in Go. It includes implementations for +managing projects and secrets, as well as a client interface to facilitate operations like login. + +## Prerequisites + +- Go installed +- C environment to run CGO + +## Installation + +Download the SDK files and place them in your Go project directory. + +## Table of Contents + +- [Initialization](#initialization) +- [Login](#login) +- [Projects](#projects) +- [Secrets](#secrets) +- [Close Client](#close-client) + +--- + +### Initialization + +To initialize the client, you need to import the SDK and create a new `BitwardenClient` instance. + +```go +import "github.com/bitwarden/sdk/languages/go" + +bitwardenClient, _ := sdk.NewBitwardenClient(&apiURL, &identityURL) +``` + +--- + +### Login + +To login using an access token: + +```go +apiKeyLogin, err := bitwardenClient.AccessTokenLogin(accessToken) +``` + +--- + +### Projects + +#### Create a Project + +```go +project, err := client.Projects.Create("organization_id", "project_name") +``` + +#### List Projects + +```go +projects, err := client.Projects.List("organization_id") +``` + +#### Update a Project + +```go +project, err := client.Projects.Update("project_id", "organization_id", "new_project_name") +``` + +#### Delete Projects + +```go +project, err := client.Projects.Delete([]string{"project_id_1", "project_id_2"}) +``` + +--- + +### Secrets + +#### Create a Secret + +```go +secret, err := client.Secrets.Create("key", "value", "note", "organization_id", []string{"project_id"}) +``` + +#### List Secrets + +```go +secrets, err := client.Secrets.List("organization_id") +``` + +#### Update a Secret + +```go +secret, err := client.Secrets.Update("secret_id", "new_key", "new_value", "new_note", "organization_id", []string{"project_id"}) +``` + +#### Delete Secrets + +```go +secret, err := client.Secrets.Delete([]string{"secret_id_1", "secret_id_2"}) +``` + +--- + +### Close Client + +To free up resources: + +```go +defer bitwardenClient.Close() +``` + +--- + +For more detailed information, refer to the code comments and method signatures. diff --git a/languages/go/bitwarden_client.go b/languages/go/bitwarden_client.go new file mode 100644 index 000000000..5e1108ce1 --- /dev/null +++ b/languages/go/bitwarden_client.go @@ -0,0 +1,63 @@ +package sdk + +import ( + "encoding/json" + + "github.com/bitwarden/sdk/languages/go/internal/cinterface" +) + +type BitwardenClient struct { + client cinterface.ClientPointer + lib cinterface.BitwardenLibrary + commandRunner CommandRunnerInterface + Projects ProjectsInterface + Secrets SecretsInterface +} + +func NewBitwardenClient(apiURL *string, identityURL *string) (*BitwardenClient, error) { + deviceType := DeviceType("SDK") + userAgent := "Bitwarden GOLANG-SDK" + clientSettings := ClientSettings{ + APIURL: apiURL, + IdentityURL: identityURL, + UserAgent: &userAgent, + DeviceType: &deviceType, + } + + settingsJSON, err := json.Marshal(clientSettings) + if err != nil { + return nil, err + } + + lib := cinterface.NewBitwardenLibrary() + client, err := lib.Init(string(settingsJSON)) + if err != nil { + return nil, err + } + runner := NewCommandRunner(client, lib) + + return &BitwardenClient{ + lib: lib, + client: client, + commandRunner: runner, + Projects: NewProjects(runner), + Secrets: NewSecrets(runner), + }, nil +} + +func (c *BitwardenClient) AccessTokenLogin(accessToken string) error { + req := AccessTokenLoginRequest{AccessToken: accessToken} + command := Command{AccessTokenLogin: &req} + + responseStr, err := c.commandRunner.RunCommand(command) + if err != nil { + return err + } + + var response APIKeyLoginResponse + return checkSuccessAndError(responseStr, &response) +} + +func (c *BitwardenClient) Close() { + c.lib.FreeMem(c.client) +} diff --git a/languages/go/command_runner.go b/languages/go/command_runner.go new file mode 100644 index 000000000..3f79f7149 --- /dev/null +++ b/languages/go/command_runner.go @@ -0,0 +1,37 @@ +package sdk + +import ( + "encoding/json" + + "github.com/bitwarden/sdk/languages/go/internal/cinterface" +) + +type CommandRunnerInterface interface { + RunCommand(command Command) (string, error) +} + +type CommandRunner struct { + client cinterface.ClientPointer + lib cinterface.BitwardenLibrary +} + +func NewCommandRunner(client cinterface.ClientPointer, lib cinterface.BitwardenLibrary) *CommandRunner { + return &CommandRunner{ + client: client, + lib: lib, + } +} + +func (c *CommandRunner) RunCommand(command Command) (string, error) { + commandJSON, err := json.Marshal(command) + if err != nil { + return "", err + } + + responseStr, err := c.lib.RunCommand(string(commandJSON), c.client) + if err != nil { + return "", err + } + + return responseStr, nil +} diff --git a/languages/go/example/example.go b/languages/go/example/example.go new file mode 100644 index 000000000..5935d8002 --- /dev/null +++ b/languages/go/example/example.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "os" + + sdk "github.com/bitwarden/sdk/languages/go" + "github.com/gofrs/uuid" +) + +func main() { + apiURL := os.Getenv("API_URL") + identityURL := os.Getenv("IDENTITY_URL") + + bitwardenClient, _ := sdk.NewBitwardenClient(&apiURL, &identityURL) + + accessToken := os.Getenv("ACCESS_TOKEN") + organizationIDStr := os.Getenv("ORGANIZATION_ID") + projectName := os.Getenv("PROJECT_NAME") + + if projectName == "" { + projectName = "NewTestProject" // default value + } + + err := bitwardenClient.AccessTokenLogin(accessToken) + if err != nil { + panic(err) + } + + organizationID, err := uuid.FromString(organizationIDStr) + if err != nil { + panic(err) + } + + project, err := bitwardenClient.Projects.Create(organizationID.String(), projectName) + if err != nil { + panic(err) + } + fmt.Println(project) + projectID := project.ID + fmt.Println(projectID) + + if _, err = bitwardenClient.Projects.List(organizationID.String()); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Projects.Get(projectID); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Projects.Update(projectID, organizationID.String(), projectName+"2"); err != nil { + panic(err) + } + + key := "key" + value := "value" + note := "note" + + secret, err := bitwardenClient.Secrets.Create(key, value, note, organizationID.String(), []string{projectID}) + if err != nil { + panic(err) + } + secretID := secret.ID + + if _, err = bitwardenClient.Secrets.List(organizationID.String()); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Secrets.Get(secretID); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Secrets.Update(secretID, key, value, note, organizationID.String(), []string{projectID}); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Secrets.Delete([]string{secretID}); err != nil { + panic(err) + } + + if _, err = bitwardenClient.Projects.Delete([]string{projectID}); err != nil { + panic(err) + } + + defer bitwardenClient.Close() +} diff --git a/languages/go/example/go.mod b/languages/go/example/go.mod new file mode 100644 index 000000000..bbde28fd5 --- /dev/null +++ b/languages/go/example/go.mod @@ -0,0 +1,10 @@ +module example + +replace github.com/bitwarden/sdk/languages/go => ../ + +go 1.20 + +require ( + github.com/bitwarden/sdk/languages/go v0.0.0-00010101000000-000000000000 + github.com/gofrs/uuid v4.4.0+incompatible +) diff --git a/languages/go/example/go.sum b/languages/go/example/go.sum new file mode 100644 index 000000000..c0ad68738 --- /dev/null +++ b/languages/go/example/go.sum @@ -0,0 +1,2 @@ +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= diff --git a/languages/go/go.mod b/languages/go/go.mod new file mode 100644 index 000000000..a9e125453 --- /dev/null +++ b/languages/go/go.mod @@ -0,0 +1,5 @@ +module github.com/bitwarden/sdk/languages/go + +go 1.18 + +require github.com/gofrs/uuid v4.4.0+incompatible diff --git a/languages/go/go.sum b/languages/go/go.sum new file mode 100644 index 000000000..c0ad68738 --- /dev/null +++ b/languages/go/go.sum @@ -0,0 +1,2 @@ +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= diff --git a/languages/go/internal/cinterface/bitwarden_library.go b/languages/go/internal/cinterface/bitwarden_library.go new file mode 100644 index 000000000..42327adb2 --- /dev/null +++ b/languages/go/internal/cinterface/bitwarden_library.go @@ -0,0 +1,55 @@ +package cinterface + +import ( + "fmt" + "unsafe" +) + +/* +#cgo LDFLAGS: -lbitwarden_c +#cgo linux LDFLAGS: -L/usr/local/lib -L/usr/lib -L ./lib +#cgo darwin LDFLAGS: -L/usr/local/lib -L/usr/lib -L ./lib +#include +typedef void* ClientPtr; +extern char* run_command(const char *command, ClientPtr client); +extern ClientPtr init(const char *clientSettings); +extern void free_mem(ClientPtr client); +*/ +import "C" + +type ClientPointer struct { + Pointer C.ClientPtr +} + +type BitwardenLibrary interface { + Init(clientSettings string) (ClientPointer, error) + FreeMem(client ClientPointer) + RunCommand(command string, client ClientPointer) (string, error) +} + +type BitwardenLibraryImpl struct{} + +func NewBitwardenLibrary() BitwardenLibrary { + return &BitwardenLibraryImpl{} +} + +func (b *BitwardenLibraryImpl) Init(clientSettings string) (ClientPointer, error) { + ptr := C.init(C.CString(clientSettings)) + if ptr == nil { + return ClientPointer{}, fmt.Errorf("initialization failed") + } + return ClientPointer{Pointer: ptr}, nil +} + +func (b *BitwardenLibraryImpl) FreeMem(client ClientPointer) { + C.free_mem(client.Pointer) +} + +func (b *BitwardenLibraryImpl) RunCommand(command string, client ClientPointer) (string, error) { + cstr := C.run_command(C.CString(command), client.Pointer) + if cstr == nil { + return "", fmt.Errorf("run command failed") + } + defer C.free(unsafe.Pointer(cstr)) + return C.GoString(cstr), nil +} diff --git a/languages/go/project.go b/languages/go/project.go new file mode 100644 index 000000000..24a30a7ac --- /dev/null +++ b/languages/go/project.go @@ -0,0 +1,107 @@ +package sdk + +type ProjectsInterface interface { + Create(organizationID string, name string) (*ProjectResponse, error) + List(organizationID string) (*ProjectsResponse, error) + Get(projectID string) (*ProjectResponse, error) + Update(projectID string, organizationID string, name string) (*ProjectResponse, error) + Delete(projectIDs []string) (*ProjectsDeleteResponse, error) +} + +type Projects struct { + CommandRunner CommandRunnerInterface +} + +func NewProjects(commandRunner CommandRunnerInterface) *Projects { + return &Projects{CommandRunner: commandRunner} +} + +func (p *Projects) Get(id string) (*ProjectResponse, error) { + command := Command{ + Projects: &ProjectsCommand{ + Get: &ProjectGetRequest{ + ID: id, + }, + }, + } + var response ProjectResponse + if err := p.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (p *Projects) Create(organizationID string, name string) (*ProjectResponse, error) { + command := Command{ + Projects: &ProjectsCommand{ + Create: &ProjectCreateRequest{ + OrganizationID: organizationID, + Name: name, + }, + }, + } + + var response ProjectResponse + if err := p.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (p *Projects) List(organizationID string) (*ProjectsResponse, error) { + command := Command{ + Projects: &ProjectsCommand{ + List: &ProjectsListRequest{ + OrganizationID: organizationID, + }, + }, + } + + var response ProjectsResponse + if err := p.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (p *Projects) Update(projectID, organizationID, name string) (*ProjectResponse, error) { + command := Command{ + Projects: &ProjectsCommand{ + Update: &ProjectPutRequest{ + ID: projectID, + OrganizationID: organizationID, + Name: name, + }, + }, + } + + var response ProjectResponse + if err := p.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (p *Projects) Delete(projectIDs []string) (*ProjectsDeleteResponse, error) { + command := Command{ + Projects: &ProjectsCommand{ + Delete: &ProjectsDeleteRequest{ + IDS: projectIDs, + }, + }, + } + + var response ProjectsDeleteResponse + if err := p.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (p *Projects) executeCommand(command Command, target interface{}) error { + responseStr, err := p.CommandRunner.RunCommand(command) + if err != nil { + return err + } + return checkSuccessAndError(responseStr, target) +} diff --git a/languages/go/secrets.go b/languages/go/secrets.go new file mode 100644 index 000000000..e6863c459 --- /dev/null +++ b/languages/go/secrets.go @@ -0,0 +1,114 @@ +package sdk + +type SecretsInterface interface { + Create(key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) + List(organizationID string) (*SecretIdentifiersResponse, error) + Get(secretID string) (*SecretResponse, error) + Update(secretID string, key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) + Delete(secretIDs []string) (*SecretsDeleteResponse, error) +} + +type Secrets struct { + CommandRunner CommandRunnerInterface +} + +func NewSecrets(commandRunner CommandRunnerInterface) *Secrets { + return &Secrets{CommandRunner: commandRunner} +} + +func (s *Secrets) executeCommand(command Command, target interface{}) error { + responseStr, err := s.CommandRunner.RunCommand(command) + if err != nil { + return err + } + return checkSuccessAndError(responseStr, target) +} + +func (s *Secrets) Create(key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + Create: &SecretCreateRequest{ + Key: key, + Value: value, + Note: note, + OrganizationID: organizationID, + ProjectIDS: projectIDs, + }, + }, + } + + var response SecretResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (s *Secrets) List(organizationID string) (*SecretIdentifiersResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + List: &SecretIdentifiersRequest{ + OrganizationID: organizationID, + }, + }, + } + + var response SecretIdentifiersResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (s *Secrets) Get(id string) (*SecretResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + Get: &SecretGetRequest{ + ID: id, + }, + }, + } + + var response SecretResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (s *Secrets) Update(id string, key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + Update: &SecretPutRequest{ + ID: id, + Key: key, + Value: value, + Note: note, + OrganizationID: organizationID, + ProjectIDS: projectIDs, + }, + }, + } + + var response SecretResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + +func (s *Secrets) Delete(ids []string) (*SecretsDeleteResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + Delete: &SecretsDeleteRequest{ + IDS: ids, + }, + }, + } + + var response SecretsDeleteResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} diff --git a/languages/go/util.go b/languages/go/util.go new file mode 100644 index 000000000..01ab3578d --- /dev/null +++ b/languages/go/util.go @@ -0,0 +1,33 @@ +package sdk + +import ( + "encoding/json" + "fmt" +) + +func checkSuccessAndError(responseStr string, v interface{}) error { + var wrapper struct { + Success bool `json:"success"` + ErrorMessage *string `json:"errorMessage"` + Data *json.RawMessage `json:"data"` + } + + err := json.Unmarshal([]byte(responseStr), &wrapper) + if err != nil { + return fmt.Errorf("failed to unmarshal wrapper response: %v", err) + } + + if !wrapper.Success { + if wrapper.ErrorMessage != nil { + return fmt.Errorf("API error: %s", *wrapper.ErrorMessage) + } + return fmt.Errorf("API error: unknown") + } + + err = json.Unmarshal(*wrapper.Data, &v) + if err != nil { + return fmt.Errorf("failed to unmarshal response: %v", err) + } + + return nil +} diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 7181d6010..98c0c39cb 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -70,6 +70,17 @@ async function main() { writeToFile("./languages/csharp/Bitwarden.Sdk/schemas.cs", csharp.lines); + const go = await quicktype({ + inputData, + lang: "go", + rendererOptions: { + package: "sdk", + "just-types-and-package": true, + }, + }); + + writeToFile("./languages/go/schema.go", go.lines); + const java = await quicktypeMultiFile({ inputData, lang: "java", From 0f5f11bc5767b86baa514300fa17262a3b89abf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Slobodan=20Todosijevi=C4=87?= <68587964+slobokv83@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:42:45 +0100 Subject: [PATCH 073/378] Cpp Wrapper for sdk (#259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change ``` - [ ] Bug fix - [x ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implemented C++ library that wraps native C library and exposed its commands through BitwardenClient class. ## Code changes - Implemented BitwardenLibrary for connection with `bitwarden_c` library and its three functions: `init`, `run_command`, and `free_mem` - Implemented CRUD operations for the Projects and Secrets for Bitwarden Secrets Manager using the API - Developed building mechanism that is building C++ dynamic library using `Cmake` - Added example in the `examples` directory - Added documentation in .md files for CRUD operations use, building the dynamic library, and for the client use --------- Co-authored-by: Todosijevic-Slobodan Co-authored-by: Daniel García --- .gitignore | 2 + languages/cpp/CMakeBuild.md | 33 +++++ languages/cpp/CMakeLists.txt | 36 ++++++ languages/cpp/ExampleUse.md | 70 ++++++++++ languages/cpp/README.md | 97 ++++++++++++++ languages/cpp/examples/Wrapper.cpp | 73 +++++++++++ languages/cpp/include/BitwardenClient.h | 36 ++++++ languages/cpp/include/BitwardenLibrary.h | 27 ++++ languages/cpp/include/BitwardenSettings.h | 19 +++ languages/cpp/include/CommandRunner.h | 45 +++++++ languages/cpp/include/Projects.h | 19 +++ languages/cpp/include/Secrets.h | 20 +++ languages/cpp/src/BitwardenClient.cpp | 145 +++++++++++++++++++++ languages/cpp/src/BitwardenLibrary.cpp | 107 ++++++++++++++++ languages/cpp/src/CommandRunner.cpp | 49 +++++++ languages/cpp/src/Projects.cpp | 132 +++++++++++++++++++ languages/cpp/src/Secrets.cpp | 149 ++++++++++++++++++++++ support/scripts/schemas.ts | 16 +++ 18 files changed, 1075 insertions(+) create mode 100644 languages/cpp/CMakeBuild.md create mode 100644 languages/cpp/CMakeLists.txt create mode 100644 languages/cpp/ExampleUse.md create mode 100644 languages/cpp/README.md create mode 100644 languages/cpp/examples/Wrapper.cpp create mode 100644 languages/cpp/include/BitwardenClient.h create mode 100644 languages/cpp/include/BitwardenLibrary.h create mode 100644 languages/cpp/include/BitwardenSettings.h create mode 100644 languages/cpp/include/CommandRunner.h create mode 100644 languages/cpp/include/Projects.h create mode 100644 languages/cpp/include/Secrets.h create mode 100644 languages/cpp/src/BitwardenClient.cpp create mode 100644 languages/cpp/src/BitwardenLibrary.cpp create mode 100644 languages/cpp/src/CommandRunner.cpp create mode 100644 languages/cpp/src/Projects.cpp create mode 100644 languages/cpp/src/Secrets.cpp diff --git a/.gitignore b/.gitignore index 37d652453..007c3e839 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /target .DS_Store .pytest_cache +.vscode/c_cpp_properties.json # Build results [Dd]ebug/ @@ -49,5 +50,6 @@ crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts languages/csharp/Bitwarden.Sdk/schemas.cs languages/js_webassembly/bitwarden_client/schemas.ts languages/python/BitwardenClient/schemas.py +languages/cpp/include/schemas.hpp languages/go/schema.go languages/java/src/main/java/com/bitwarden/sdk/schema diff --git a/languages/cpp/CMakeBuild.md b/languages/cpp/CMakeBuild.md new file mode 100644 index 000000000..4c7c29814 --- /dev/null +++ b/languages/cpp/CMakeBuild.md @@ -0,0 +1,33 @@ +# CMAKE build + +## INTRODUCTION + +Cmake is used to build the c++ Bitwarden client library. Output should be placed in the build directory. The output contains two dynamic libraries: one that we are building `BitwardenClient` and another that the building library uses `bitwarden_c`. + +## PREREQUISITES + +- Cmake installed, minimum version 3.15 +- `schemas.hpp` generated into `include` directory +- installed `nlohmann-json` library +- installed `boost` library + +## BUILD commands + +One should be in the root directory of the c++ wrapper (the same level where is CMakeLists.txt placed). Paths of the three libraries should be placed inside the cmake build command: + +$ mkdir build +$ cd build +$ cmake .. -DNLOHMANN=/path/to/include/nlohmann -DBOOST=/path/to/include/boost -DTARGET=relative/path/to/libbitwarden_c +$ cmake --build . + + + +## Example + +macOS: + +$ mkdir build +$ cd build +$ cmake .. -DNLOHMANN=/opt/hombrew/include -DBOOST=/opt/homebrew/include -DTARGET=../../target/release/libbitwarden_c.dylib +$ cmake --build . + diff --git a/languages/cpp/CMakeLists.txt b/languages/cpp/CMakeLists.txt new file mode 100644 index 000000000..e513a32ed --- /dev/null +++ b/languages/cpp/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.15) +project(BitwardenClient) + +set(CMAKE_CXX_STANDARD 20) + +# Set placeholders to be passed from command line +set(NLOHMANN_JSON_INCLUDE_DIR_PLACEHOLDER ${NLOHMANN}) +set(BOOST_INCLUDE_DIR_PLACEHOLDER ${BOOST}) +set(TARGET_INCLUDE_DIR_PLACEHOLDER ${TARGET}) + +# Specify the locations of nlohmann.json and Boost libraries +find_path(NLOHMANN_JSON_INCLUDE_DIR nlohmann/json.hpp HINTS ${NLOHMANN_JSON_INCLUDE_DIR_PLACEHOLDER}) +find_path(BOOST_INCLUDE_DIR boost/optional.hpp HINTS ${BOOST_INCLUDE_DIR_PLACEHOLDER}) + +# Include directories for library +include_directories(include ${NLOHMANN_JSON_INCLUDE_DIR} ${BOOST_INCLUDE_DIR}) + +# Add library source files +file(GLOB SOURCES "src/*.cpp") + +# Add library source files along with the schemas.cpp file +add_library(BitwardenClient SHARED ${SOURCES} ${SCHEMAS_SOURCE}) + +# Set path for native library loading +set(LIB_BITWARDEN_C "${CMAKE_SOURCE_DIR}/${TARGET}") + +# Copy the library to the build directory before building +add_custom_command( + TARGET BitwardenClient PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${LIB_BITWARDEN_C} + $ +) + +# Link libraries +target_link_libraries(BitwardenClient PRIVATE ${LIB_BITWARDEN_C}) diff --git a/languages/cpp/ExampleUse.md b/languages/cpp/ExampleUse.md new file mode 100644 index 000000000..579cd0e67 --- /dev/null +++ b/languages/cpp/ExampleUse.md @@ -0,0 +1,70 @@ +# EXAMPLES + + +## PREREQUISITES + +### BITWARDEN Libraries +One should have two libraries at the same path: +- `BitwardeClient` +- `bitwarden_c` + +It should look like `libBitwardeClient.dylib` and `libbitwarden_c.dylib` for the macOS. + +For Linux: `libBitwardeClient.so` and `libbitwarden_c.so` +For Windows: `BitwardeClient.dll` and `bitwarden_c.dll` + +### INCLUDE directory + +`include` directory contains: +- `BitwardenLibrary.h` +- `BitwardenClient.h` +- `BitwardenSettings.h` +- `CommandRunner.h` +- `Projects.h` +- `Secrets.h` +- `schemas.hpp` + +### Other libraries +- `nlohmann-json` (https://github.com/nlohmann/json) +- `boost` (https://www.boost.org/) + + +### COMPILING + +One could use g++/clang++ for compiling. +Example of the folder structure (macOS): + +--root + --build + `libBitwardenClient.dylib` + `libbitwarden_c.dylib` + --include + --`BitwardenLibrary.h` + --`BitwardenClient.h` + --`BitwardenSettings.h` + --`CommandRunner.h` + --`Projects.h` + --`Secrets.h` + --`schemas.hpp` + --examples + --`Wrapper.cpp` + + +1. $ export ACCESS_TOKEN=<"access-token"> +2. $ export ORGANIZATION_ID=<"organization-id"> +3. $ export DYLD_LIBRARY_PATH=/path/to/your/library:$DYLD_LIBRARY_PATH + +The last step is neccessary to add the path for the dynamic library (macOS). +For the Linux one should use: +$ export LD_LIBRARY_PATH=/path/to/your/library:$LD_LIBRARY_PATH +For the Windows: +$ set PATH=%PATH%;C:\path\to\your\library + +4. $ cd examples +5. $ clang++ -std=c++20 -I../include -I/path/to/include/nlohmann -I/path/to/include/boost -L../build/ -o MyBitwardenApp Wrapper.cpp -lBitwardenClient -ldl + +for Windows `-ldl` should be excluded, + +The result is `MyBitwardenApp` in the `examples` directory, and one can run it from the `examples` directory: + +6. $ ./MyBitwardenApp diff --git a/languages/cpp/README.md b/languages/cpp/README.md new file mode 100644 index 000000000..23b59ac76 --- /dev/null +++ b/languages/cpp/README.md @@ -0,0 +1,97 @@ +# Bitwarden Secrets Manager SDK + +C++ bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. + +## Create access token + +Review the help documentation on [Access Tokens] + +## Usage code snippets + +### Client settings + +```c++ +// Optional - if not stressed, then default values are used +BitwardenSettings bitwardenSettings; +bitwardenSettings.set_api_url(""); +bitwardenSettings.set_identity_url(""); +``` + + +### Create new Bitwarden client + +```c++ +std::string accessToken = ""; +// Optional - argument in BitwardenClient +BitwardenClient bitwardenClient = BitwardenClient(bitwardenSettings); +bitwardenClient.accessTokenLogin(accessToken); +``` + +### Create new project + +```c++ +boost::uuids::uuid organizationUuid = boost::uuids::string_generator()(""); +ProjectResponse projectResponseCreate = bitwardenClient.createProject(organizationUuid, "TestProject"); +``` + +### List all projects + +```c++ +ProjectsResponse projectResponseList = bitwardenClient.listProjects(organizationUuid); +``` + +### Get project details + +```c++ +boost::uuids::uuid projectId = boost::uuids::string_generator()(projectResponseCreate.get_id()); +ProjectResponse projectResponseGet = bitwardenClient.getProject(projectId); +``` + +### Update project + +```c++ +boost::uuids::uuid projectId = boost::uuids::string_generator()(projectResponseCreate.get_id()); +ProjectResponse projectResponseUpdate = bitwardenClient.updateProject(projectId, organizationUuid, "TestProjectUpdated"); +``` + +### Delete projects + +```c++ +SecretsDeleteResponse secretsDeleteResponse = bitwardenClient.deleteSecrets({secretId}); +``` + +### Add new secret + +```c++ +std::string key = "key"; +std::string value = "value"; +std::string note = "note"; +SecretResponse secretResponseCreate = bitwardenClient.createSecret(key, value, note, organizationUuid, {projectId}); +``` + +### List secrets + +```c++ +SecretIdentifiersResponse secretIdentifiersResponse = bitwardenClient.listSecrets(organizationUuid); +``` + +### Get secret details + +``` +boost::uuids::uuid secretId = boost::uuids::string_generator()(secretResponseCreate.get_id()); +SecretResponse secretResponseGet = bitwardenClient.getSecret(secretId); +``` + +### Update secret +```c++ +SecretResponse secretResponseUpdate = bitwardenClient.updateSecret(secretId, "key2", "value2", "note2", organizationUuid, {projectId}); +``` + +# Delete secrets + +```c++ +SecretsDeleteResponse secretsDeleteResponse = bitwardenClient.deleteSecrets({secretId}); +``` + +[Access Tokens]: https://bitwarden.com/help/access-tokens/ +[Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ diff --git a/languages/cpp/examples/Wrapper.cpp b/languages/cpp/examples/Wrapper.cpp new file mode 100644 index 000000000..df4aa164c --- /dev/null +++ b/languages/cpp/examples/Wrapper.cpp @@ -0,0 +1,73 @@ +#include "BitwardenClient.h" +#include +#include + +int main() { + // Retrieve access token and organization ID from environment variables + const char* accessTokenEnv = std::getenv("ACCESS_TOKEN"); + const char* organizationIdEnv = std::getenv("ORGANIZATION_ID"); + + if (!accessTokenEnv || !organizationIdEnv) { + std::cerr << "Error: Environment variables ACCESS_TOKEN or ORGANIZATION_ID not set." << std::endl; + return 1; + } + + std::string accessToken = accessTokenEnv; + std::string organizationId = organizationIdEnv; + + + + // Optional - commented to use default values + // BitwardenSettings bitwardenSettings; + // bitwardenSettings.set_api_url(""); + // bitwardenSettings.set_identity_url(""); + + // Create a Bitwarden client instance + BitwardenClient bitwardenClient = BitwardenClient(); + // // Access token login + bitwardenClient.accessTokenLogin(accessToken); + // Organization ID + boost::uuids::uuid organizationUuid = boost::uuids::string_generator()(organizationId); + + // // Create a new project + ProjectResponse projectResponseCreate = bitwardenClient.createProject(organizationUuid, "NewTestProject"); + boost::uuids::uuid projectId = boost::uuids::string_generator()(projectResponseCreate.get_id()); + + // List projects + ProjectsResponse projectResponseList = bitwardenClient.listProjects(organizationUuid); + + // Get project details + ProjectResponse projectResponseGet = bitwardenClient.getProject(projectId); + + // Update project + ProjectResponse ProjectResponseUpdate = bitwardenClient.updateProject(projectId, organizationUuid, "NewTestProject2"); + + // Secrets + std::string key = "key"; + std::string value = "value"; + std::string note = "note"; + + // Create a new secret + SecretResponse secretResponseCreate = bitwardenClient.createSecret(key, value, note, organizationUuid, {projectId}); + boost::uuids::uuid secretId = boost::uuids::string_generator()(secretResponseCreate.get_id()); + + // List secrets + SecretIdentifiersResponse secretIdentifiersResponse = bitwardenClient.listSecrets(organizationUuid); + + // Get secret details + SecretResponse secretResponseGet = bitwardenClient.getSecret(secretId); + + // Update secret + key = "key2"; + value = "value2"; + note = "note2"; + SecretResponse responseForSecretResponseUpdate = bitwardenClient.updateSecret(secretId, key, value, note, organizationUuid, {projectId}); + + // Delete secrets + SecretsDeleteResponse secretsDeleteResponse = bitwardenClient.deleteSecrets({secretId}); + + // Delete projects + ProjectsDeleteResponse projectsDeleteResponse = bitwardenClient.deleteProjects({projectId}); + + return 0; +} diff --git a/languages/cpp/include/BitwardenClient.h b/languages/cpp/include/BitwardenClient.h new file mode 100644 index 000000000..a5cf72475 --- /dev/null +++ b/languages/cpp/include/BitwardenClient.h @@ -0,0 +1,36 @@ +#pragma once + +#include "CommandRunner.h" +#include "BitwardenSettings.h" +#include "Projects.h" +#include "Secrets.h" +#include +#include + +class BitwardenClient { +public: + BitwardenClient(const BitwardenSettings& bitwardenSettings = BitwardenSettings()); + ~BitwardenClient(); + + void accessTokenLogin(const std::string& accessToken); + ProjectResponse getProject(const boost::uuids::uuid& id); + ProjectResponse createProject(const boost::uuids::uuid& organizationId, const std::string& name); + ProjectResponse updateProject(const boost::uuids::uuid& id, const boost::uuids::uuid& organizationId, const std::string& name); + ProjectsDeleteResponse deleteProjects(const std::vector& ids); + ProjectsResponse listProjects(const boost::uuids::uuid &organizationId); + SecretResponse getSecret(const boost::uuids::uuid& id); + SecretResponse createSecret(const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds); + SecretResponse updateSecret(const boost::uuids::uuid& id, const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds); + SecretsDeleteResponse deleteSecrets(const std::vector& ids); + SecretIdentifiersResponse listSecrets(const boost::uuids::uuid& organizationId); + +private: + BitwardenLibrary* library; + void* client; + CommandRunner* commandRunner; + Projects projects; + Secrets secrets; + bool isClientOpen; + ClientSettings clientSettings; + +}; diff --git a/languages/cpp/include/BitwardenLibrary.h b/languages/cpp/include/BitwardenLibrary.h new file mode 100644 index 000000000..5fee78726 --- /dev/null +++ b/languages/cpp/include/BitwardenLibrary.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +class BitwardenLibrary { +public: + BitwardenLibrary(const std::string& providedLibraryPath); + ~BitwardenLibrary(); + + void* init(const char* clientSettingsJson); + void free_mem(void* client); + const char* run_command(const char* commandJson, void* client); + +private: +#ifdef _WIN32 + HMODULE libraryHandle; +#else + void* libraryHandle; +#endif +}; + diff --git a/languages/cpp/include/BitwardenSettings.h b/languages/cpp/include/BitwardenSettings.h new file mode 100644 index 000000000..4d075ed0a --- /dev/null +++ b/languages/cpp/include/BitwardenSettings.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class BitwardenSettings { +public: + BitwardenSettings() = default; + ~BitwardenSettings() = default; + + const std::string& get_api_url() const { return api_url; } + void set_api_url(const std::string& value) { api_url = value; } + + const std::string& get_identity_url() const { return identity_url; } + void set_identity_url(const std::string& value) { identity_url = value; } + +private: + std::string api_url; + std::string identity_url; +}; diff --git a/languages/cpp/include/CommandRunner.h b/languages/cpp/include/CommandRunner.h new file mode 100644 index 000000000..9aa6cbe9c --- /dev/null +++ b/languages/cpp/include/CommandRunner.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include "BitwardenLibrary.h" +#include "schemas.hpp" +#include + +using namespace Bitwarden::Sdk; + +class CommandRunner { +public: + CommandRunner(BitwardenLibrary* library, void* client); + + template + R runCommand(const Command& command, Func deserializer); + + + +private: + BitwardenLibrary* library; + void* client; + + std::string commandToString(const Command& command); + nlohmann::json filterNullObjects(const nlohmann::json& input); +}; + +template +R CommandRunner::runCommand(const Command& command, Func deserializer) { + // Serialize the Command object to a JSON string + std::string jsonString = commandToString(command); + const char* jsonCStr = jsonString.c_str(); + const char* response = library->run_command(jsonCStr, client); + + // Deserialize the response using the provided deserializer function + T deserialized = deserializer(response); + + // Unwrap the response and throw an exception if it was not successful + if (!deserialized.get_success()) { + throw std::runtime_error(*deserialized.get_error_message()); + } + + return deserialized.get_data().get(); +} + diff --git a/languages/cpp/include/Projects.h b/languages/cpp/include/Projects.h new file mode 100644 index 000000000..9bef19b9c --- /dev/null +++ b/languages/cpp/include/Projects.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include "CommandRunner.h" + +class Projects { +public: + Projects(CommandRunner* commandRunner); + + ProjectResponse get(const boost::uuids::uuid& id); + ProjectResponse create(const boost::uuids::uuid& organizationId, const std::string& name); + ProjectResponse update(const boost::uuids::uuid& id, const boost::uuids::uuid& organizationId, const std::string& name); + ProjectsDeleteResponse deleteProjects(const std::vector& ids); + ProjectsResponse list(const boost::uuids::uuid& organizationId); + +private: + CommandRunner* commandRunner; +}; diff --git a/languages/cpp/include/Secrets.h b/languages/cpp/include/Secrets.h new file mode 100644 index 000000000..024ec3692 --- /dev/null +++ b/languages/cpp/include/Secrets.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include "CommandRunner.h" + +class Secrets { +public: + Secrets(CommandRunner* commandRunner); + + SecretResponse get(const boost::uuids::uuid& id); + SecretResponse create(const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds); + SecretResponse update(const boost::uuids::uuid& id, const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds); + SecretsDeleteResponse deleteSecrets(const std::vector& ids); + SecretIdentifiersResponse list(const boost::uuids::uuid& organizationId); + +private: + CommandRunner* commandRunner; +}; + diff --git a/languages/cpp/src/BitwardenClient.cpp b/languages/cpp/src/BitwardenClient.cpp new file mode 100644 index 000000000..fef9ea267 --- /dev/null +++ b/languages/cpp/src/BitwardenClient.cpp @@ -0,0 +1,145 @@ +#include "BitwardenClient.h" +#include +#include + +BitwardenClient::BitwardenClient(const BitwardenSettings& bitwardenSettings) + : library(nullptr), commandRunner(nullptr), isClientOpen(false), projects(nullptr), secrets(nullptr) { + + // Set default values for optional strings + boost::optional apiUrl = bitwardenSettings.get_api_url().empty() + ? boost::optional("https://api.bitwarden.com") + : boost::optional(bitwardenSettings.get_api_url()); + + boost::optional identityUrl = bitwardenSettings.get_identity_url().empty() + ? boost::optional("https://identity.bitwarden.com") + : boost::optional(bitwardenSettings.get_identity_url()); + + boost::optional user_agent = boost::optional("Bitwarden CPP-SDK"); + + // Set values in clientSettings + clientSettings.set_device_type(Bitwarden::Sdk::DeviceType::SDK); + clientSettings.set_user_agent(user_agent); + clientSettings.set_api_url(apiUrl); + clientSettings.set_identity_url(identityUrl); + + nlohmann::json jsonClientSettings; + Bitwarden::Sdk::to_json(jsonClientSettings, clientSettings); + + std::string jsonClientSettingsString = jsonClientSettings.dump(); + const char* jsonClientSettingsCStr = jsonClientSettingsString.c_str(); + + try { + library = new BitwardenLibrary("./"); + client = library->init(jsonClientSettingsCStr); + commandRunner = new CommandRunner(library, client); + projects = Projects(commandRunner); + secrets = Secrets(commandRunner); + isClientOpen = true; + } catch (const std::exception& ex) { + std::cerr << "Failed to initialize: " << ex.what() << std::endl; + throw ex; + } +} + +BitwardenClient::~BitwardenClient() { + if (library) { + delete commandRunner; + library->free_mem(client); + delete library; + isClientOpen = false; + } +} + +void BitwardenClient::accessTokenLogin(const std::string& accessToken) { + Command command; + AccessTokenLoginRequest accessTokenLoginRequest; + accessTokenLoginRequest.set_access_token(accessToken); + command.set_access_token_login(accessTokenLoginRequest); + + auto deserializer = [](const char* response) -> ResponseForApiKeyLoginResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForApiKeyLoginResponse loginResponse; + Bitwarden::Sdk::from_json(jsonResponse, loginResponse); + return loginResponse; + }; + try { + commandRunner->runCommand(command, deserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in accessTokenLogin: " << ex.what() << std::endl; + throw ex; + } +} + +ProjectResponse BitwardenClient::getProject(const boost::uuids::uuid& id){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return projects.get(id); +} + +ProjectResponse BitwardenClient::createProject(const boost::uuids::uuid& organizationId, const std::string& name){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return projects.create(organizationId, name); +} + +ProjectResponse BitwardenClient::updateProject(const boost::uuids::uuid& id, const boost::uuids::uuid& organizationId, const std::string& name){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return projects.update(id, organizationId, name); +} + +ProjectsDeleteResponse BitwardenClient::deleteProjects(const std::vector& ids) { + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return projects.deleteProjects(ids); + +} + +ProjectsResponse BitwardenClient::listProjects(const boost::uuids::uuid &organizationId) { + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return projects.list(organizationId); + +} + +SecretResponse BitwardenClient::getSecret(const boost::uuids::uuid& id){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return secrets.get(id); +} + +SecretResponse BitwardenClient::createSecret(const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return secrets.create(key, value, note, organizationId, projectIds); +} + +SecretResponse BitwardenClient::updateSecret(const boost::uuids::uuid& id, const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds){ + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return secrets.update(id, key, value, note, organizationId, projectIds); +} + +SecretsDeleteResponse BitwardenClient::deleteSecrets(const std::vector& ids) { + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return secrets.deleteSecrets(ids); + +} + +SecretIdentifiersResponse BitwardenClient::listSecrets(const boost::uuids::uuid &organizationId) { + if (!isClientOpen) { + throw std::runtime_error("Client is not open."); + } + return secrets.list(organizationId); + +} diff --git a/languages/cpp/src/BitwardenLibrary.cpp b/languages/cpp/src/BitwardenLibrary.cpp new file mode 100644 index 000000000..0af592786 --- /dev/null +++ b/languages/cpp/src/BitwardenLibrary.cpp @@ -0,0 +1,107 @@ +#include "BitwardenLibrary.h" +#include + +BitwardenLibrary::BitwardenLibrary(const std::string& providedLibraryPath) : libraryHandle(nullptr) { + std::string libraryExtension; + std::string libraryNameUnix = "libbitwarden_c"; + std::string libraryNameWin = "bitwarden_c"; +#if defined(_WIN32) + libraryExtension = ".dll"; +#elif defined(__linux__) + libraryExtension = ".so"; +#elif defined(__APPLE__) + libraryExtension = ".dylib"; +#else + // Unsupported platform + std::cerr << "Unsupported platform." << std::endl; + return; +#endif + + // Load the dynamic library +#ifdef _WIN32 + std::string libraryPath = providedLibraryPath + libraryNameWin + libraryExtension; + // Load the dynamic library on Windows + libraryHandle = LoadLibraryA(libraryPath.c_str()); + + if (!libraryHandle) { + std::cerr << "Failed to load the Bitwarden library." << std::endl; + } +#else + std::string libraryPath = providedLibraryPath + libraryNameUnix + libraryExtension; + // Load the dynamic library on Unix-based systems (Linux, macOS) + libraryHandle = dlopen(libraryPath.c_str(), RTLD_NOW); + + if (!libraryHandle) { + std::cerr << "Failed to load the Bitwarden library: " << dlerror() << std::endl; + } +#endif +} + +BitwardenLibrary::~BitwardenLibrary() { + if (libraryHandle) { +#ifdef _WIN32 + FreeLibrary(libraryHandle); +#else + dlclose(libraryHandle); +#endif + } +} + +void* BitwardenLibrary::init(const char* clientSettingsJson) { + typedef void* (*InitFunction)(const char*); + InitFunction initFunction = nullptr; + +#ifdef _WIN32 + // Get the address of the init function on Windows + initFunction = reinterpret_cast(GetProcAddress(libraryHandle, "init")); +#else + // Get the address of the init function on Unix-based systems + initFunction = reinterpret_cast(dlsym(libraryHandle, "init")); +#endif + + if (initFunction) { + return initFunction(clientSettingsJson); + } + + std::cerr << "Failed to load init function from the Bitwarden library: " << std::endl; + return nullptr; +} + +void BitwardenLibrary::free_mem(void* client) { + typedef void (*FreeMemFunction)(void*); + FreeMemFunction freeMemFunction = nullptr; + +#ifdef _WIN32 + // Get the address of the free_mem function on Windows + freeMemFunction = reinterpret_cast(GetProcAddress(libraryHandle, "free_mem")); +#else + // Get the address of the free_mem function on Unix-based systems + freeMemFunction = reinterpret_cast(dlsym(libraryHandle, "free_mem")); +#endif + + if (freeMemFunction) { + freeMemFunction(client); + } else { + std::cerr << "Failed to load free_mem function from the Bitwarden library." << std::endl; + } +} + +const char* BitwardenLibrary::run_command(const char* commandJson, void* client) { + typedef const char* (*RunCommandFunction)(const char*, void*); + RunCommandFunction runCommandFunction = nullptr; + +#ifdef _WIN32 + // Get the address of the run_command function on Windows + runCommandFunction = reinterpret_cast(GetProcAddress(libraryHandle, "run_command")); +#else + // Get the address of the run_command function on Unix-based systems + runCommandFunction = reinterpret_cast(dlsym(libraryHandle, "run_command")); +#endif + + if (runCommandFunction) { + return runCommandFunction(commandJson, client); + } + + std::cerr << "Failed to load run_command function from the Bitwarden library." << std::endl; + return nullptr; +} diff --git a/languages/cpp/src/CommandRunner.cpp b/languages/cpp/src/CommandRunner.cpp new file mode 100644 index 000000000..032347f34 --- /dev/null +++ b/languages/cpp/src/CommandRunner.cpp @@ -0,0 +1,49 @@ +#include "CommandRunner.h" +#include +#include +#include + + +CommandRunner::CommandRunner(BitwardenLibrary* library, void* client) : library(library), client(client) {} + +// Function to recursively filter out objects with all null values +nlohmann::json CommandRunner::filterNullObjects(const nlohmann::json& input) { + nlohmann::json result; + + for (auto it = input.begin(); it != input.end(); ++it) { + if (!it.value().is_null()) { + if (it.value().is_object()) { + // Recursively filter nested objects + json nestedFiltered = filterNullObjects(it.value()); + if (!nestedFiltered.empty()) { + result[it.key()] = nestedFiltered; + } + } else { + result[it.key()] = it.value(); + } + } + } + + return result; +} + +// Implement the commandToString function +std::string CommandRunner::commandToString(const Command& command) { + try { + // Create an nlohmann::json object from the Command object + nlohmann::json jsonCommand; + nlohmann::json filteredJsonCommand; + + Bitwarden::Sdk::to_json(jsonCommand, command); + + filteredJsonCommand = filterNullObjects(jsonCommand); + + // Convert the JSON to a string + std::string jsonCommandString = filteredJsonCommand.dump(); + + return jsonCommandString; + } catch (const std::exception& ex) { + std::cerr << "Error: " << ex.what() << std::endl; + throw ex; + } +} diff --git a/languages/cpp/src/Projects.cpp b/languages/cpp/src/Projects.cpp new file mode 100644 index 000000000..d0aa6ed49 --- /dev/null +++ b/languages/cpp/src/Projects.cpp @@ -0,0 +1,132 @@ +#include "Projects.h" +#include +#include +#include +#include +#include + +Projects::Projects(CommandRunner* commandRunner) : commandRunner(commandRunner) {} + +auto projectsDeserializer = [](const char* response) -> ResponseForProjectResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForProjectResponse projectResponse; + Bitwarden::Sdk::from_json(jsonResponse, projectResponse); + return projectResponse; +}; + +auto deleteProjectsDeserializer = [](const char* response) -> ResponseForProjectsDeleteResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForProjectsDeleteResponse deleteProjectsResponse; + Bitwarden::Sdk::from_json(jsonResponse, deleteProjectsResponse); + return deleteProjectsResponse; +}; + +auto projectListDeserializer = [](const char* response) -> ResponseForProjectsResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForProjectsResponse listResponse; + Bitwarden::Sdk::from_json(jsonResponse, listResponse); + return listResponse; +}; + +ProjectResponse Projects::get(const boost::uuids::uuid& id) { + Command command; + ProjectsCommand projectsCommand; + ProjectGetRequest projectGetRequest; + + std::string idStr = boost::uuids::to_string(id); + projectGetRequest.set_id(idStr); + + projectsCommand.set_get(projectGetRequest); + command.set_projects(projectsCommand); + + try { + return commandRunner->runCommand(command, projectsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in getProject: " << ex.what() << std::endl; + throw ex; + } +} + +ProjectResponse Projects::create(const boost::uuids::uuid& organizationId, const std::string& name) { + Command command; + ProjectsCommand projectsCommand; + ProjectCreateRequest projectCreateRequest; + + std::string orgIdStr = boost::uuids::to_string(organizationId); + projectCreateRequest.set_organization_id(orgIdStr); + + projectCreateRequest.set_name(name); + projectsCommand.set_create(projectCreateRequest); + command.set_projects(projectsCommand); + + try { + return commandRunner->runCommand(command, projectsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in createProject: " << ex.what() << std::endl; + throw ex; + } +} + +ProjectResponse Projects::update(const boost::uuids::uuid& id, const boost::uuids::uuid& organizationId, const std::string& name) { + Command command; + ProjectsCommand projectsCommand; + ProjectPutRequest projectPutRequest; + + std::string idStr = boost::uuids::to_string(id); + projectPutRequest.set_id(idStr); + + std::string orgIdStr = boost::uuids::to_string(organizationId); + projectPutRequest.set_organization_id(orgIdStr); + + projectPutRequest.set_name(name); + projectsCommand.set_update(projectPutRequest); + command.set_projects(projectsCommand); + + try { + return commandRunner->runCommand(command, projectsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in updateProject: " << ex.what() << std::endl; + throw ex; + } +} + +ProjectsDeleteResponse Projects::deleteProjects(const std::vector& ids) { + Command command; + ProjectsCommand projectsCommand; + ProjectsDeleteRequest projectsDeleteRequest; + + std::vector idStrs; + for (const auto& id : ids) { + idStrs.push_back(boost::uuids::to_string(id)); + } + projectsDeleteRequest.set_ids(idStrs); + + projectsCommand.set_projects_command_delete(projectsDeleteRequest); + command.set_projects(projectsCommand); + + try { + return commandRunner->runCommand(command, deleteProjectsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in deleteProjects: " << ex.what() << std::endl; + throw ex; + } +} + +ProjectsResponse Projects::list(const boost::uuids::uuid& organizationId) { + Command command; + ProjectsCommand projectsCommand; + ProjectsListRequest projectsListRequest; + + std::string orgIdStr = boost::uuids::to_string(organizationId); + projectsListRequest.set_organization_id(orgIdStr); + + projectsCommand.set_list(projectsListRequest); + command.set_projects(projectsCommand); + + try { + return commandRunner->runCommand(command, projectListDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in listProjects: " << ex.what() << std::endl; + throw ex; + } +} diff --git a/languages/cpp/src/Secrets.cpp b/languages/cpp/src/Secrets.cpp new file mode 100644 index 000000000..e153ea7f1 --- /dev/null +++ b/languages/cpp/src/Secrets.cpp @@ -0,0 +1,149 @@ +#include "Secrets.h" +#include +#include +#include +#include + +Secrets::Secrets(CommandRunner* commandRunner) : commandRunner(commandRunner) {} + +auto secretsDeserializer = [](const std::string& response) -> ResponseForSecretResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForSecretResponse secretResponse; + Bitwarden::Sdk::from_json(jsonResponse, secretResponse); + return secretResponse; +}; + +auto deleteSecretsDeserializer = [](const std::string& response) -> ResponseForSecretsDeleteResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForSecretsDeleteResponse deleteSecretsResponse; + Bitwarden::Sdk::from_json(jsonResponse, deleteSecretsResponse); + return deleteSecretsResponse; +}; + +auto secretListDeserializer = [](const std::string& response) -> ResponseForSecretIdentifiersResponse { + nlohmann::json jsonResponse = nlohmann::json::parse(response); + ResponseForSecretIdentifiersResponse listResponse; + Bitwarden::Sdk::from_json(jsonResponse, listResponse); + return listResponse; +}; + +SecretResponse Secrets::get(const boost::uuids::uuid& id) { + Command command; + SecretsCommand secretsCommand; + SecretGetRequest secretGetRequest; + + std::string idStr = boost::uuids::to_string(id); + secretGetRequest.set_id(idStr); + + secretsCommand.set_get(secretGetRequest); + command.set_secrets(secretsCommand); + + try { + return commandRunner->runCommand(command, secretsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in getSecret: " << ex.what() << std::endl; + throw ex; + } +} + +SecretResponse Secrets::create(const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds) { + Command command; + SecretsCommand secretsCommand; + SecretCreateRequest secretCreateRequest; + + std::string orgIdStr = boost::uuids::to_string(organizationId); + secretCreateRequest.set_organization_id(orgIdStr); + + secretCreateRequest.set_key(key); + secretCreateRequest.set_value(value); + secretCreateRequest.set_note(note); + + std::vector projectIdsStr; + for (const auto& projectId : projectIds) { + projectIdsStr.push_back(boost::uuids::to_string(projectId)); + } + secretCreateRequest.set_project_ids(projectIdsStr); + + secretsCommand.set_create(secretCreateRequest); + command.set_secrets(secretsCommand); + + try { + return commandRunner->runCommand(command, secretsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in createSecret: " << ex.what() << std::endl; + throw ex; + } +} + +SecretResponse Secrets::update(const boost::uuids::uuid& id, const std::string& key, const std::string& value, const std::string& note, const boost::uuids::uuid& organizationId, const std::vector& projectIds) { + Command command; + SecretsCommand secretsCommand; + SecretPutRequest secretPutRequest; + + std::string idStr = boost::uuids::to_string(id); + secretPutRequest.set_id(idStr); + + std::string orgIdStr = boost::uuids::to_string(organizationId); + secretPutRequest.set_organization_id(orgIdStr); + + secretPutRequest.set_key(key); + secretPutRequest.set_value(value); + secretPutRequest.set_note(note); + + std::vector projectIdsStr; + for (const auto& projectId : projectIds) { + projectIdsStr.push_back(boost::uuids::to_string(projectId)); + } + secretPutRequest.set_project_ids(projectIdsStr); + + secretsCommand.set_update(secretPutRequest); + command.set_secrets(secretsCommand); + + try { + return commandRunner->runCommand(command, secretsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in updateSecret: " << ex.what() << std::endl; + throw ex; + } +} + +SecretsDeleteResponse Secrets::deleteSecrets(const std::vector& ids) { + Command command; + SecretsCommand secretsCommand; + SecretsDeleteRequest secretsDeleteRequest; + + std::vector idsStr; + for (const auto& id : ids) { + idsStr.push_back(boost::uuids::to_string(id)); + } + secretsDeleteRequest.set_ids(idsStr); + + secretsCommand.set_secrets_command_delete(secretsDeleteRequest); + command.set_secrets(secretsCommand); + + try { + return commandRunner->runCommand(command, deleteSecretsDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in deleteSecrets: " << ex.what() << std::endl; + throw ex; + } +} + +SecretIdentifiersResponse Secrets::list(const boost::uuids::uuid& organizationId) { + Command command; + SecretsCommand secretsCommand; + SecretIdentifiersRequest secretIdentifiersRequest; + + std::string orgIdStr = boost::uuids::to_string(organizationId); + secretIdentifiersRequest.set_organization_id(orgIdStr); + + secretsCommand.set_list(secretIdentifiersRequest); + command.set_secrets(secretsCommand); + + try { + return commandRunner->runCommand(command, secretListDeserializer); + } catch (const std::exception& ex) { + std::cerr << "Error in listSecret: " << ex.what() << std::endl; + throw ex; + } +} diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 98c0c39cb..2958efc18 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -70,6 +70,22 @@ async function main() { writeToFile("./languages/csharp/Bitwarden.Sdk/schemas.cs", csharp.lines); + const cpp = await quicktype({ + inputData, + lang: "cpp", + rendererOptions: { + namespace: "Bitwarden::Sdk", + "include-location": "global-include", + }, + }); + + cpp.lines.forEach((line, idx) => { + // Replace DOMAIN for URI_DOMAIN, because DOMAIN is an already defined macro + cpp.lines[idx] = line.replace(/DOMAIN/g, "URI_DOMAIN"); + }); + + writeToFile("./languages/cpp/include/schemas.hpp", cpp.lines); + const go = await quicktype({ inputData, lang: "go", From dd26683bdd9afedb76df4b9705ba3c982d8fbb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 30 Nov 2023 17:29:27 +0100 Subject: [PATCH 074/378] Update uniffi to add comments support (#371) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective This upgrade adds code comments to the generated uniffi code --- Cargo.lock | 63 +++++++++++++++++++++--------- Cargo.toml | 10 ++--- crates/bitwarden-uniffi/Cargo.toml | 4 +- crates/bitwarden/Cargo.toml | 2 +- crates/uniffi-bindgen/Cargo.toml | 2 +- 5 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2a4d3b6aa..50e263401 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2977,6 +2977,12 @@ version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "socket2" version = "0.4.10" @@ -3156,6 +3162,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -3435,6 +3452,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -3458,8 +3481,8 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "camino", @@ -3479,8 +3502,8 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "askama", @@ -3494,6 +3517,7 @@ dependencies = [ "once_cell", "paste", "serde", + "textwrap", "toml 0.5.11", "uniffi_meta", "uniffi_testing", @@ -3502,8 +3526,8 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "camino", @@ -3512,8 +3536,8 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "quote", "syn 2.0.39", @@ -3521,8 +3545,8 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "bytes", @@ -3536,8 +3560,8 @@ dependencies = [ [[package]] name = "uniffi_macros" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "bincode", "camino", @@ -3554,8 +3578,8 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "bytes", @@ -3565,8 +3589,8 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", "camino", @@ -3577,10 +3601,11 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.25.1" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +version = "0.25.2" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", + "textwrap", "uniffi_meta", "uniffi_testing", "weedle2", @@ -3785,7 +3810,7 @@ dependencies = [ [[package]] name = "weedle2" version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=0a03b713306d6ce3de033157fc2ce92a238c2e24#0a03b713306d6ce3de033157fc2ce92a238c2e24" +source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index c7c2906dc..f841f07c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,8 +24,8 @@ codegen-units = 1 # Using git dependency temporarily to add support for immutable records in generated code [patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" } +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } +uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } +uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } +uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } +uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 405642d71..c1a47ea29 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -19,12 +19,12 @@ chrono = { version = ">=0.4.26, <0.5", features = [ ], default-features = false } env_logger = "0.10.1" schemars = { version = ">=0.8, <0.9", optional = true } -uniffi = "=0.25.1" +uniffi = "=0.25.2" bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] -uniffi = { version = "=0.25.1", features = ["build"] } +uniffi = { version = "=0.25.2", features = ["build"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index e52c03723..aea2cfe9e 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -54,7 +54,7 @@ sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" -uniffi = { version = "=0.25.1", optional = true } +uniffi = { version = "=0.25.2", optional = true } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index 825f923e3..cfbb5b554 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.25.1", features = ["cli"] } +uniffi = { version = "=0.25.2", features = ["cli"] } From 9bdce5dafe28f6afb9f0ad8f5f1a2a876befcbee Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 30 Nov 2023 18:05:12 +0100 Subject: [PATCH 075/378] Update swagger (#273) --- README.md | 28 +-- .../.openapi-generator/FILES | 11 +- crates/bitwarden-api-api/README.md | 18 +- .../src/apis/auth_requests_api.rs | 51 ++++++ .../bitwarden-api-api/src/apis/devices_api.rs | 151 +++++++++++----- crates/bitwarden-api-api/src/apis/mod.rs | 3 +- .../src/apis/organization_users_api.rs | 18 +- .../src/apis/organizations_api.rs | 170 ++++++++++++------ .../src/apis/service_accounts_api.rs | 7 +- .../src/models/attachment_response_model.rs | 2 +- .../src/models/billing_customer_discount.rs | 26 +++ .../models/cipher_details_response_model.rs | 3 + .../cipher_mini_details_response_model.rs | 3 + .../src/models/cipher_mini_response_model.rs | 3 + .../src/models/cipher_request_model.rs | 3 + .../src/models/cipher_response_model.rs | 3 + .../models/cipher_with_id_request_model.rs | 3 + .../device_keys_update_request_model.rs | 29 +++ .../src/models/device_response_model.rs | 15 +- .../src/models/event_type.rs | 6 + .../src/models/global_domains.rs | 2 +- crates/bitwarden-api-api/src/models/mod.rs | 22 ++- .../organization_public_key_response_model.rs | 26 +++ ...rganization_subscription_response_model.rs | 3 + ...reset_password_enrollment_request_model.rs | 15 -- .../other_device_keys_update_request_model.rs | 33 ++++ .../models/protected_device_response_model.rs | 44 +++++ ...secrets_manager_subscribe_request_model.rs | 29 +++ ..._account_secrets_details_response_model.rs | 41 +++++ ...ails_response_model_list_response_model.rs | 29 +++ .../src/models/subscription_response_model.rs | 3 + .../update_devices_trust_request_model.rs | 43 +++++ 32 files changed, 669 insertions(+), 174 deletions(-) create mode 100644 crates/bitwarden-api-api/src/models/billing_customer_discount.rs create mode 100644 crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/protected_device_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs diff --git a/README.md b/README.md index 18613d4dc..2de94b09c 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,10 @@ The first step is to generate the swagger documents from the server repository. ```bash # src/Api -dotnet swagger tofile --output ../../api.json .\bin\Debug\net6.0\Api.dll internal +dotnet swagger tofile --output ../../api.json ./bin/Debug/net6.0/Api.dll internal # src/Identity -dotnet swagger tofile --output ../../identity.json .\bin\Debug\net6.0\Identity.dll v1 +ASPNETCORE_ENVIRONMENT=development dotnet swagger tofile --output ../../identity.json ./bin/Debug/net6.0/Identity.dll v1 ``` ### OpenApi Generator @@ -68,20 +68,20 @@ dotnet swagger tofile --output ../../identity.json .\bin\Debug\net6.0\Identity.d Runs from the root of the SDK project. ```bash -npx openapi-generator-cli generate ` - -i ../server/api.json ` - -g rust ` - -o crates/bitwarden-api-api ` - --package-name bitwarden-api-api ` - -t ./support/openapi-template ` +npx openapi-generator-cli generate \ + -i ../server/api.json \ + -g rust \ + -o crates/bitwarden-api-api \ + --package-name bitwarden-api-api \ + -t ./support/openapi-template \ --additional-properties=packageVersion=1.0.0 -npx openapi-generator-cli generate ` - -i ../server/identity.json ` - -g rust ` - -o crates/bitwarden-api-identity ` - --package-name bitwarden-api-identity ` - -t ./support/openapi-template ` +npx openapi-generator-cli generate \ + -i ../server/identity.json \ + -g rust \ + -o crates/bitwarden-api-identity \ + --package-name bitwarden-api-identity \ + -t ./support/openapi-template \ --additional-properties=packageVersion=1.0.0 ``` diff --git a/crates/bitwarden-api-api/.openapi-generator/FILES b/crates/bitwarden-api-api/.openapi-generator/FILES index 4fbc2fbf9..586d4f2db 100644 --- a/crates/bitwarden-api-api/.openapi-generator/FILES +++ b/crates/bitwarden-api-api/.openapi-generator/FILES @@ -69,6 +69,7 @@ src/models/authenticator_attestation_raw_response.rs src/models/base_access_policy_response_model.rs src/models/base_secret_response_model.rs src/models/base_secret_response_model_list_response_model.rs +src/models/billing_customer_discount.rs src/models/billing_history_response_model.rs src/models/billing_invoice.rs src/models/billing_payment_response_model.rs @@ -122,6 +123,7 @@ src/models/collection_with_id_request_model.rs src/models/config_response_model.rs src/models/delete_recover_request_model.rs src/models/device_keys_request_model.rs +src/models/device_keys_update_request_model.rs src/models/device_request_model.rs src/models/device_response_model.rs src/models/device_response_model_list_response_model.rs @@ -201,10 +203,10 @@ src/models/organization_domain_response_model.rs src/models/organization_domain_response_model_list_response_model.rs src/models/organization_domain_sso_details_request_model.rs src/models/organization_domain_sso_details_response_model.rs -src/models/organization_enroll_secrets_manager_request_model.rs src/models/organization_keys_request_model.rs src/models/organization_keys_response_model.rs src/models/organization_license.rs +src/models/organization_public_key_response_model.rs src/models/organization_response_model.rs src/models/organization_seat_request_model.rs src/models/organization_sponsorship_create_request_model.rs @@ -241,6 +243,7 @@ src/models/organization_user_update_request_model.rs src/models/organization_user_user_details_response_model.rs src/models/organization_user_user_details_response_model_list_response_model.rs src/models/organization_verify_bank_request_model.rs +src/models/other_device_keys_update_request_model.rs src/models/password_hint_request_model.rs src/models/password_request_model.rs src/models/payment_method_type.rs @@ -272,6 +275,7 @@ src/models/project_create_request_model.rs src/models/project_response_model.rs src/models/project_response_model_list_response_model.rs src/models/project_update_request_model.rs +src/models/protected_device_response_model.rs src/models/provider_organization_add_request_model.rs src/models/provider_organization_create_request_model.rs src/models/provider_organization_organization_details_response_model.rs @@ -316,6 +320,7 @@ src/models/secret_update_request_model.rs src/models/secret_verification_request_model.rs src/models/secret_with_projects_inner_project.rs src/models/secret_with_projects_list_response_model.rs +src/models/secrets_manager_subscribe_request_model.rs src/models/secrets_manager_subscription_update_request_model.rs src/models/secrets_with_projects_inner_secret.rs src/models/secure_note_type.rs @@ -337,7 +342,8 @@ src/models/service_account_create_request_model.rs src/models/service_account_project_access_policy_response_model.rs src/models/service_account_project_access_policy_response_model_list_response_model.rs src/models/service_account_response_model.rs -src/models/service_account_response_model_list_response_model.rs +src/models/service_account_secrets_details_response_model.rs +src/models/service_account_secrets_details_response_model_list_response_model.rs src/models/service_account_update_request_model.rs src/models/set_key_connector_key_request_model.rs src/models/set_password_request_model.rs @@ -370,6 +376,7 @@ src/models/two_factor_web_authn_request_model.rs src/models/two_factor_web_authn_response_model.rs src/models/two_factor_yubi_key_response_model.rs src/models/update_avatar_request_model.rs +src/models/update_devices_trust_request_model.rs src/models/update_domains_request_model.rs src/models/update_key_request_model.rs src/models/update_profile_request_model.rs diff --git a/crates/bitwarden-api-api/README.md b/crates/bitwarden-api-api/README.md index 255041dc5..43cbc40e8 100644 --- a/crates/bitwarden-api-api/README.md +++ b/crates/bitwarden-api-api/README.md @@ -86,6 +86,7 @@ All URIs are relative to _http://localhost_ | _AccountsApi_ | [**accounts_verify_password_post**](docs/AccountsApi.md#accounts_verify_password_post) | **POST** /accounts/verify-password | | _AccountsBillingApi_ | [**accounts_billing_history_get**](docs/AccountsBillingApi.md#accounts_billing_history_get) | **GET** /accounts/billing/history | | _AccountsBillingApi_ | [**accounts_billing_payment_method_get**](docs/AccountsBillingApi.md#accounts_billing_payment_method_get) | **GET** /accounts/billing/payment-method | +| _AuthRequestsApi_ | [**auth_requests_admin_request_post**](docs/AuthRequestsApi.md#auth_requests_admin_request_post) | **POST** /auth-requests/admin-request | | _AuthRequestsApi_ | [**auth_requests_get**](docs/AuthRequestsApi.md#auth_requests_get) | **GET** /auth-requests | | _AuthRequestsApi_ | [**auth_requests_id_get**](docs/AuthRequestsApi.md#auth_requests_id_get) | **GET** /auth-requests/{id} | | _AuthRequestsApi_ | [**auth_requests_id_put**](docs/AuthRequestsApi.md#auth_requests_id_put) | **PUT** /auth-requests/{id} | @@ -162,7 +163,6 @@ All URIs are relative to _http://localhost_ | _CollectionsApi_ | [**organizations_org_id_collections_id_users_put**](docs/CollectionsApi.md#organizations_org_id_collections_id_users_put) | **PUT** /organizations/{orgId}/collections/{id}/users | | _CollectionsApi_ | [**organizations_org_id_collections_post**](docs/CollectionsApi.md#organizations_org_id_collections_post) | **POST** /organizations/{orgId}/collections | | _ConfigApi_ | [**config_get**](docs/ConfigApi.md#config_get) | **GET** /config | -| _DevicesApi_ | [**devices_exist_by_types_post**](docs/DevicesApi.md#devices_exist_by_types_post) | **POST** /devices/exist-by-types | | _DevicesApi_ | [**devices_get**](docs/DevicesApi.md#devices_get) | **GET** /devices | | _DevicesApi_ | [**devices_id_delete**](docs/DevicesApi.md#devices_id_delete) | **DELETE** /devices/{id} | | _DevicesApi_ | [**devices_id_delete_post**](docs/DevicesApi.md#devices_id_delete_post) | **POST** /devices/{id}/delete | @@ -176,9 +176,11 @@ All URIs are relative to _http://localhost_ | _DevicesApi_ | [**devices_identifier_identifier_token_put**](docs/DevicesApi.md#devices_identifier_identifier_token_put) | **PUT** /devices/identifier/{identifier}/token | | _DevicesApi_ | [**devices_identifier_keys_post**](docs/DevicesApi.md#devices_identifier_keys_post) | **POST** /devices/{identifier}/keys | | _DevicesApi_ | [**devices_identifier_keys_put**](docs/DevicesApi.md#devices_identifier_keys_put) | **PUT** /devices/{identifier}/keys | +| _DevicesApi_ | [**devices_identifier_retrieve_keys_post**](docs/DevicesApi.md#devices_identifier_retrieve_keys_post) | **POST** /devices/{identifier}/retrieve-keys | | _DevicesApi_ | [**devices_knowndevice_email_identifier_get**](docs/DevicesApi.md#devices_knowndevice_email_identifier_get) | **GET** /devices/knowndevice/{email}/{identifier} | | _DevicesApi_ | [**devices_knowndevice_get**](docs/DevicesApi.md#devices_knowndevice_get) | **GET** /devices/knowndevice | | _DevicesApi_ | [**devices_post**](docs/DevicesApi.md#devices_post) | **POST** /devices | +| _DevicesApi_ | [**devices_update_trust_post**](docs/DevicesApi.md#devices_update_trust_post) | **POST** /devices/update-trust | | _EmergencyAccessApi_ | [**emergency_access_granted_get**](docs/EmergencyAccessApi.md#emergency_access_granted_get) | **GET** /emergency-access/granted | | _EmergencyAccessApi_ | [**emergency_access_id_accept_post**](docs/EmergencyAccessApi.md#emergency_access_id_accept_post) | **POST** /emergency-access/{id}/accept | | _EmergencyAccessApi_ | [**emergency_access_id_approve_post**](docs/EmergencyAccessApi.md#emergency_access_id_approve_post) | **POST** /emergency-access/{id}/approve | @@ -304,7 +306,6 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_cancel_post**](docs/OrganizationsApi.md#organizations_id_cancel_post) | **POST** /organizations/{id}/cancel | | _OrganizationsApi_ | [**organizations_id_delete**](docs/OrganizationsApi.md#organizations_id_delete) | **DELETE** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_delete_post**](docs/OrganizationsApi.md#organizations_id_delete_post) | **POST** /organizations/{id}/delete | -| _OrganizationsApi_ | [**organizations_id_enroll_secrets_manager_post**](docs/OrganizationsApi.md#organizations_id_enroll_secrets_manager_post) | **POST** /organizations/{id}/enroll-secrets-manager | | _OrganizationsApi_ | [**organizations_id_get**](docs/OrganizationsApi.md#organizations_id_get) | **GET** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_import_post**](docs/OrganizationsApi.md#organizations_id_import_post) | **POST** /organizations/{id}/import | | _OrganizationsApi_ | [**organizations_id_keys_get**](docs/OrganizationsApi.md#organizations_id_keys_get) | **GET** /organizations/{id}/keys | @@ -313,6 +314,7 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_license_get**](docs/OrganizationsApi.md#organizations_id_license_get) | **GET** /organizations/{id}/license | | _OrganizationsApi_ | [**organizations_id_payment_post**](docs/OrganizationsApi.md#organizations_id_payment_post) | **POST** /organizations/{id}/payment | | _OrganizationsApi_ | [**organizations_id_post**](docs/OrganizationsApi.md#organizations_id_post) | **POST** /organizations/{id} | +| _OrganizationsApi_ | [**organizations_id_public_key_get**](docs/OrganizationsApi.md#organizations_id_public_key_get) | **GET** /organizations/{id}/public-key | | _OrganizationsApi_ | [**organizations_id_put**](docs/OrganizationsApi.md#organizations_id_put) | **PUT** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_reinstate_post**](docs/OrganizationsApi.md#organizations_id_reinstate_post) | **POST** /organizations/{id}/reinstate | | _OrganizationsApi_ | [**organizations_id_rotate_api_key_post**](docs/OrganizationsApi.md#organizations_id_rotate_api_key_post) | **POST** /organizations/{id}/rotate-api-key | @@ -321,6 +323,7 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_sso_get**](docs/OrganizationsApi.md#organizations_id_sso_get) | **GET** /organizations/{id}/sso | | _OrganizationsApi_ | [**organizations_id_sso_post**](docs/OrganizationsApi.md#organizations_id_sso_post) | **POST** /organizations/{id}/sso | | _OrganizationsApi_ | [**organizations_id_storage_post**](docs/OrganizationsApi.md#organizations_id_storage_post) | **POST** /organizations/{id}/storage | +| _OrganizationsApi_ | [**organizations_id_subscribe_secrets_manager_post**](docs/OrganizationsApi.md#organizations_id_subscribe_secrets_manager_post) | **POST** /organizations/{id}/subscribe-secrets-manager | | _OrganizationsApi_ | [**organizations_id_subscription_get**](docs/OrganizationsApi.md#organizations_id_subscription_get) | **GET** /organizations/{id}/subscription | | _OrganizationsApi_ | [**organizations_id_subscription_post**](docs/OrganizationsApi.md#organizations_id_subscription_post) | **POST** /organizations/{id}/subscription | | _OrganizationsApi_ | [**organizations_id_tax_get**](docs/OrganizationsApi.md#organizations_id_tax_get) | **GET** /organizations/{id}/tax | @@ -472,6 +475,7 @@ All URIs are relative to _http://localhost_ - [BaseAccessPolicyResponseModel](docs/BaseAccessPolicyResponseModel.md) - [BaseSecretResponseModel](docs/BaseSecretResponseModel.md) - [BaseSecretResponseModelListResponseModel](docs/BaseSecretResponseModelListResponseModel.md) +- [BillingCustomerDiscount](docs/BillingCustomerDiscount.md) - [BillingHistoryResponseModel](docs/BillingHistoryResponseModel.md) - [BillingInvoice](docs/BillingInvoice.md) - [BillingPaymentResponseModel](docs/BillingPaymentResponseModel.md) @@ -525,6 +529,7 @@ All URIs are relative to _http://localhost_ - [ConfigResponseModel](docs/ConfigResponseModel.md) - [DeleteRecoverRequestModel](docs/DeleteRecoverRequestModel.md) - [DeviceKeysRequestModel](docs/DeviceKeysRequestModel.md) +- [DeviceKeysUpdateRequestModel](docs/DeviceKeysUpdateRequestModel.md) - [DeviceRequestModel](docs/DeviceRequestModel.md) - [DeviceResponseModel](docs/DeviceResponseModel.md) - [DeviceResponseModelListResponseModel](docs/DeviceResponseModelListResponseModel.md) @@ -603,10 +608,10 @@ All URIs are relative to _http://localhost_ - [OrganizationDomainResponseModelListResponseModel](docs/OrganizationDomainResponseModelListResponseModel.md) - [OrganizationDomainSsoDetailsRequestModel](docs/OrganizationDomainSsoDetailsRequestModel.md) - [OrganizationDomainSsoDetailsResponseModel](docs/OrganizationDomainSsoDetailsResponseModel.md) -- [OrganizationEnrollSecretsManagerRequestModel](docs/OrganizationEnrollSecretsManagerRequestModel.md) - [OrganizationKeysRequestModel](docs/OrganizationKeysRequestModel.md) - [OrganizationKeysResponseModel](docs/OrganizationKeysResponseModel.md) - [OrganizationLicense](docs/OrganizationLicense.md) +- [OrganizationPublicKeyResponseModel](docs/OrganizationPublicKeyResponseModel.md) - [OrganizationResponseModel](docs/OrganizationResponseModel.md) - [OrganizationSeatRequestModel](docs/OrganizationSeatRequestModel.md) - [OrganizationSponsorshipCreateRequestModel](docs/OrganizationSponsorshipCreateRequestModel.md) @@ -644,6 +649,7 @@ All URIs are relative to _http://localhost_ - [OrganizationUserUserDetailsResponseModel](docs/OrganizationUserUserDetailsResponseModel.md) - [OrganizationUserUserDetailsResponseModelListResponseModel](docs/OrganizationUserUserDetailsResponseModelListResponseModel.md) - [OrganizationVerifyBankRequestModel](docs/OrganizationVerifyBankRequestModel.md) +- [OtherDeviceKeysUpdateRequestModel](docs/OtherDeviceKeysUpdateRequestModel.md) - [PasswordHintRequestModel](docs/PasswordHintRequestModel.md) - [PasswordRequestModel](docs/PasswordRequestModel.md) - [PaymentMethodType](docs/PaymentMethodType.md) @@ -675,6 +681,7 @@ All URIs are relative to _http://localhost_ - [ProjectResponseModel](docs/ProjectResponseModel.md) - [ProjectResponseModelListResponseModel](docs/ProjectResponseModelListResponseModel.md) - [ProjectUpdateRequestModel](docs/ProjectUpdateRequestModel.md) +- [ProtectedDeviceResponseModel](docs/ProtectedDeviceResponseModel.md) - [ProviderOrganizationAddRequestModel](docs/ProviderOrganizationAddRequestModel.md) - [ProviderOrganizationCreateRequestModel](docs/ProviderOrganizationCreateRequestModel.md) - [ProviderOrganizationOrganizationDetailsResponseModel](docs/ProviderOrganizationOrganizationDetailsResponseModel.md) @@ -719,6 +726,7 @@ All URIs are relative to _http://localhost_ - [SecretVerificationRequestModel](docs/SecretVerificationRequestModel.md) - [SecretWithProjectsInnerProject](docs/SecretWithProjectsInnerProject.md) - [SecretWithProjectsListResponseModel](docs/SecretWithProjectsListResponseModel.md) +- [SecretsManagerSubscribeRequestModel](docs/SecretsManagerSubscribeRequestModel.md) - [SecretsManagerSubscriptionUpdateRequestModel](docs/SecretsManagerSubscriptionUpdateRequestModel.md) - [SecretsWithProjectsInnerSecret](docs/SecretsWithProjectsInnerSecret.md) - [SecureNoteType](docs/SecureNoteType.md) @@ -740,7 +748,8 @@ All URIs are relative to _http://localhost_ - [ServiceAccountProjectAccessPolicyResponseModel](docs/ServiceAccountProjectAccessPolicyResponseModel.md) - [ServiceAccountProjectAccessPolicyResponseModelListResponseModel](docs/ServiceAccountProjectAccessPolicyResponseModelListResponseModel.md) - [ServiceAccountResponseModel](docs/ServiceAccountResponseModel.md) -- [ServiceAccountResponseModelListResponseModel](docs/ServiceAccountResponseModelListResponseModel.md) +- [ServiceAccountSecretsDetailsResponseModel](docs/ServiceAccountSecretsDetailsResponseModel.md) +- [ServiceAccountSecretsDetailsResponseModelListResponseModel](docs/ServiceAccountSecretsDetailsResponseModelListResponseModel.md) - [ServiceAccountUpdateRequestModel](docs/ServiceAccountUpdateRequestModel.md) - [SetKeyConnectorKeyRequestModel](docs/SetKeyConnectorKeyRequestModel.md) - [SetPasswordRequestModel](docs/SetPasswordRequestModel.md) @@ -773,6 +782,7 @@ All URIs are relative to _http://localhost_ - [TwoFactorWebAuthnResponseModel](docs/TwoFactorWebAuthnResponseModel.md) - [TwoFactorYubiKeyResponseModel](docs/TwoFactorYubiKeyResponseModel.md) - [UpdateAvatarRequestModel](docs/UpdateAvatarRequestModel.md) +- [UpdateDevicesTrustRequestModel](docs/UpdateDevicesTrustRequestModel.md) - [UpdateDomainsRequestModel](docs/UpdateDomainsRequestModel.md) - [UpdateKeyRequestModel](docs/UpdateKeyRequestModel.md) - [UpdateProfileRequestModel](docs/UpdateProfileRequestModel.md) diff --git a/crates/bitwarden-api-api/src/apis/auth_requests_api.rs b/crates/bitwarden-api-api/src/apis/auth_requests_api.rs index 476a94129..39c4dd7b4 100644 --- a/crates/bitwarden-api-api/src/apis/auth_requests_api.rs +++ b/crates/bitwarden-api-api/src/apis/auth_requests_api.rs @@ -13,6 +13,13 @@ use reqwest; use super::{configuration, Error}; use crate::apis::ResponseContent; +/// struct for typed errors of method [`auth_requests_admin_request_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum AuthRequestsAdminRequestPostError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`auth_requests_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -48,6 +55,50 @@ pub enum AuthRequestsPostError { UnknownValue(serde_json::Value), } +pub async fn auth_requests_admin_request_post( + configuration: &configuration::Configuration, + auth_request_create_request_model: Option, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/auth-requests/admin-request", + local_var_configuration.base_path + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&auth_request_create_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn auth_requests_get( configuration: &configuration::Configuration, ) -> Result> { diff --git a/crates/bitwarden-api-api/src/apis/devices_api.rs b/crates/bitwarden-api-api/src/apis/devices_api.rs index e7be0685e..95564464a 100644 --- a/crates/bitwarden-api-api/src/apis/devices_api.rs +++ b/crates/bitwarden-api-api/src/apis/devices_api.rs @@ -13,13 +13,6 @@ use reqwest; use super::{configuration, Error}; use crate::apis::ResponseContent; -/// struct for typed errors of method [`devices_exist_by_types_post`] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum DevicesExistByTypesPostError { - UnknownValue(serde_json::Value), -} - /// struct for typed errors of method [`devices_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -111,6 +104,13 @@ pub enum DevicesIdentifierKeysPutError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`devices_identifier_retrieve_keys_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DevicesIdentifierRetrieveKeysPostError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`devices_knowndevice_email_identifier_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -132,48 +132,11 @@ pub enum DevicesPostError { UnknownValue(serde_json::Value), } -pub async fn devices_exist_by_types_post( - configuration: &configuration::Configuration, - device_type: Option>, -) -> Result> { - let local_var_configuration = configuration; - - let local_var_client = &local_var_configuration.client; - - let local_var_uri_str = format!( - "{}/devices/exist-by-types", - local_var_configuration.base_path - ); - let mut local_var_req_builder = - local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); - - if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { - local_var_req_builder = - local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); - } - if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { - local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); - }; - local_var_req_builder = local_var_req_builder.json(&device_type); - - let local_var_req = local_var_req_builder.build()?; - let local_var_resp = local_var_client.execute(local_var_req).await?; - - let local_var_status = local_var_resp.status(); - let local_var_content = local_var_resp.text().await?; - - if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - serde_json::from_str(&local_var_content).map_err(Error::from) - } else { - let local_var_entity: Option = - serde_json::from_str(&local_var_content).ok(); - let local_var_error = ResponseContent { - status: local_var_status, - content: local_var_content, - entity: local_var_entity, - }; - Err(Error::ResponseError(local_var_error)) - } +/// struct for typed errors of method [`devices_update_trust_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DevicesUpdateTrustPostError { + UnknownValue(serde_json::Value), } pub async fn devices_get( @@ -755,6 +718,55 @@ pub async fn devices_identifier_keys_put( } } +pub async fn devices_identifier_retrieve_keys_post( + configuration: &configuration::Configuration, + identifier: &str, + secret_verification_request_model: Option, +) -> Result< + crate::models::ProtectedDeviceResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/devices/{identifier}/retrieve-keys", + local_var_configuration.base_path, + identifier = crate::apis::urlencode(identifier.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&secret_verification_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn devices_knowndevice_email_identifier_get( configuration: &configuration::Configuration, email: &str, @@ -890,3 +902,44 @@ pub async fn devices_post( Err(Error::ResponseError(local_var_error)) } } + +pub async fn devices_update_trust_post( + configuration: &configuration::Configuration, + update_devices_trust_request_model: Option, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/devices/update-trust", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&update_devices_trust_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} diff --git a/crates/bitwarden-api-api/src/apis/mod.rs b/crates/bitwarden-api-api/src/apis/mod.rs index 623d5d0b6..492680582 100644 --- a/crates/bitwarden-api-api/src/apis/mod.rs +++ b/crates/bitwarden-api-api/src/apis/mod.rs @@ -1,5 +1,4 @@ -use std::error; -use std::fmt; +use std::{error, fmt}; #[derive(Debug, Clone)] pub struct ResponseContent { diff --git a/crates/bitwarden-api-api/src/apis/organization_users_api.rs b/crates/bitwarden-api-api/src/apis/organization_users_api.rs index f81290a86..5a8e99916 100644 --- a/crates/bitwarden-api-api/src/apis/organization_users_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_users_api.rs @@ -391,10 +391,7 @@ pub async fn organizations_org_id_users_enable_secrets_manager_patch( configuration: &configuration::Configuration, org_id: uuid::Uuid, organization_user_bulk_request_model: Option, -) -> Result< - crate::models::OrganizationUserBulkResponseModelListResponseModel, - Error, -> { +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; @@ -423,7 +420,7 @@ pub async fn organizations_org_id_users_enable_secrets_manager_patch( let local_var_content = local_var_resp.text().await?; if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - serde_json::from_str(&local_var_content).map_err(Error::from) + Ok(()) } else { let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); @@ -440,10 +437,7 @@ pub async fn organizations_org_id_users_enable_secrets_manager_put( configuration: &configuration::Configuration, org_id: uuid::Uuid, organization_user_bulk_request_model: Option, -) -> Result< - crate::models::OrganizationUserBulkResponseModelListResponseModel, - Error, -> { +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; @@ -472,7 +466,7 @@ pub async fn organizations_org_id_users_enable_secrets_manager_put( let local_var_content = local_var_resp.text().await?; if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - serde_json::from_str(&local_var_content).map_err(Error::from) + Ok(()) } else { let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); @@ -1761,8 +1755,8 @@ pub async fn organizations_org_id_users_revoke_put( pub async fn organizations_org_id_users_user_id_reset_password_enrollment_put( configuration: &configuration::Configuration, - org_id: &str, - user_id: &str, + org_id: uuid::Uuid, + user_id: uuid::Uuid, organization_user_reset_password_enrollment_request_model: Option< crate::models::OrganizationUserResetPasswordEnrollmentRequestModel, >, diff --git a/crates/bitwarden-api-api/src/apis/organizations_api.rs b/crates/bitwarden-api-api/src/apis/organizations_api.rs index 1cd531b2f..6377ef6bf 100644 --- a/crates/bitwarden-api-api/src/apis/organizations_api.rs +++ b/crates/bitwarden-api-api/src/apis/organizations_api.rs @@ -62,13 +62,6 @@ pub enum OrganizationsIdDeletePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_id_enroll_secrets_manager_post`] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum OrganizationsIdEnrollSecretsManagerPostError { - UnknownValue(serde_json::Value), -} - /// struct for typed errors of method [`organizations_id_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -125,6 +118,13 @@ pub enum OrganizationsIdPostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_id_public_key_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsIdPublicKeyGetError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_id_put`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -181,6 +181,13 @@ pub enum OrganizationsIdStoragePostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_id_subscribe_secrets_manager_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsIdSubscribeSecretsManagerPostError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_id_subscription_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -549,55 +556,6 @@ pub async fn organizations_id_delete_post( } } -pub async fn organizations_id_enroll_secrets_manager_post( - configuration: &configuration::Configuration, - id: uuid::Uuid, - organization_enroll_secrets_manager_request_model: Option< - crate::models::OrganizationEnrollSecretsManagerRequestModel, - >, -) -> Result<(), Error> { - let local_var_configuration = configuration; - - let local_var_client = &local_var_configuration.client; - - let local_var_uri_str = format!( - "{}/organizations/{id}/enroll-secrets-manager", - local_var_configuration.base_path, - id = crate::apis::urlencode(id.to_string()) - ); - let mut local_var_req_builder = - local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); - - if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { - local_var_req_builder = - local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); - } - if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { - local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); - }; - local_var_req_builder = - local_var_req_builder.json(&organization_enroll_secrets_manager_request_model); - - let local_var_req = local_var_req_builder.build()?; - let local_var_resp = local_var_client.execute(local_var_req).await?; - - let local_var_status = local_var_resp.status(); - let local_var_content = local_var_resp.text().await?; - - if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - Ok(()) - } else { - let local_var_entity: Option = - serde_json::from_str(&local_var_content).ok(); - let local_var_error = ResponseContent { - status: local_var_status, - content: local_var_content, - entity: local_var_entity, - }; - Err(Error::ResponseError(local_var_error)) - } -} - pub async fn organizations_id_get( configuration: &configuration::Configuration, id: &str, @@ -693,7 +651,7 @@ pub async fn organizations_id_import_post( pub async fn organizations_id_keys_get( configuration: &configuration::Configuration, id: &str, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; @@ -965,6 +923,53 @@ pub async fn organizations_id_post( } } +pub async fn organizations_id_public_key_get( + configuration: &configuration::Configuration, + id: &str, +) -> Result< + crate::models::OrganizationPublicKeyResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{id}/public-key", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_id_put( configuration: &configuration::Configuration, id: &str, @@ -1332,6 +1337,57 @@ pub async fn organizations_id_storage_post( } } +pub async fn organizations_id_subscribe_secrets_manager_post( + configuration: &configuration::Configuration, + id: uuid::Uuid, + secrets_manager_subscribe_request_model: Option< + crate::models::SecretsManagerSubscribeRequestModel, + >, +) -> Result< + crate::models::ProfileOrganizationResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{id}/subscribe-secrets-manager", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&secrets_manager_subscribe_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_id_subscription_get( configuration: &configuration::Configuration, id: &str, diff --git a/crates/bitwarden-api-api/src/apis/service_accounts_api.rs b/crates/bitwarden-api-api/src/apis/service_accounts_api.rs index 511fb3674..47045b475 100644 --- a/crates/bitwarden-api-api/src/apis/service_accounts_api.rs +++ b/crates/bitwarden-api-api/src/apis/service_accounts_api.rs @@ -72,8 +72,9 @@ pub enum ServiceAccountsIdPutError { pub async fn organizations_organization_id_service_accounts_get( configuration: &configuration::Configuration, organization_id: uuid::Uuid, + include_access_to_secrets: Option, ) -> Result< - crate::models::ServiceAccountResponseModelListResponseModel, + crate::models::ServiceAccountSecretsDetailsResponseModelListResponseModel, Error, > { let local_var_configuration = configuration; @@ -88,6 +89,10 @@ pub async fn organizations_organization_id_service_accounts_get( let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + if let Some(ref local_var_str) = include_access_to_secrets { + local_var_req_builder = + local_var_req_builder.query(&[("includeAccessToSecrets", &local_var_str.to_string())]); + } if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); diff --git a/crates/bitwarden-api-api/src/models/attachment_response_model.rs b/crates/bitwarden-api-api/src/models/attachment_response_model.rs index 86637a161..c9066488d 100644 --- a/crates/bitwarden-api-api/src/models/attachment_response_model.rs +++ b/crates/bitwarden-api-api/src/models/attachment_response_model.rs @@ -21,7 +21,7 @@ pub struct AttachmentResponseModel { #[serde(rename = "key", skip_serializing_if = "Option::is_none")] pub key: Option, #[serde(rename = "size", skip_serializing_if = "Option::is_none")] - pub size: Option, + pub size: Option, #[serde(rename = "sizeName", skip_serializing_if = "Option::is_none")] pub size_name: Option, } diff --git a/crates/bitwarden-api-api/src/models/billing_customer_discount.rs b/crates/bitwarden-api-api/src/models/billing_customer_discount.rs new file mode 100644 index 000000000..61f695d70 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/billing_customer_discount.rs @@ -0,0 +1,26 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct BillingCustomerDiscount { + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "active", skip_serializing_if = "Option::is_none")] + pub active: Option, +} + +impl BillingCustomerDiscount { + pub fn new() -> BillingCustomerDiscount { + BillingCustomerDiscount { + id: None, + active: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs index 448712702..289169e41 100644 --- a/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs @@ -51,6 +51,8 @@ pub struct CipherDetailsResponseModel { pub deleted_date: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(rename = "folderId", skip_serializing_if = "Option::is_none")] pub folder_id: Option, #[serde(rename = "favorite", skip_serializing_if = "Option::is_none")] @@ -85,6 +87,7 @@ impl CipherDetailsResponseModel { creation_date: None, deleted_date: None, reprompt: None, + key: None, folder_id: None, favorite: None, edit: None, diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs index 28dafcdbb..1aa5b8e3b 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs @@ -51,6 +51,8 @@ pub struct CipherMiniDetailsResponseModel { pub deleted_date: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(rename = "collectionIds", skip_serializing_if = "Option::is_none")] pub collection_ids: Option>, } @@ -77,6 +79,7 @@ impl CipherMiniDetailsResponseModel { creation_date: None, deleted_date: None, reprompt: None, + key: None, collection_ids: None, } } diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs index 8ea52926d..c96ddfd18 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs @@ -51,6 +51,8 @@ pub struct CipherMiniResponseModel { pub deleted_date: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, } impl CipherMiniResponseModel { @@ -75,6 +77,7 @@ impl CipherMiniResponseModel { creation_date: None, deleted_date: None, reprompt: None, + key: None, } } } diff --git a/crates/bitwarden-api-api/src/models/cipher_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_request_model.rs index 4ac3f62d7..2e445802b 100644 --- a/crates/bitwarden-api-api/src/models/cipher_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_request_model.rs @@ -20,6 +20,8 @@ pub struct CipherRequestModel { pub favorite: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(rename = "name")] pub name: String, #[serde(rename = "notes", skip_serializing_if = "Option::is_none")] @@ -56,6 +58,7 @@ impl CipherRequestModel { folder_id: None, favorite: None, reprompt: None, + key: None, name, notes: None, fields: None, diff --git a/crates/bitwarden-api-api/src/models/cipher_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_response_model.rs index 62a930e1f..59831e6fb 100644 --- a/crates/bitwarden-api-api/src/models/cipher_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_response_model.rs @@ -51,6 +51,8 @@ pub struct CipherResponseModel { pub deleted_date: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(rename = "folderId", skip_serializing_if = "Option::is_none")] pub folder_id: Option, #[serde(rename = "favorite", skip_serializing_if = "Option::is_none")] @@ -83,6 +85,7 @@ impl CipherResponseModel { creation_date: None, deleted_date: None, reprompt: None, + key: None, folder_id: None, favorite: None, edit: None, diff --git a/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs index db4c3604f..093d2e5d9 100644 --- a/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs @@ -20,6 +20,8 @@ pub struct CipherWithIdRequestModel { pub favorite: Option, #[serde(rename = "reprompt", skip_serializing_if = "Option::is_none")] pub reprompt: Option, + #[serde(rename = "key", skip_serializing_if = "Option::is_none")] + pub key: Option, #[serde(rename = "name")] pub name: String, #[serde(rename = "notes", skip_serializing_if = "Option::is_none")] @@ -58,6 +60,7 @@ impl CipherWithIdRequestModel { folder_id: None, favorite: None, reprompt: None, + key: None, name, notes: None, fields: None, diff --git a/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs b/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs new file mode 100644 index 000000000..65d82513c --- /dev/null +++ b/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct DeviceKeysUpdateRequestModel { + #[serde(rename = "encryptedPublicKey")] + pub encrypted_public_key: String, + #[serde(rename = "encryptedUserKey")] + pub encrypted_user_key: String, +} + +impl DeviceKeysUpdateRequestModel { + pub fn new( + encrypted_public_key: String, + encrypted_user_key: String, + ) -> DeviceKeysUpdateRequestModel { + DeviceKeysUpdateRequestModel { + encrypted_public_key, + encrypted_user_key, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/device_response_model.rs b/crates/bitwarden-api-api/src/models/device_response_model.rs index 463d6f104..c6dc76d96 100644 --- a/crates/bitwarden-api-api/src/models/device_response_model.rs +++ b/crates/bitwarden-api-api/src/models/device_response_model.rs @@ -22,15 +22,8 @@ pub struct DeviceResponseModel { pub identifier: Option, #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] pub creation_date: Option, - #[serde(rename = "encryptedUserKey", skip_serializing_if = "Option::is_none")] - pub encrypted_user_key: Option, - #[serde(rename = "encryptedPublicKey", skip_serializing_if = "Option::is_none")] - pub encrypted_public_key: Option, - #[serde( - rename = "encryptedPrivateKey", - skip_serializing_if = "Option::is_none" - )] - pub encrypted_private_key: Option, + #[serde(rename = "isTrusted", skip_serializing_if = "Option::is_none")] + pub is_trusted: Option, } impl DeviceResponseModel { @@ -42,9 +35,7 @@ impl DeviceResponseModel { r#type: None, identifier: None, creation_date: None, - encrypted_user_key: None, - encrypted_public_key: None, - encrypted_private_key: None, + is_trusted: None, } } } diff --git a/crates/bitwarden-api-api/src/models/event_type.rs b/crates/bitwarden-api-api/src/models/event_type.rs index 3988c656f..f0cea8ebc 100644 --- a/crates/bitwarden-api-api/src/models/event_type.rs +++ b/crates/bitwarden-api-api/src/models/event_type.rs @@ -24,6 +24,7 @@ pub enum EventType { Variant1007 = 1007, Variant1008 = 1008, Variant1009 = 1009, + Variant1010 = 1010, Variant1100 = 1100, Variant1101 = 1101, Variant1102 = 1102, @@ -61,6 +62,8 @@ pub enum EventType { Variant1510 = 1510, Variant1511 = 1511, Variant1512 = 1512, + Variant1513 = 1513, + Variant1514 = 1514, Variant1600 = 1600, Variant1601 = 1601, Variant1602 = 1602, @@ -99,6 +102,7 @@ impl ToString for EventType { Self::Variant1007 => String::from("1007"), Self::Variant1008 => String::from("1008"), Self::Variant1009 => String::from("1009"), + Self::Variant1010 => String::from("1010"), Self::Variant1100 => String::from("1100"), Self::Variant1101 => String::from("1101"), Self::Variant1102 => String::from("1102"), @@ -136,6 +140,8 @@ impl ToString for EventType { Self::Variant1510 => String::from("1510"), Self::Variant1511 => String::from("1511"), Self::Variant1512 => String::from("1512"), + Self::Variant1513 => String::from("1513"), + Self::Variant1514 => String::from("1514"), Self::Variant1600 => String::from("1600"), Self::Variant1601 => String::from("1601"), Self::Variant1602 => String::from("1602"), diff --git a/crates/bitwarden-api-api/src/models/global_domains.rs b/crates/bitwarden-api-api/src/models/global_domains.rs index f0582caa4..10a943482 100644 --- a/crates/bitwarden-api-api/src/models/global_domains.rs +++ b/crates/bitwarden-api-api/src/models/global_domains.rs @@ -11,7 +11,7 @@ #[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] pub struct GlobalDomains { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] - pub r#type: Option, + pub r#type: Option, #[serde(rename = "domains", skip_serializing_if = "Option::is_none")] pub domains: Option>, #[serde(rename = "excluded", skip_serializing_if = "Option::is_none")] diff --git a/crates/bitwarden-api-api/src/models/mod.rs b/crates/bitwarden-api-api/src/models/mod.rs index 9d2aa9ae8..db4702827 100644 --- a/crates/bitwarden-api-api/src/models/mod.rs +++ b/crates/bitwarden-api-api/src/models/mod.rs @@ -42,6 +42,8 @@ pub mod base_secret_response_model; pub use self::base_secret_response_model::BaseSecretResponseModel; pub mod base_secret_response_model_list_response_model; pub use self::base_secret_response_model_list_response_model::BaseSecretResponseModelListResponseModel; +pub mod billing_customer_discount; +pub use self::billing_customer_discount::BillingCustomerDiscount; pub mod billing_history_response_model; pub use self::billing_history_response_model::BillingHistoryResponseModel; pub mod billing_invoice; @@ -148,6 +150,8 @@ pub mod delete_recover_request_model; pub use self::delete_recover_request_model::DeleteRecoverRequestModel; pub mod device_keys_request_model; pub use self::device_keys_request_model::DeviceKeysRequestModel; +pub mod device_keys_update_request_model; +pub use self::device_keys_update_request_model::DeviceKeysUpdateRequestModel; pub mod device_request_model; pub use self::device_request_model::DeviceRequestModel; pub mod device_response_model; @@ -304,14 +308,14 @@ pub mod organization_domain_sso_details_request_model; pub use self::organization_domain_sso_details_request_model::OrganizationDomainSsoDetailsRequestModel; pub mod organization_domain_sso_details_response_model; pub use self::organization_domain_sso_details_response_model::OrganizationDomainSsoDetailsResponseModel; -pub mod organization_enroll_secrets_manager_request_model; -pub use self::organization_enroll_secrets_manager_request_model::OrganizationEnrollSecretsManagerRequestModel; pub mod organization_keys_request_model; pub use self::organization_keys_request_model::OrganizationKeysRequestModel; pub mod organization_keys_response_model; pub use self::organization_keys_response_model::OrganizationKeysResponseModel; pub mod organization_license; pub use self::organization_license::OrganizationLicense; +pub mod organization_public_key_response_model; +pub use self::organization_public_key_response_model::OrganizationPublicKeyResponseModel; pub mod organization_response_model; pub use self::organization_response_model::OrganizationResponseModel; pub mod organization_seat_request_model; @@ -386,6 +390,8 @@ pub mod organization_user_user_details_response_model_list_response_model; pub use self::organization_user_user_details_response_model_list_response_model::OrganizationUserUserDetailsResponseModelListResponseModel; pub mod organization_verify_bank_request_model; pub use self::organization_verify_bank_request_model::OrganizationVerifyBankRequestModel; +pub mod other_device_keys_update_request_model; +pub use self::other_device_keys_update_request_model::OtherDeviceKeysUpdateRequestModel; pub mod password_hint_request_model; pub use self::password_hint_request_model::PasswordHintRequestModel; pub mod password_request_model; @@ -448,6 +454,8 @@ pub mod project_response_model_list_response_model; pub use self::project_response_model_list_response_model::ProjectResponseModelListResponseModel; pub mod project_update_request_model; pub use self::project_update_request_model::ProjectUpdateRequestModel; +pub mod protected_device_response_model; +pub use self::protected_device_response_model::ProtectedDeviceResponseModel; pub mod provider_organization_add_request_model; pub use self::provider_organization_add_request_model::ProviderOrganizationAddRequestModel; pub mod provider_organization_create_request_model; @@ -536,6 +544,8 @@ pub mod secret_with_projects_inner_project; pub use self::secret_with_projects_inner_project::SecretWithProjectsInnerProject; pub mod secret_with_projects_list_response_model; pub use self::secret_with_projects_list_response_model::SecretWithProjectsListResponseModel; +pub mod secrets_manager_subscribe_request_model; +pub use self::secrets_manager_subscribe_request_model::SecretsManagerSubscribeRequestModel; pub mod secrets_manager_subscription_update_request_model; pub use self::secrets_manager_subscription_update_request_model::SecretsManagerSubscriptionUpdateRequestModel; pub mod secrets_with_projects_inner_secret; @@ -578,8 +588,10 @@ pub mod service_account_project_access_policy_response_model_list_response_model pub use self::service_account_project_access_policy_response_model_list_response_model::ServiceAccountProjectAccessPolicyResponseModelListResponseModel; pub mod service_account_response_model; pub use self::service_account_response_model::ServiceAccountResponseModel; -pub mod service_account_response_model_list_response_model; -pub use self::service_account_response_model_list_response_model::ServiceAccountResponseModelListResponseModel; +pub mod service_account_secrets_details_response_model; +pub use self::service_account_secrets_details_response_model::ServiceAccountSecretsDetailsResponseModel; +pub mod service_account_secrets_details_response_model_list_response_model; +pub use self::service_account_secrets_details_response_model_list_response_model::ServiceAccountSecretsDetailsResponseModelListResponseModel; pub mod service_account_update_request_model; pub use self::service_account_update_request_model::ServiceAccountUpdateRequestModel; pub mod set_key_connector_key_request_model; @@ -644,6 +656,8 @@ pub mod two_factor_yubi_key_response_model; pub use self::two_factor_yubi_key_response_model::TwoFactorYubiKeyResponseModel; pub mod update_avatar_request_model; pub use self::update_avatar_request_model::UpdateAvatarRequestModel; +pub mod update_devices_trust_request_model; +pub use self::update_devices_trust_request_model::UpdateDevicesTrustRequestModel; pub mod update_domains_request_model; pub use self::update_domains_request_model::UpdateDomainsRequestModel; pub mod update_key_request_model; diff --git a/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs b/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs new file mode 100644 index 000000000..c5849d3e6 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs @@ -0,0 +1,26 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct OrganizationPublicKeyResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "publicKey", skip_serializing_if = "Option::is_none")] + pub public_key: Option, +} + +impl OrganizationPublicKeyResponseModel { + pub fn new() -> OrganizationPublicKeyResponseModel { + OrganizationPublicKeyResponseModel { + object: None, + public_key: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs b/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs index c3789f17a..b08184d43 100644 --- a/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs @@ -102,6 +102,8 @@ pub struct OrganizationSubscriptionResponseModel { pub storage_name: Option, #[serde(rename = "storageGb", skip_serializing_if = "Option::is_none")] pub storage_gb: Option, + #[serde(rename = "discount", skip_serializing_if = "Option::is_none")] + pub discount: Option>, #[serde(rename = "subscription", skip_serializing_if = "Option::is_none")] pub subscription: Option>, #[serde(rename = "upcomingInvoice", skip_serializing_if = "Option::is_none")] @@ -162,6 +164,7 @@ impl OrganizationSubscriptionResponseModel { max_autoscale_sm_service_accounts: None, storage_name: None, storage_gb: None, + discount: None, subscription: None, upcoming_invoice: None, expiration_without_grace_period: None, diff --git a/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs index c21020f96..7287c58a3 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs @@ -10,17 +10,6 @@ #[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] pub struct OrganizationUserResetPasswordEnrollmentRequestModel { - #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] - pub master_password_hash: Option, - #[serde(rename = "otp", skip_serializing_if = "Option::is_none")] - pub otp: Option, - #[serde( - rename = "authRequestAccessCode", - skip_serializing_if = "Option::is_none" - )] - pub auth_request_access_code: Option, - #[serde(rename = "secret", skip_serializing_if = "Option::is_none")] - pub secret: Option, #[serde(rename = "resetPasswordKey", skip_serializing_if = "Option::is_none")] pub reset_password_key: Option, } @@ -28,10 +17,6 @@ pub struct OrganizationUserResetPasswordEnrollmentRequestModel { impl OrganizationUserResetPasswordEnrollmentRequestModel { pub fn new() -> OrganizationUserResetPasswordEnrollmentRequestModel { OrganizationUserResetPasswordEnrollmentRequestModel { - master_password_hash: None, - otp: None, - auth_request_access_code: None, - secret: None, reset_password_key: None, } } diff --git a/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs b/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs new file mode 100644 index 000000000..c163a4343 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs @@ -0,0 +1,33 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct OtherDeviceKeysUpdateRequestModel { + #[serde(rename = "encryptedPublicKey")] + pub encrypted_public_key: String, + #[serde(rename = "encryptedUserKey")] + pub encrypted_user_key: String, + #[serde(rename = "deviceId")] + pub device_id: uuid::Uuid, +} + +impl OtherDeviceKeysUpdateRequestModel { + pub fn new( + encrypted_public_key: String, + encrypted_user_key: String, + device_id: uuid::Uuid, + ) -> OtherDeviceKeysUpdateRequestModel { + OtherDeviceKeysUpdateRequestModel { + encrypted_public_key, + encrypted_user_key, + device_id, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/protected_device_response_model.rs b/crates/bitwarden-api-api/src/models/protected_device_response_model.rs new file mode 100644 index 000000000..f34e1128d --- /dev/null +++ b/crates/bitwarden-api-api/src/models/protected_device_response_model.rs @@ -0,0 +1,44 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct ProtectedDeviceResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, + #[serde(rename = "identifier", skip_serializing_if = "Option::is_none")] + pub identifier: Option, + #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] + pub creation_date: Option, + #[serde(rename = "encryptedUserKey", skip_serializing_if = "Option::is_none")] + pub encrypted_user_key: Option, + #[serde(rename = "encryptedPublicKey", skip_serializing_if = "Option::is_none")] + pub encrypted_public_key: Option, +} + +impl ProtectedDeviceResponseModel { + pub fn new() -> ProtectedDeviceResponseModel { + ProtectedDeviceResponseModel { + object: None, + id: None, + name: None, + r#type: None, + identifier: None, + creation_date: None, + encrypted_user_key: None, + encrypted_public_key: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs b/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs new file mode 100644 index 000000000..2510d8f2c --- /dev/null +++ b/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct SecretsManagerSubscribeRequestModel { + #[serde(rename = "additionalSmSeats")] + pub additional_sm_seats: i32, + #[serde(rename = "additionalServiceAccounts")] + pub additional_service_accounts: i32, +} + +impl SecretsManagerSubscribeRequestModel { + pub fn new( + additional_sm_seats: i32, + additional_service_accounts: i32, + ) -> SecretsManagerSubscribeRequestModel { + SecretsManagerSubscribeRequestModel { + additional_sm_seats, + additional_service_accounts, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs new file mode 100644 index 000000000..5be4d8bb1 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs @@ -0,0 +1,41 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct ServiceAccountSecretsDetailsResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "organizationId", skip_serializing_if = "Option::is_none")] + pub organization_id: Option, + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] + pub creation_date: Option, + #[serde(rename = "revisionDate", skip_serializing_if = "Option::is_none")] + pub revision_date: Option, + #[serde(rename = "accessToSecrets", skip_serializing_if = "Option::is_none")] + pub access_to_secrets: Option, +} + +impl ServiceAccountSecretsDetailsResponseModel { + pub fn new() -> ServiceAccountSecretsDetailsResponseModel { + ServiceAccountSecretsDetailsResponseModel { + object: None, + id: None, + organization_id: None, + name: None, + creation_date: None, + revision_date: None, + access_to_secrets: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs new file mode 100644 index 000000000..5edfbefba --- /dev/null +++ b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct ServiceAccountSecretsDetailsResponseModelListResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "data", skip_serializing_if = "Option::is_none")] + pub data: Option>, + #[serde(rename = "continuationToken", skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, +} + +impl ServiceAccountSecretsDetailsResponseModelListResponseModel { + pub fn new() -> ServiceAccountSecretsDetailsResponseModelListResponseModel { + ServiceAccountSecretsDetailsResponseModelListResponseModel { + object: None, + data: None, + continuation_token: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/subscription_response_model.rs b/crates/bitwarden-api-api/src/models/subscription_response_model.rs index 2ebba2a44..c21cbdbea 100644 --- a/crates/bitwarden-api-api/src/models/subscription_response_model.rs +++ b/crates/bitwarden-api-api/src/models/subscription_response_model.rs @@ -22,6 +22,8 @@ pub struct SubscriptionResponseModel { pub upcoming_invoice: Option>, #[serde(rename = "subscription", skip_serializing_if = "Option::is_none")] pub subscription: Option>, + #[serde(rename = "discount", skip_serializing_if = "Option::is_none")] + pub discount: Option>, #[serde(rename = "license", skip_serializing_if = "Option::is_none")] pub license: Option>, #[serde(rename = "expiration", skip_serializing_if = "Option::is_none")] @@ -39,6 +41,7 @@ impl SubscriptionResponseModel { max_storage_gb: None, upcoming_invoice: None, subscription: None, + discount: None, license: None, expiration: None, using_in_app_purchase: None, diff --git a/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs b/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs new file mode 100644 index 000000000..e4d381d51 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs @@ -0,0 +1,43 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +pub struct UpdateDevicesTrustRequestModel { + #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] + pub master_password_hash: Option, + #[serde(rename = "otp", skip_serializing_if = "Option::is_none")] + pub otp: Option, + #[serde( + rename = "authRequestAccessCode", + skip_serializing_if = "Option::is_none" + )] + pub auth_request_access_code: Option, + #[serde(rename = "secret", skip_serializing_if = "Option::is_none")] + pub secret: Option, + #[serde(rename = "currentDevice")] + pub current_device: Box, + #[serde(rename = "otherDevices", skip_serializing_if = "Option::is_none")] + pub other_devices: Option>, +} + +impl UpdateDevicesTrustRequestModel { + pub fn new( + current_device: crate::models::DeviceKeysUpdateRequestModel, + ) -> UpdateDevicesTrustRequestModel { + UpdateDevicesTrustRequestModel { + master_password_hash: None, + otp: None, + auth_request_access_code: None, + secret: None, + current_device: Box::new(current_device), + other_devices: None, + } + } +} From b51a5d6b522906d277895ee3eb8e893e80744d1d Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 30 Nov 2023 19:00:54 +0100 Subject: [PATCH 076/378] [PM-4272] Expose fingerprint to uniffi (#372) --- crates/bitwarden-uniffi/src/docs.rs | 4 +++ crates/bitwarden-uniffi/src/lib.rs | 6 ++++ crates/bitwarden-uniffi/src/platform/mod.rs | 16 +++++++++ crates/bitwarden/src/client/client.rs | 2 +- .../src/platform/generate_fingerprint.rs | 1 + languages/kotlin/doc.md | 33 +++++++++++++++++++ support/docs/docs.ts | 1 + 7 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 crates/bitwarden-uniffi/src/platform/mod.rs diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index 45fabb0b7..d66c78002 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -2,6 +2,7 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, client::kdf::Kdf, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, + platform::FingerprintRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, vault::{ Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, @@ -34,6 +35,9 @@ pub enum DocRef { // Exporters ExportFormat(ExportFormat), + // Platform + FingerprintRequest(FingerprintRequest), + // Auth MasterPasswordPolicyOptions(MasterPasswordPolicyOptions), diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 5035f22b9..13253d9a6 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -9,6 +9,7 @@ use bitwarden::client::client_settings::ClientSettings; pub mod auth; pub mod crypto; mod error; +pub mod platform; pub mod tool; mod uniffi_support; pub mod vault; @@ -18,6 +19,7 @@ pub mod docs; use crypto::ClientCrypto; use error::Result; +use platform::ClientPlatform; use tool::ClientGenerators; use vault::ClientVault; @@ -42,6 +44,10 @@ impl Client { Arc::new(ClientVault(self)) } + pub fn platform(self: Arc) -> Arc { + Arc::new(ClientPlatform(self)) + } + /// Generator operations pub fn generators(self: Arc) -> Arc { Arc::new(ClientGenerators(self)) diff --git a/crates/bitwarden-uniffi/src/platform/mod.rs b/crates/bitwarden-uniffi/src/platform/mod.rs new file mode 100644 index 000000000..f4eaaa095 --- /dev/null +++ b/crates/bitwarden-uniffi/src/platform/mod.rs @@ -0,0 +1,16 @@ +use std::sync::Arc; + +use bitwarden::platform::FingerprintRequest; + +use crate::{error::Result, Client}; + +#[derive(uniffi::Object)] +pub struct ClientPlatform(pub(crate) Arc); + +#[uniffi::export] +impl ClientPlatform { + /// Fingerprint + pub async fn fingerprint(&self, req: FingerprintRequest) -> Result { + Ok(self.0 .0.read().await.fingerprint(&req)?.fingerprint) + } +} diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 960ca9bda..5133a5c01 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -262,7 +262,7 @@ impl Client { } #[cfg(feature = "internal")] - pub fn fingerprint(&mut self, input: &FingerprintRequest) -> Result { + pub fn fingerprint(&self, input: &FingerprintRequest) -> Result { generate_fingerprint(input) } } diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index 800d6e847..e9562ab34 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -7,6 +7,7 @@ use crate::{crypto::fingerprint, error::Result, util::BASE64_ENGINE}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct FingerprintRequest { /// The input material, used in the fingerprint generation process. pub fingerprint_material: String, diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index fd65c7b71..652e09813 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -327,6 +327,19 @@ Decrypt password history **Output**: std::result::Result +## ClientPlatform + +### `fingerprint` + +Fingerprint + +**Arguments**: + +- self: +- req: [FingerprintRequest](#fingerprintrequest) + +**Output**: std::result::Result + ## ClientSends ### `encrypt` @@ -818,6 +831,26 @@ implementations. +## `FingerprintRequest` + + + + + + + + + + + + + + + + + +
KeyTypeDescription
fingerprintMaterialstringThe input material, used in the fingerprint generation process.
publicKeystringThe user's public key encoded with base64.
+ ## `Folder` diff --git a/support/docs/docs.ts b/support/docs/docs.ts index 14603dd57..b547b4502 100644 --- a/support/docs/docs.ts +++ b/support/docs/docs.ts @@ -28,6 +28,7 @@ const rootElements = [ "ClientFolders", "ClientGenerators", "ClientPasswordHistory", + "ClientPlatform", "ClientSends", "ClientVault", ]; From b6c6532c441990e1c87bd9817449b1c128154377 Mon Sep 17 00:00:00 2001 From: Milos Trifunovic Date: Thu, 30 Nov 2023 19:36:04 +0100 Subject: [PATCH 077/378] Ruby SDK (#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change ``` - [ ] Bug fix - [ x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Ruby wrapper for Bitwarden SDK. ## Code changes First version which introduces basic functionality to interact with projects and clients. --------- Co-authored-by: Milos Trifunovic Co-authored-by: Miloš Trifunović <84377717+milost77@users.noreply.github.com> Co-authored-by: Oscar Hinton Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> Co-authored-by: Daniel García --- .github/workflows/generate_schemas.yml | 7 + .github/workflows/publish-ruby.yml | 88 +++++++++++++ languages/ruby/.gitignore | 3 + languages/ruby/CHANGELOG.md | 5 + languages/ruby/README.md | 95 ++++++++++++++ languages/ruby/bitwarden_sdk/Rakefile | 8 ++ .../ruby/bitwarden_sdk/bitwarden-sdk.gemspec | 47 +++++++ .../ruby/bitwarden_sdk/lib/bitwarden-sdk.rb | 56 ++++++++ .../ruby/bitwarden_sdk/lib/bitwarden_error.rb | 9 ++ .../ruby/bitwarden_sdk/lib/bitwarden_lib.rb | 35 +++++ .../ruby/bitwarden_sdk/lib/command_runner.rb | 15 +++ .../lib/extended_schemas/schemas.rb | 64 +++++++++ languages/ruby/bitwarden_sdk/lib/projects.rb | 116 ++++++++++++++++ languages/ruby/bitwarden_sdk/lib/secrets.rb | 124 ++++++++++++++++++ languages/ruby/bitwarden_sdk/lib/version.rb | 5 + .../ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs | 13 ++ .../bitwarden_sdk/sig/bitwarden_settings.rbs | 8 ++ .../ruby/bitwarden_sdk/sig/command_runner.rbs | 4 + .../bitwarden_sdk/sig/projects_client.rbs | 17 +++ languages/ruby/bitwarden_sdk/sig/sdk.rbs | 3 + .../ruby/bitwarden_sdk/sig/secrets_client.rbs | 18 +++ languages/ruby/examples/example.rb | 67 ++++++++++ sig/bitwarden_sdk/bitwarden_client.rbs | 5 + support/scripts/schemas.ts | 10 ++ 24 files changed, 822 insertions(+) create mode 100644 .github/workflows/publish-ruby.yml create mode 100644 languages/ruby/.gitignore create mode 100644 languages/ruby/CHANGELOG.md create mode 100644 languages/ruby/README.md create mode 100644 languages/ruby/bitwarden_sdk/Rakefile create mode 100644 languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec create mode 100644 languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/command_runner.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/projects.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/secrets.rb create mode 100644 languages/ruby/bitwarden_sdk/lib/version.rb create mode 100644 languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs create mode 100644 languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs create mode 100644 languages/ruby/bitwarden_sdk/sig/command_runner.rbs create mode 100644 languages/ruby/bitwarden_sdk/sig/projects_client.rbs create mode 100644 languages/ruby/bitwarden_sdk/sig/sdk.rbs create mode 100644 languages/ruby/bitwarden_sdk/sig/secrets_client.rbs create mode 100644 languages/ruby/examples/example.rb create mode 100644 sig/bitwarden_sdk/bitwarden_client.rbs diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 7eba684c4..b0517ea36 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -57,6 +57,13 @@ jobs: path: ${{ github.workspace }}/languages/python/BitwardenClient/schemas.py if-no-files-found: error + - name: Upload ruby schemas artifact + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: schemas.rb + path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb + if-no-files-found: error + - name: Upload json schemas artifact uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml new file mode 100644 index 000000000..da641dce5 --- /dev/null +++ b/.github/workflows/publish-ruby.yml @@ -0,0 +1,88 @@ +name: Publish Ruby SDK + +on: + pull_request: + branches: + - master + +jobs: + generate_schemas: + uses: ./.github/workflows/generate_schemas.yml + + build_rust: + uses: ./.github/workflows/build-rust-cross-platform.yml + + build_ruby: + name: Build Ruby + runs-on: ubuntu-22.04 + needs: + - generate_schemas + - build_rust + steps: + - name: Checkout Repository + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Set up Ruby + uses: ruby/setup-ruby@54a18e26dbbb1eabc604f317ade9a5788dddef81 # v1.159.0 + with: + ruby-version: 3.2 + + - name: Download Ruby schemas artifact + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: schemas.rb + path: languages/ruby/bitwarden_sdk/lib + + - name: Download x86_64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-apple-darwin + path: temp/macos-x64 + + - name: Download aarch64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-aarch64-apple-darwin + path: temp/macos-arm64 + + - name: Download x86_64-unknown-linux-gnu files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-unknown-linux-gnu + path: temp/ubuntu-x64 + + - name: Download x86_64-pc-windows-msvc files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-pc-windows-msvc + path: temp/windows-x64 + + - name: Copy lib files + run: | + mkdir -p languages/ruby/bitwarden_sdk/lib/macos-arm64 + mkdir -p languages/ruby/bitwarden_sdk/lib/ubuntu-x64 + mkdir -p languages/ruby/bitwarden_sdk/lib/macos-x64 + mkdir -p languages/ruby/bitwarden_sdk/lib/windows-x64 + + platforms=("macos-arm64" "ubuntu-x64" "macos-x64" "windows-x64") + files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") + + for ((i=0; i<${#platforms[@]}; i++)); do + cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk/lib/${platforms[$i]}/${files[$i]}" + done + shell: bash + + - name: Build gem + run: gem build bitwarden-sdk.gemspec + working-directory: languages/ruby/bitwarden_sdk + + - name: Push gem to Rubygems + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem push *.gem + env: + GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }} + working-directory: languages/ruby/bitwarden_sdk diff --git a/languages/ruby/.gitignore b/languages/ruby/.gitignore new file mode 100644 index 000000000..f0e7bd4c1 --- /dev/null +++ b/languages/ruby/.gitignore @@ -0,0 +1,3 @@ +*.lock +*.gem +bitwarden_sdk/lib/schemas.rb diff --git a/languages/ruby/CHANGELOG.md b/languages/ruby/CHANGELOG.md new file mode 100644 index 000000000..91c5ee3c2 --- /dev/null +++ b/languages/ruby/CHANGELOG.md @@ -0,0 +1,5 @@ +## [Unreleased] + +## [0.1.0] - 2023-09-19 + +- Initial release diff --git a/languages/ruby/README.md b/languages/ruby/README.md new file mode 100644 index 000000000..d02d5c500 --- /dev/null +++ b/languages/ruby/README.md @@ -0,0 +1,95 @@ +# Bitwarden Secrets Manager SDK + +Ruby bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. + +## Installation + +Requirements: Ruby >= 3.0 + +Install gem: `gem install bitwarden-sdk` + +Import it: require 'bitwarden-sdk' + + +## Usage + +To interact with client first you need to obtain access token from Bitwarden. +Client will be initialized with default client settings if they are not provided +via env variables. + +```ruby +require 'bitwarden-sdk' + +# then you can initialize BitwardenSettings: +bitwarden_settings = BitwardenSDK::BitwardenSettings.new( + 'https://api.bitwarden.com', + 'https://identity.bitwarden.com' +) + +# By passing these setting you can initialize BitwardenClient + +bw_client = BitwardenSDK::BitwardenClient.new(bitwarden_settings) +response = bw_client.access_token_login(token) +puts response +``` + +After successful authorization you can interact with client to manage your projects and secrets. +```ruby + +# CREATE project +project_name = 'Test project 1' +response = bw_client.project_client.create_project(project_name, organization_id) +puts response +project_id = response['id'] + +# GET project +response = bw_client.project_client.get(project_id) +puts response + +# LIST projects +response = bw_client.project_client.list_projects(organization_id) +puts response + +# UPDATE projects +name = 'Updated test project 1' +response = bw_client.project_client.update_project(project_id, name, organization_id) +puts response + +# DELETE project +response = bw_client.project_client.delete_projects([project_id]) +puts response +``` + +Similarly, you interact with secrets: +```ruby +# CREATE secret +key = 'AWS-SES' +note = 'Private account' +value = '8t27.dfj;' +response = bw_client.secrets_client.create(key, note, organization_id, [project_id], value) +puts response +secret_id = response['id'] + +# GET secret +response = bw_client.secrets_client.get(secret_id) +puts response + +# GET secret by ids +response = bw_client.secrets_client.get_by_ids([secret_id]) +puts response + +# LIST secrets +response = bw_client.secrets_client.list(organization_id) +puts response + +# UPDATE secret +note = 'updated password' +value = '7I.ert10AjK' +response = bw_client.secrets_client.update(secret_id, key, note,organization_id, [project_id], value) +puts response + +# DELETE secret +response = bw_client.secrets_client.delete_secret([secret_id]) +puts response +``` +[Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ diff --git a/languages/ruby/bitwarden_sdk/Rakefile b/languages/ruby/bitwarden_sdk/Rakefile new file mode 100644 index 000000000..192414345 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/Rakefile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require "bundler/gem_tasks" +require "rubocop/rake_task" + +RuboCop::RakeTask.new + +task default: :rubocop diff --git a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec new file mode 100644 index 000000000..12a4f5fdc --- /dev/null +++ b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require_relative 'lib/version' + +Gem::Specification.new do |spec| + spec.name = 'bitwarden-sdk' + spec.version = BitwardenSDK::VERSION + spec.authors = ['Bitwarden Inc.'] + spec.email = ['hello@bitwarden_sdk.com'] + + spec.summary = 'Bitwarden Secrets Manager SDK.' + spec.description = 'Ruby wrapper for Bitwarden secrets manager SDK.' + spec.homepage = 'https://bitwarden.com/products/secrets-manager/' + spec.required_ruby_version = '>= 3.0.0' + + spec.metadata['homepage_uri'] = spec.homepage + spec.metadata['source_code_uri'] = 'https://github.com/bitwarden/sdk' + spec.metadata['changelog_uri'] = 'https://github.com/bitwarden/sdk/blob/master/languages/ruby/CHANGELOG.md' + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(__dir__) do + `git ls-files -z`.split("\x0").reject do |f| + (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor]) + end + end + + spec.files += Dir.glob('lib/ubuntu-x64/**/*') + spec.files += Dir.glob('lib/macos-x64/**/*') + spec.files += Dir.glob('lib/windows-x64/**/*') + spec.files += Dir.glob('lib/macos-arm64/**/*') + spec.files += Dir.glob('lib/schemas.rb') + + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ['lib'] + + # Uncomment to register a new dependency of your gem + # spec.add_dependency "example-gem", "~> 1.0" + spec.add_dependency 'dry-struct', '~> 1.6' + spec.add_dependency 'dry-types', '~> 1.7' + spec.add_dependency 'ffi', '~> 1.15' + spec.add_dependency 'json', '~> 2.6' + spec.add_dependency 'rake', '~> 13.0' + spec.add_dependency 'rubocop', '~> 1.21' + +end diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb b/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb new file mode 100644 index 000000000..c2ce7e576 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'json' +require 'dry-types' + +require_relative 'schemas' +require_relative 'extended_schemas/schemas' +require_relative 'command_runner' +require_relative 'bitwarden_lib' +require_relative 'bitwarden_error' +require_relative 'projects' +require_relative 'secrets' + +module BitwardenSDK + class BitwardenSettings + attr_accessor :api_url, :identity_url + + def initialize(api_url, identity_url) + # if api_url.nil? || identity_url.nil? + # raise ArgumentError, "api_url and identity_url cannot be nil" + # end + + @api_url = api_url + @identity_url = identity_url + end + end + + class BitwardenClient + attr_reader :bitwarden, :project_client, :secrets_client + + def initialize(bitwarden_settings) + client_settings = ClientSettings.new( + api_url: bitwarden_settings.api_url, + identity_url: bitwarden_settings.identity_url, + user_agent: 'Bitwarden RUBY-SDK', + device_type: nil + ) + + @bitwarden = BitwardenLib + @handle = @bitwarden.init(client_settings.to_json) + @command_runner = CommandRunner.new(@bitwarden, @handle) + @project_client = ProjectsClient.new(@command_runner) + @secrets_client = SecretsClient.new(@command_runner) + end + + def access_token_login(access_token) + access_token_request = AccessTokenLoginRequest.new(access_token: access_token) + @command_runner.run(SelectiveCommand.new(access_token_login: access_token_request)) + nil + end + + def free_mem + @bitwarden.free_mem(@handle) + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb b/languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb new file mode 100644 index 000000000..ec9adf932 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module BitwardenSDK + class BitwardenError < StandardError + def initialize(message = 'Error getting response') + super(message) + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb b/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb new file mode 100644 index 000000000..e09541788 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'ffi' + +module BitwardenSDK + module BitwardenLib + extend FFI::Library + + def self.mac_with_intel? + `uname -m`.strip == 'x86_64' + end + + ffi_lib case RUBY_PLATFORM + when /darwin/ + local_file = if mac_with_intel? + File.expand_path('macos-x64/libbitwarden_c.dylib', __dir__) + else + File.expand_path('macos-arm64/libbitwarden_c.dylib', __dir__) + end + File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.dylib', __dir__) + when /linux/ + local_file = File.expand_path('ubuntu-x64/libbitwarden_c.so', __dir__) + File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.so', __dir__) + when /mswin|mingw/ + local_file = File.expand_path('windows-x64/bitwarden_c.dll', __dir__) + File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/bitwarden_c.dll', __dir__) + else + raise "Unsupported platform: #{RUBY_PLATFORM}" + end + + attach_function :init, [:string], :pointer + attach_function :run_command, %i[string pointer], :string + attach_function :free_mem, [:pointer], :void + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/command_runner.rb b/languages/ruby/bitwarden_sdk/lib/command_runner.rb new file mode 100644 index 000000000..7da2269b6 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/command_runner.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module BitwardenSDK + class CommandRunner + def initialize(bitwarden_sdk, handle) + @bitwarden_sdk = bitwarden_sdk + @handle = handle + end + + # @param [Dry-Struct] cmd + def run(cmd) + @bitwarden_sdk.run_command(cmd.to_json, @handle) + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb b/languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb new file mode 100644 index 000000000..be7ca2cbc --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb @@ -0,0 +1,64 @@ + +module BitwardenSDK + class SelectiveCommand < Command + attribute :password_login, PasswordLoginRequest.optional.default(nil) + attribute :api_key_login, APIKeyLoginRequest.optional.default(nil) + attribute :access_token_login, AccessTokenLoginRequest.optional.default(nil) + attribute :get_user_api_key, SecretVerificationRequest.optional.default(nil) + attribute :fingerprint, FingerprintRequest.optional.default(nil) + attribute :sync, SyncRequest.optional.default(nil) + attribute :secrets, SecretsCommand.optional.default(nil) + attribute :projects, ProjectsCommand.optional.default(nil) + + def to_dynamic + { + "passwordLogin" => password_login&.to_dynamic, + "apiKeyLogin" => api_key_login&.to_dynamic, + "accessTokenLogin" => access_token_login&.to_dynamic, + "getUserApiKey" => get_user_api_key&.to_dynamic, + "fingerprint" => fingerprint&.to_dynamic, + "sync" => sync&.to_dynamic, + "secrets" => secrets&.to_dynamic, + "projects" => projects&.to_dynamic, + }.compact + end + end + + class SelectiveProjectsCommand < ProjectsCommand + attribute :get, ProjectGetRequest.optional.default(nil) + attribute :create, ProjectCreateRequest.optional.default(nil) + attribute :list, ProjectsListRequest.optional.default(nil) + attribute :update, ProjectPutRequest.optional.default(nil) + attribute :delete, ProjectsDeleteRequest.optional.default(nil) + + def to_dynamic + { + "get" => get&.to_dynamic, + "create" => create&.to_dynamic, + "list" => list&.to_dynamic, + "update" => update&.to_dynamic, + "delete" => delete&.to_dynamic, + }.compact + end + end + + class SelectiveSecretsCommand < SecretsCommand + attribute :get, SecretGetRequest.optional.default(nil) + attribute :get_by_ids, SecretsGetRequest.optional.default(nil) + attribute :create, SecretCreateRequest.optional.default(nil) + attribute :list, SecretIdentifiersRequest.optional.default(nil) + attribute :update, SecretPutRequest.optional.default(nil) + attribute :delete, SecretsDeleteRequest.optional.default(nil) + + def to_dynamic + { + "get" => get&.to_dynamic, + "getByIds" => get_by_ids&.to_dynamic, + "create" => create&.to_dynamic, + "list" => list&.to_dynamic, + "update" => update&.to_dynamic, + "delete" => delete&.to_dynamic, + }.compact + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/projects.rb b/languages/ruby/bitwarden_sdk/lib/projects.rb new file mode 100644 index 000000000..4363fcb9e --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/projects.rb @@ -0,0 +1,116 @@ +# frozen_string_literal: true + +require_relative 'bitwarden_error' + +module BitwardenSDK + class ProjectsClient + def initialize(command_runner) + @command_runner = command_runner + end + + def create_project(project_name, organization_id) + project_create_request = ProjectCreateRequest.new( + project_create_request_name: project_name, + organization_id: organization_id + ) + command = create_command( + create: project_create_request + ) + response = parse_response(command) + + projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic + + if projects_response.key?('success') && projects_response['success'] == true && + projects_response.key?('data') + return projects_response['data'] + end + + error_response(projects_response) + end + + def get(project_id) + project_get_request = ProjectGetRequest.new(id: project_id) + command = create_command(get: project_get_request) + response = parse_response(command) + + projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic + + if projects_response.key?('success') && projects_response['success'] == true && + projects_response.key?('data') + return projects_response['data'] + end + + error_response(projects_response) + end + + def list_projects(organization_id) + project_list_request = ProjectsListRequest.new(organization_id: organization_id) + command = create_command(list: project_list_request) + response = parse_response(command) + + projects_response = ResponseForProjectsResponse.from_json!(response).to_dynamic + + if projects_response.key?('success') && projects_response['success'] == true && + projects_response.key?('data') && projects_response['data'].key?('data') + return projects_response['data']['data'] + end + + error_response(projects_response) + end + + def update_project(id, project_put_request_name, organization_id) + project_put_request = ProjectPutRequest.new( + id: id, + project_put_request_name: project_put_request_name, + organization_id: organization_id + ) + command = create_command( + update: project_put_request + ) + response = parse_response(command) + + projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic + + if projects_response.key?('success') && projects_response['success'] == true && + projects_response.key?('data') + return projects_response['data'] + end + + error_response(projects_response) + end + + def delete_projects(ids) + project_delete_request = ProjectsDeleteRequest.new(ids: ids) + command = create_command(delete: project_delete_request) + response = parse_response(command) + + projects_response = ResponseForProjectsDeleteResponse.from_json!(response).to_dynamic + + if projects_response.key?('success') && projects_response['success'] == true && + projects_response.key?('data') && projects_response['data'].key?('data') + return projects_response['data']['data'] + end + + error_response(projects_response) + end + + private + + def error_response(response) + raise BitwardenError, response['errorMessage'] if response.key?('errorMessage') + + raise BitwardenError, 'Error while getting response' + end + + def create_command(commands) + SelectiveCommand.new(projects: SelectiveProjectsCommand.new(commands)) + end + + def parse_response(command) + response = @command_runner.run(command) + raise BitwardenError, 'Error getting response' if response.nil? + + response + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/secrets.rb b/languages/ruby/bitwarden_sdk/lib/secrets.rb new file mode 100644 index 000000000..0eca98993 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/secrets.rb @@ -0,0 +1,124 @@ +# frozen_string_literal: true + +require 'json' + +module BitwardenSDK + class SecretsClient + def initialize(command_runner) + @command_runner = command_runner + end + + def get(id) + command = create_command(get: SecretGetRequest.new(id: id)) + response = run_command(command) + + secrets_response = ResponseForSecretResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') + return secrets_response['data'] + end + + error_response(secrets_response) + end + + def get_by_ids(ids) + command = create_command(get_by_ids: SecretsGetRequest.new(ids: ids)) + response = run_command(command) + + secrets_response = ResponseForSecretIdentifiersResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') && secrets_response['data'].key?('data') + return secrets_response['data']['data'] + end + + error_response(secrets_response) + end + + def create(key, note, organization_id, project_ids, value) + command = create_command( + create: SecretCreateRequest.new( + key: key, note: note, organization_id: organization_id, project_ids: project_ids, value: value + ) + ) + response = run_command(command) + + secrets_response = ResponseForSecretResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') + return secrets_response['data'] + end + + error_response(secrets_response) + end + + def list(organization_id) + command = create_command(list: SecretIdentifiersRequest.new(organization_id: organization_id)) + response = run_command(command) + + secrets_response = ResponseForSecretIdentifiersResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') && secrets_response['data'].key?('data') + return secrets_response['data']['data'] + end + + error_response(secrets_response) + end + + def update(id, key, note, organization_id, project_ids, value) + command = create_command( + update: SecretPutRequest.new( + id: id, key: key, note: note, organization_id: organization_id, project_ids: project_ids, value: value + ) + ) + response = run_command(command) + + secrets_response = ResponseForSecretResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') + return secrets_response['data'] + end + + error_response(secrets_response) + end + + def delete_secret(ids) + command = create_command(delete: SecretsDeleteRequest.new(ids: ids)) + response = run_command(command) + + secrets_response = ResponseForSecretsDeleteResponse.from_json!(response).to_dynamic + + if secrets_response.key?('success') && secrets_response['success'] == true && + secrets_response.key?('data') && secrets_response['data'].key?('data') + return secrets_response['data']['data'] + end + + error_response(secrets_response) + end + + private + + def error_response(response) + if response['errorMessage'] + raise BitwardenError, response['errorMessage'] if response.key?('errorMessage') + else + raise BitwardenError, 'Error while getting response' + end + end + + def create_command(commands) + SelectiveCommand.new(secrets: SelectiveSecretsCommand.new(commands)) + end + + def run_command(command) + response = @command_runner.run(command) + raise BitwardenError, 'Error getting response' if response.nil? + + response + end + end +end diff --git a/languages/ruby/bitwarden_sdk/lib/version.rb b/languages/ruby/bitwarden_sdk/lib/version.rb new file mode 100644 index 000000000..1fd8c02c1 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/lib/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module BitwardenSDK + VERSION = '0.0.0' +end diff --git a/languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs b/languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs new file mode 100644 index 000000000..3f6a73f6a --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs @@ -0,0 +1,13 @@ +require_relative '../lib/schemas' + +class BitwardenClient + @command_runner: CommandRunner + + attr_reader bitwarden: Module + attr_reader project_client: ProjectsClient + attr_reader secrets_client: SecretsClient + + def initialize: (BitwardenSettings) -> void + def access_token_login: (String) -> JSON + def free_mem: () -> nil +end diff --git a/languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs b/languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs new file mode 100644 index 000000000..154ee16e5 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs @@ -0,0 +1,8 @@ +require_relative '../lib/schemas' + +class BitwardenSettings + attr_accessor api_url: String + attr_accessor identity_url: String + + def initialize: (String, String) -> void +end diff --git a/languages/ruby/bitwarden_sdk/sig/command_runner.rbs b/languages/ruby/bitwarden_sdk/sig/command_runner.rbs new file mode 100644 index 000000000..7a7a17dd9 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/command_runner.rbs @@ -0,0 +1,4 @@ +class CommandRunner + @bitwarden_sdk: Module + def run: -> String +end diff --git a/languages/ruby/bitwarden_sdk/sig/projects_client.rbs b/languages/ruby/bitwarden_sdk/sig/projects_client.rbs new file mode 100644 index 000000000..00c9e578d --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/projects_client.rbs @@ -0,0 +1,17 @@ +require_once '../lib/extended_schemas/schemas.rbs' +require_once '../schemas.rbs' + +class ProjectsClient + @command_runner: CommandRunner + def initialize: (command_runner: CommandRunner) -> void + def create_project: (project_name: String, organization_id: String) -> ProjectsResponse + def get: (project_id: String) -> ProjectsResponse + def list_projects: (organization_id: String) -> Array(DatumElement) + def update_project: (id: String, project_put_request_name: String, organization_id: String) -> ProjectsResponse + def delete_projects: (ids: Array[String]) -> Array(ProjectDeleteResponse) + + private + + def create_command: (SelectiveProjectsCommand) -> SelectiveCommand + def parse_response: (ResponseForProjectResponse) -> ResponseForProjectResponse +end diff --git a/languages/ruby/bitwarden_sdk/sig/sdk.rbs b/languages/ruby/bitwarden_sdk/sig/sdk.rbs new file mode 100644 index 000000000..260fa1420 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/sdk.rbs @@ -0,0 +1,3 @@ +module BitwardenSDK + VERSION: String +end diff --git a/languages/ruby/bitwarden_sdk/sig/secrets_client.rbs b/languages/ruby/bitwarden_sdk/sig/secrets_client.rbs new file mode 100644 index 000000000..ccebcecd8 --- /dev/null +++ b/languages/ruby/bitwarden_sdk/sig/secrets_client.rbs @@ -0,0 +1,18 @@ +require_once '../lib/extended_schemas/schemas.rbs' +require_once '../schemas.rbs' + +class SecretsClient + # @command_runner: CommandRunner + def initialize: (command_runner: CommandRunner) -> void + def get: (id: String) -> SecretResponse + def get_by_ids: (ids: Array[String]) -> Array(SecretIdentifierResponse) + def create: (key: String, note: String, organization_id: String, project_ids: Array[String], value: String) -> SecretResponse + def list: (organization_id: String) -> Array(SecretIdentifierResponse) + def update: (id: String, key: String, note: String, organization_id: String, project_ids: Array[String], value: String) -> SecretResponse + def delete_secret: (ids: Array[String]) -> Array(SecretDeleteResponse) + + private + + def create_command: (SelectiveSecretsCommand) -> SelectiveCommand + def parse_response: (SelectiveSecretCommand) -> ResponseForSecretResponse +end diff --git a/languages/ruby/examples/example.rb b/languages/ruby/examples/example.rb new file mode 100644 index 000000000..c0deeb437 --- /dev/null +++ b/languages/ruby/examples/example.rb @@ -0,0 +1,67 @@ +# NOTE - for example purpose only - import gem instead +require 'bitwarden-sdk' + +token = '' +organization_id = '' + +bitwarden_settings = BitwardenSDK::BitwardenSettings.new( + 'https://api.bitwarden.com', + 'https://identity.bitwarden.com/connect/token' +) + +bw_client = BitwardenSDK::BitwardenClient.new(bitwarden_settings) +response = bw_client.access_token_login(token) +puts response + +# CREATE project +project_name = 'Test project 1' +response = bw_client.project_client.create_project(project_name, organization_id) +puts response +project_id = response['id'] + +# GET project +response = bw_client.project_client.get(project_id) +puts response + +# LIST projects +response = bw_client.project_client.list_projects(organization_id) +puts response + +# UPDATE projects +name = 'Updated test project 1' +response = bw_client.project_client.update_project(project_id, name, organization_id) +puts response + +# CREATE secret +key = 'AWS-SES' +note = 'Private account' +value = '8t27.dfj;' +response = bw_client.secrets_client.create(key, note, organization_id, [project_id], value) +puts response +secret_id = response['id'] + +# GET secret +response = bw_client.secrets_client.get(secret_id) +puts response + +# GET secret by ids +response = bw_client.secrets_client.get_by_ids([secret_id]) +puts response + +# LIST secrets +response = bw_client.secrets_client.list(organization_id) +puts response + +# UPDATE secret +note = 'updated password' +value = '7I.ert10AjK' +response = bw_client.secrets_client.update(secret_id, key, note,organization_id, [project_id], value) +puts response + +# DELETE secret +response = bw_client.secrets_client.delete_secret([secret_id]) +puts response + +# DELETE project +response = bw_client.project_client.delete_projects([project_id]) +puts response diff --git a/sig/bitwarden_sdk/bitwarden_client.rbs b/sig/bitwarden_sdk/bitwarden_client.rbs new file mode 100644 index 000000000..1ff97eb92 --- /dev/null +++ b/sig/bitwarden_sdk/bitwarden_client.rbs @@ -0,0 +1,5 @@ +module BitwardenSDK + class BitwardenClient + attr_reader project_client: ProjectsClient + end +end diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 2958efc18..9e25bedc5 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -58,6 +58,16 @@ async function main() { writeToFile("./languages/python/BitwardenClient/schemas.py", python.lines); + const ruby = await quicktype({ + inputData, + lang: "ruby", + rendererOptions: { + "ruby-version": "3.0", + }, + }); + + writeToFile("./languages/ruby/bitwarden_sdk/lib/schemas.rb", ruby.lines); + const csharp = await quicktype({ inputData, lang: "csharp", From e219efa40d9f9d04a8f69e55dd6409b6ff43f069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Trifunovi=C4=87?= <84377717+milost77@users.noreply.github.com> Date: Fri, 1 Dec 2023 13:35:44 +0100 Subject: [PATCH 078/378] PHP SDK implementation (#316) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change Implemented PHP library that wraps native C library and exposed its commands through BitwardenClient class. ``` - [ ] Bug fix - [ x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective To provide PHP interface for bitwarden c library files by which you can use PHP code to work with Bitwarden API. It implements CRUD requests for projects and secrets. ## Code changes TODO: Updating package repository - will hosted on Packagist. --------- Co-authored-by: Daniel García --- .github/workflows/publish-php.yml | 75 ++++++ languages/php/.gitignore | 2 + languages/php/README.md | 100 +++++++ languages/php/composer.json | 22 ++ languages/php/composer.lock | 247 ++++++++++++++++++ languages/php/example.php | 43 +++ languages/php/src/BitwardenClient.php | 64 +++++ languages/php/src/BitwardenLib.php | 79 ++++++ languages/php/src/BitwardenSettings.php | 26 ++ languages/php/src/CommandRunner.php | 37 +++ languages/php/src/ProjectsClient.php | 81 ++++++ languages/php/src/SecretsClient.php | 98 +++++++ .../src/schemas/AccessTokenLoginRequest.php | 39 +++ .../src/schemas/BitwardenClassStructure.php | 11 + .../schemas/BitwardenClassStructureTrait.php | 189 ++++++++++++++ languages/php/src/schemas/ClientSettings.php | 133 ++++++++++ languages/php/src/schemas/Command.php | 44 ++++ .../php/src/schemas/ProjectCreateRequest.php | 43 +++ .../php/src/schemas/ProjectGetRequest.php | 37 +++ .../php/src/schemas/ProjectPutRequest.php | 50 ++++ languages/php/src/schemas/ProjectsCommand.php | 55 ++++ .../php/src/schemas/ProjectsDeleteRequest.php | 39 +++ .../php/src/schemas/ProjectsListRequest.php | 38 +++ .../php/src/schemas/SecretCreateRequest.php | 58 ++++ .../php/src/schemas/SecretGetRequest.php | 38 +++ .../src/schemas/SecretIdentifiersRequest.php | 38 +++ .../php/src/schemas/SecretPutRequest.php | 64 +++++ .../src/schemas/SecretVerificationRequest.php | 35 +++ languages/php/src/schemas/SecretsCommand.php | 56 ++++ .../php/src/schemas/SecretsDeleteRequest.php | 39 +++ .../php/src/schemas/SecretsGetRequest.php | 39 +++ 31 files changed, 1919 insertions(+) create mode 100644 .github/workflows/publish-php.yml create mode 100644 languages/php/.gitignore create mode 100644 languages/php/README.md create mode 100644 languages/php/composer.json create mode 100644 languages/php/composer.lock create mode 100644 languages/php/example.php create mode 100644 languages/php/src/BitwardenClient.php create mode 100644 languages/php/src/BitwardenLib.php create mode 100644 languages/php/src/BitwardenSettings.php create mode 100644 languages/php/src/CommandRunner.php create mode 100644 languages/php/src/ProjectsClient.php create mode 100644 languages/php/src/SecretsClient.php create mode 100644 languages/php/src/schemas/AccessTokenLoginRequest.php create mode 100644 languages/php/src/schemas/BitwardenClassStructure.php create mode 100644 languages/php/src/schemas/BitwardenClassStructureTrait.php create mode 100644 languages/php/src/schemas/ClientSettings.php create mode 100644 languages/php/src/schemas/Command.php create mode 100644 languages/php/src/schemas/ProjectCreateRequest.php create mode 100644 languages/php/src/schemas/ProjectGetRequest.php create mode 100644 languages/php/src/schemas/ProjectPutRequest.php create mode 100644 languages/php/src/schemas/ProjectsCommand.php create mode 100644 languages/php/src/schemas/ProjectsDeleteRequest.php create mode 100644 languages/php/src/schemas/ProjectsListRequest.php create mode 100644 languages/php/src/schemas/SecretCreateRequest.php create mode 100644 languages/php/src/schemas/SecretGetRequest.php create mode 100644 languages/php/src/schemas/SecretIdentifiersRequest.php create mode 100644 languages/php/src/schemas/SecretPutRequest.php create mode 100644 languages/php/src/schemas/SecretVerificationRequest.php create mode 100644 languages/php/src/schemas/SecretsCommand.php create mode 100644 languages/php/src/schemas/SecretsDeleteRequest.php create mode 100644 languages/php/src/schemas/SecretsGetRequest.php diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml new file mode 100644 index 000000000..b443f2057 --- /dev/null +++ b/.github/workflows/publish-php.yml @@ -0,0 +1,75 @@ +name: Publish PHP SDK + +on: + pull_request: + branches: + - master + +jobs: + build_rust: + uses: ./.github/workflows/build-rust-cross-platform.yml + + setup_php: + name: Setup PHP + runs-on: ubuntu-22.04 + needs: + - build_rust + + steps: + - name: Checkout Repository + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + + - name: Setup PHP with PECL extension + uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # 2.26.0 + with: + php-version: "8.0" + tools: composer + extensions: ext-ffi + + - name: Composer check + run: | + composer install + composer validate + working-directory: languages/php/ + + - name: Download x86_64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-apple-darwin + path: temp/macos-x64 + + - name: Download aarch64-apple-darwin files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-aarch64-apple-darwin + path: temp/macos-arm64 + + - name: Download x86_64-unknown-linux-gnu files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-unknown-linux-gnu + path: temp/ubuntu-x64 + + - name: Download x86_64-pc-windows-msvc files + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: libbitwarden_c_files-x86_64-pc-windows-msvc + path: temp/windows-x64 + + - name: Copy lib files + run: | + mkdir -p languages/php/src/lib/macos-arm64 + mkdir -p languages/php/src/lib/ubuntu-x64 + mkdir -p languages/php/src/lib/macos-x64 + mkdir -p languages/php/src/lib/windows-x64 + + platforms=("macos-arm64" "ubuntu-x64" "macos-x64" "windows-x64") + files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") + + for ((i=0; i<${#platforms[@]}; i++)); do + cp "temp/${platforms[$i]}/${files[$i]}" "languages/php/src/lib/${platforms[$i]}/${files[$i]}" + done + + - name: Publish version + run: curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username=malirobot&apiToken=${{secrets.PACKAGIST_KEY}}' -d'{"repository":{"url":"https://packagist.org/packages/bitwarden/sdk"}}' + working-directory: languages/php/ diff --git a/languages/php/.gitignore b/languages/php/.gitignore new file mode 100644 index 000000000..b2a69e9a0 --- /dev/null +++ b/languages/php/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +vendor diff --git a/languages/php/README.md b/languages/php/README.md new file mode 100644 index 000000000..9e4a9385d --- /dev/null +++ b/languages/php/README.md @@ -0,0 +1,100 @@ +# Bitwarden Secrets Manager SDK wrapper for PHP + +PHP bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. +Supported are CRUD operations on project and secret entities. + +## Installation + +Requirements: +- PHP >= 8.0 +- Composer +- Bitwarden C libraries which you can generate using BitwardenSDK and following instructions in its readme (requires Rust). https://github.com/bitwarden/sdk +If you are not using the standalone version of this library, file will be placed in `target/debug` folder if you are using from BitwardenSDK repository. +- Access token for the Bitwarden account + + +## Usage + +To interact with the client first you need to obtain the access token from Bitwarden. +You can then initialize BitwardenSettings passing $api_url and $identity_url if needed. These parameteres are +optional and if they are not defined, BitwardenSettings instance will try to get these values from ENV, and +if they are not defined there as well, it will use defaults: `https://api.bitwarden.com` as api_url and +`https://identity.bitwarden.com` as identity_url. You can also pass device type as argument but that is entirely +optional. + +Passing BitwardenSettings instance to BitwardenClient will initialize it. Before using the client you must +be authorized by calling the access_token_login method passing your Bitwarden access token to it. + + +```php +$access_token = ''; +$api_url = ""; +$identity_url = ""; +$bitwarden_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); + +$bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); +$bitwarden_client->access_token_login($access_token); +``` + +After successful authorization you can interact with client to manage your projects and secrets. +```php +$organization_id = ""; + +$bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($bitwarden_settings); +$res = $bitwarden_client->access_token_login($access_token); + +// create project +$name = "PHP project" +$res = $bitwarden_client->projects->create($name, $organization_id); +$project_id = $res->id; + +// get project +$res = $bitwarden_client->projects->get($project_id); + +// list projects +$res = $bitwarden_client->projects->list($organization_id); + +// update project +$name = "Updated PHP project" +$res = $bitwarden_client->projects->put($project_id, $name, $organization_id); + +// get secret +$res = $bitwarden_client->secrets->get($secret_id); + +// list secrets +$res = $bitwarden_client->secrets->list($organization_id); + +// delete project +$res = $bitwarden_client->projects->delete([$project_id]); + +``` + +Similarly, you interact with secrets: +```php +$organization_id = ""; + +// create secret +$key = "AWS secret key"; +$note = "Private account"; +$secret = "76asaj,Is_)" +$res = $bitwarden_client->secrets->create($key, $note, $organization_id, [$project_id], $secret); +$secret_id = $res->id; + +// get secret +$res = $bitwarden_sdk->secrets->get($secret_id); + +// list secrets +$res = $bitwarden_client->secrets->list($organization_id); + +// update secret +$note = "Updated account"; +$key = "AWS private updated" +$secret = "7uYTE,:Aer" +$res = $bitwarden_client->secrets->update($secret_id, $key, $note, $organization_id, [$project_id], $secret); + +// delete secret +$res = $bitwarden_sdk->secrets->delete([$secret_id]); +``` + + +[Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ diff --git a/languages/php/composer.json b/languages/php/composer.json new file mode 100644 index 000000000..18b333eac --- /dev/null +++ b/languages/php/composer.json @@ -0,0 +1,22 @@ +{ + "name": "bitwarden/sdk", + "description": "PHP bindings for interacting with the Bitwarden Secrets Manager. This is a beta release and might be missing some functionality.", + "type": "library", + "keywords": ["bitwarden","sdk","password-manager"], + "homepage": "https://github.com/bitwarden/sdk", + "require": { + "php": "^8.0", + "swaggest/json-schema": "^0.12.42", + "ext-ffi": "*" + }, + "autoload": { + "psr-4": { + "Bitwarden\\Sdk\\": "src/" + } + }, + "authors": [ + { + "name": "Bitwarden Inc." + } + ] +} diff --git a/languages/php/composer.lock b/languages/php/composer.lock new file mode 100644 index 000000000..fc6b42c4f --- /dev/null +++ b/languages/php/composer.lock @@ -0,0 +1,247 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "7081b1bfe099982a63ad06d5ab9fa66d", + "packages": [ + { + "name": "phplang/scope-exit", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/phplang/scope-exit.git", + "reference": "239b73abe89f9414aa85a7ca075ec9445629192b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phplang/scope-exit/zipball/239b73abe89f9414aa85a7ca075ec9445629192b", + "reference": "239b73abe89f9414aa85a7ca075ec9445629192b", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpLang\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD" + ], + "authors": [ + { + "name": "Sara Golemon", + "email": "pollita@php.net", + "homepage": "https://twitter.com/SaraMG", + "role": "Developer" + } + ], + "description": "Emulation of SCOPE_EXIT construct from C++", + "homepage": "https://github.com/phplang/scope-exit", + "keywords": [ + "cleanup", + "exit", + "scope" + ], + "support": { + "issues": "https://github.com/phplang/scope-exit/issues", + "source": "https://github.com/phplang/scope-exit/tree/master" + }, + "time": "2016-09-17T00:15:18+00:00" + }, + { + "name": "swaggest/json-diff", + "version": "v3.10.4", + "source": { + "type": "git", + "url": "https://github.com/swaggest/json-diff.git", + "reference": "f4e511708060ff7511a3743fab4aa484a062bcfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swaggest/json-diff/zipball/f4e511708060ff7511a3743fab4aa484a062bcfb", + "reference": "f4e511708060ff7511a3743fab4aa484a062bcfb", + "shasum": "" + }, + "require": { + "ext-json": "*" + }, + "require-dev": { + "phperf/phpunit": "4.8.37" + }, + "type": "library", + "autoload": { + "psr-4": { + "Swaggest\\JsonDiff\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Viacheslav Poturaev", + "email": "vearutop@gmail.com" + } + ], + "description": "JSON diff/rearrange/patch/pointer library for PHP", + "support": { + "issues": "https://github.com/swaggest/json-diff/issues", + "source": "https://github.com/swaggest/json-diff/tree/v3.10.4" + }, + "time": "2022-11-09T13:21:05+00:00" + }, + { + "name": "swaggest/json-schema", + "version": "v0.12.42", + "source": { + "type": "git", + "url": "https://github.com/swaggest/php-json-schema.git", + "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/swaggest/php-json-schema/zipball/d23adb53808b8e2da36f75bc0188546e4cbe3b45", + "reference": "d23adb53808b8e2da36f75bc0188546e4cbe3b45", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.4", + "phplang/scope-exit": "^1.0", + "swaggest/json-diff": "^3.8.2", + "symfony/polyfill-mbstring": "^1.19" + }, + "require-dev": { + "phperf/phpunit": "4.8.37" + }, + "suggest": { + "ext-mbstring": "For better performance" + }, + "type": "library", + "autoload": { + "psr-4": { + "Swaggest\\JsonSchema\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Viacheslav Poturaev", + "email": "vearutop@gmail.com" + } + ], + "description": "High definition PHP structures with JSON-schema based validation", + "support": { + "email": "vearutop@gmail.com", + "issues": "https://github.com/swaggest/php-json-schema/issues", + "source": "https://github.com/swaggest/php-json-schema/tree/v0.12.42" + }, + "time": "2023-09-12T14:43:42+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "42292d99c55abe617799667f454222c54c60e229" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-28T09:04:16+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^8.0", + "ext-ffi": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/languages/php/example.php b/languages/php/example.php new file mode 100644 index 000000000..0fdb6930a --- /dev/null +++ b/languages/php/example.php @@ -0,0 +1,43 @@ +'; +$organization_id = ""; + +$client_settings = new \Bitwarden\Sdk\BitwardenSettings(); + +$bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); +$bitwarden_client->access_token_login($access_token); + +// create project +$res = $bitwarden_client->projects->create('php project', $organization_id); +$project_id = $res->id; + +// get project +$res = $bitwarden_client->projects->get($project_id); + +// list projects +$res = $bitwarden_client->projects->list($organization_id); + +// update project +$res = $bitwarden_client->projects->put($project_id, 'php test awesome', $organization_id); + +// create secret +$res = $bitwarden_client->secrets->create("New Key", "hello world", $organization_id, [$project_id], "123"); +$secret_id = $res->id; + +// get secret +$res = $bitwarden_client->secrets->get($secret_id); + +// list secrets +$res = $bitwarden_client->secrets->list($organization_id); + +// update secret +$res = $bitwarden_client->secrets->update($secret_id, "hello world 2", "hello", $organization_id, [$project_id], "123"); + +// delete secret +$res = $bitwarden_client->secrets->delete([$secret_id]); + +// delete project +$res = $bitwarden_client->projects->delete([$project_id]); diff --git a/languages/php/src/BitwardenClient.php b/languages/php/src/BitwardenClient.php new file mode 100644 index 000000000..79fccdf9c --- /dev/null +++ b/languages/php/src/BitwardenClient.php @@ -0,0 +1,64 @@ +clientSettings = new ClientSettings(); + $this->clientSettings->apiUrl = $bitwardenSettings->get_api_url(); + $this->clientSettings->identityUrl = $bitwardenSettings->get_identity_url(); + $this->clientSettings->userAgent = "Bitwarden PHP-SDK"; + + $this->bitwarden_lib = new BitwardenLib(); + $this->handle = $this->bitwarden_lib->init($this->clientSettings); + + $this->commandRunner = new CommandRunner($this->bitwarden_lib, $this->handle); + $this->projects = new ProjectsClient($this->commandRunner); + $this->secrets = new SecretsClient($this->commandRunner); + } + + /** + * @throws \Exception + */ + public function access_token_login(string $access_token) + { + $access_token_request = new AccessTokenLoginRequest(); + $access_token_request->accessToken = $access_token; + $command = new Command(); + $command->accessTokenLogin = $access_token_request->jsonSerialize(); + $result = $this->commandRunner->run($command); + if (!isset($result->authenticated)) { + throw new \Exception("Authorization error"); + } + + if ($result->authenticated == False) { + throw new \Exception("Unauthorized"); + } + } + + public function __destruct() + { + $this->bitwarden_lib->free_mem(); + } +} diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php new file mode 100644 index 000000000..3eb3ed5f4 --- /dev/null +++ b/languages/php/src/BitwardenLib.php @@ -0,0 +1,79 @@ +ffi = FFI::cdef(' + void* init(const char* param); + char* run_command(void* c_str_ptr, void* client_ptr); + void free_mem(void* client_ptr);', + $lib_file + ); + } + + public function init(ClientSettings $client_settings): FFI\CData + { + $this->handle = $this->ffi->init(json_encode($client_settings->jsonSerialize())); + return $this->handle; + } + + public function run_command(Command $command): \stdClass + { + $encoded_json = json_encode($command->jsonSerialize()); + try { + $result = $this->ffi->run_command($encoded_json, $this->handle); + return json_decode(FFI::string($result)); + } catch (\FFI\Exception $e) { + throw new \RuntimeException('Error occurred during FFI operation: ' . $e->getMessage()); + } + } + + public function free_mem(): void + { + $this->ffi->free_mem($this->handle); + } +} diff --git a/languages/php/src/BitwardenSettings.php b/languages/php/src/BitwardenSettings.php new file mode 100644 index 000000000..b3d62bc2e --- /dev/null +++ b/languages/php/src/BitwardenSettings.php @@ -0,0 +1,26 @@ +api_url = $api_url; + $this->identity_url = $identity_url; + } + + public function get_api_url(): ?string + { + return $this->api_url; + } + + public function get_identity_url(): ?string + { + return $this->identity_url; + } +} diff --git a/languages/php/src/CommandRunner.php b/languages/php/src/CommandRunner.php new file mode 100644 index 000000000..9eec68b2d --- /dev/null +++ b/languages/php/src/CommandRunner.php @@ -0,0 +1,37 @@ +bitwardenLib = $bitwardenLib; + $this->handle = $handle; + } + + /** + * @throws \Exception + */ + public function run(Command $command): \stdClass + { + $result = $this->bitwardenLib->run_command($command); + if ($result->success == true) { + return $result->data; + } + + if (isset($result->errorMessage)) + { + throw new \Exception($result->errorMessage); + } + throw new \Exception("Unknown error occurred"); + } +} diff --git a/languages/php/src/ProjectsClient.php b/languages/php/src/ProjectsClient.php new file mode 100644 index 000000000..6b6f9fb6a --- /dev/null +++ b/languages/php/src/ProjectsClient.php @@ -0,0 +1,81 @@ +commandRunner = $commandRunner; + } + + public function get(string $project_id): \stdClass + { + $project_get_request = new ProjectGetRequest(); + $project_get_request->id = $project_id; + $project_get_request->validate(); + $project_command = new ProjectsCommand(); + $project_command->get = $project_get_request->jsonSerialize(); + return $this->run_project_command($project_command); + } + + public function list(string $organization_id): \stdClass + { + $project_list_request = new ProjectsListRequest(); + $project_list_request->organizationId = $organization_id; + $project_list_request->validate(); + $project_command = new ProjectsCommand(); + $project_command->list = $project_list_request->jsonSerialize(); + return $this->run_project_command($project_command); + } + + public function create(string $project_name, string $organization_id): \stdClass + { + $project_create_request = new ProjectCreateRequest(); + $project_create_request->name = $project_name; + $project_create_request->organizationId = $organization_id; + $project_create_request->validate(); + $project_command = new ProjectsCommand(); + $project_command->create = $project_create_request->jsonSerialize(); + return $this->run_project_command($project_command); + } + + public function put(string $project_id, string $project_name, string $organization_id): \stdClass + { + $project_put_request = new ProjectPutRequest(); + $project_put_request->organizationId = $organization_id; + $project_put_request->name = $project_name; + $project_put_request->id = $project_id; + $project_put_request->validate(); + $project_command = new ProjectsCommand(); + $project_command->update = $project_put_request->jsonSerialize(); + return $this->run_project_command($project_command); + } + + public function delete(array $ids): \stdClass + { + $projects_delete_request = new ProjectsDeleteRequest(); + $projects_delete_request->ids = $ids; + $projects_delete_request->validate(); + $project_command = new ProjectsCommand(); + $project_command->delete = $projects_delete_request->jsonSerialize(); + return $this->run_project_command($project_command); + } + + public function run_project_command($projectCommand): \stdClass + { + $command = new Command(); + $command->projects = $projectCommand; + return $this->commandRunner->run($command); + } +} diff --git a/languages/php/src/SecretsClient.php b/languages/php/src/SecretsClient.php new file mode 100644 index 000000000..d5c0b0cef --- /dev/null +++ b/languages/php/src/SecretsClient.php @@ -0,0 +1,98 @@ +commandRunner = $commandRunner; + } + + public function get(string $secret_id): \stdClass + { + $secret_get_request = new SecretGetRequest(); + $secret_get_request->id = $secret_id; + $secret_get_request->validate(); + $secret_command = new SecretsCommand(); + $secret_command->get = $secret_get_request->jsonSerialize(); + return $this->run_secret_command($secret_command); + } + + public function get_by_ids(array $secret_ids): \stdClass + { + $project_get_by_ids_request = new SecretsGetRequest(); + $project_get_by_ids_request->ids = $secret_ids; + $project_get_by_ids_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->get_by_ids = $project_get_by_ids_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + + public function list(string $organization_id): \stdClass + { + $secrets_list_request = new SecretIdentifiersRequest(); + $secrets_list_request->organizationId = $organization_id; + $secrets_list_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->list = $secrets_list_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + + public function create(string $key, string $note, string $organization_id, array $project_ids, string $value): \stdClass + { + $secrets_create_request = new SecretCreateRequest(); + $secrets_create_request->organizationId = $organization_id; + $secrets_create_request->projectIds = $project_ids; + $secrets_create_request->key = $key; + $secrets_create_request->note = $note; + $secrets_create_request->value = $value; + $secrets_create_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->create = $secrets_create_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + + public function update(string $id, string $key, string $note, string $organization_id, array $project_ids, string $value): \stdClass + { + $secrets_put_request = new SecretPutRequest(); + $secrets_put_request->id = $id; + $secrets_put_request->organizationId = $organization_id; + $secrets_put_request->projectIds = $project_ids; + $secrets_put_request->key = $key; + $secrets_put_request->note = $note; + $secrets_put_request->value = $value; + $secrets_put_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->update = $secrets_put_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + + public function delete(array $secrets_ids): \stdClass + { + $secrets_delete_request = new SecretsDeleteRequest(); + $secrets_delete_request->ids = $secrets_ids; + $secrets_delete_request->validate(); + $secrets_command = new SecretsCommand(); + $secrets_command->delete = $secrets_delete_request->jsonSerialize(); + return $this->run_secret_command($secrets_command); + } + + public function run_secret_command($secretsCommand): \stdClass + { + $command = new Command(); + $command->secrets = $secretsCommand; + return $this->commandRunner->run($command); + } +} diff --git a/languages/php/src/schemas/AccessTokenLoginRequest.php b/languages/php/src/schemas/AccessTokenLoginRequest.php new file mode 100644 index 000000000..a08805f92 --- /dev/null +++ b/languages/php/src/schemas/AccessTokenLoginRequest.php @@ -0,0 +1,39 @@ +accessToken = Schema::string(); + $properties->accessToken->description = "Bitwarden service API access token"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->description = "Login to Bitwarden with access token"; + $ownerSchema->required = array( + self::names()->accessToken, + ); + $ownerSchema->setFromRef('#/definitions/AccessTokenLoginRequest'); + } +} diff --git a/languages/php/src/schemas/BitwardenClassStructure.php b/languages/php/src/schemas/BitwardenClassStructure.php new file mode 100644 index 000000000..fd50354d4 --- /dev/null +++ b/languages/php/src/schemas/BitwardenClassStructure.php @@ -0,0 +1,11 @@ +properties = $properties; + $schema->objectItemClass = $className; + $schemaWrapper = new Wrapper($schema); + static::setUpProperties($properties, $schema); + if (null === $schema->getFromRefs()) { + $schema->setFromRef('#/definitions/' . $className); + } + if ($properties->isEmpty()) { + $schema->properties = null; + } + $properties->lock(); + } + + return $schemaWrapper; + } + + /** + * @return Properties|static|null + */ + public static function properties() + { + return static::schema()->getProperties(); + } + + /** + * @param mixed $data + * @param Context $options + * @return static|mixed + * @throws \Swaggest\JsonSchema\Exception + * @throws \Swaggest\JsonSchema\InvalidValue + */ + public static function import($data, Context $options = null) + { + return static::schema()->in($data, $options); + } + + /** + * @param mixed $data + * @param Context $options + * @return mixed + * @throws \Swaggest\JsonSchema\InvalidValue + * @throws \Exception + */ + public static function export($data, Context $options = null) + { + return static::schema()->out($data, $options); + } + + /** + * @param ObjectItemContract $objectItem + * @return static + */ + public static function pick(ObjectItemContract $objectItem) + { + $className = get_called_class(); + return $objectItem->getNestedObject($className); + } + + /** + * @return static + */ + public static function create() + { + return new static; + } + + protected $__validateOnSet = true; // todo skip validation during import + + /** + * @return \stdClass + */ + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + $result = new \stdClass(); + $schema = static::schema(); + $properties = $schema->getProperties(); + $processed = array(); + if (null !== $properties) { + foreach ($properties->getDataKeyMap() as $propertyName => $dataName) { + $value = $this->$propertyName ?? null; + + // Value is exported if exists. + if (null !== $value || array_key_exists($propertyName, $this->__arrayOfData)) { + $result->$dataName = $value; + $processed[$propertyName] = true; + continue; + } + + // Non-existent value is only exported if belongs to nullable property (having 'null' in type array). + $property = $schema->getProperty($propertyName); + if ($property instanceof Schema) { + $types = $property->type; + if ($types === Schema::NULL || (is_array($types) && in_array(Schema::NULL, $types))) { + $result->$dataName = $value; + } + } + } + } + foreach ($schema->getNestedPropertyNames() as $name) { + /** @var ObjectItem $nested */ + $nested = $this->$name; + if (null !== $nested) { + foreach ((array)$nested->jsonSerialize() as $key => $value) { + $result->$key = $value; + } + } + } + + if (!empty($this->__arrayOfData)) { + foreach ($this->__arrayOfData as $name => $value) { + if (!isset($processed[$name])) { + $result->$name = $this->{$name}; + } + } + } + + return $result; + } + + /** + * @return static|NameMirror + */ + public static function names(Properties $properties = null, $mapping = Schema::DEFAULT_MAPPING) + { + if ($properties !== null) { + return new NameMirror($properties->getDataKeyMap($mapping)); + } + + static $nameflector = null; + if (null === $nameflector) { + $nameflector = new NameMirror(); + } + return $nameflector; + } + + public function __set($name, $column) // todo nested schemas + { + if ($this->__validateOnSet) { + if ($property = static::schema()->getProperty($name)) { + $property->out($column); + } + } + $this->__arrayOfData[$name] = $column; + return $this; + } + + public static function className() + { + return get_called_class(); + } + + /** + * @throws \Exception + * @throws \Swaggest\JsonSchema\InvalidValue + */ + public function validate() + { + static::schema()->out($this); + } +} + diff --git a/languages/php/src/schemas/ClientSettings.php b/languages/php/src/schemas/ClientSettings.php new file mode 100644 index 000000000..c27cc3322 --- /dev/null +++ b/languages/php/src/schemas/ClientSettings.php @@ -0,0 +1,133 @@ +identityUrl = Schema::string(); + $properties->identityUrl->description = "The identity url of the targeted Bitwarden instance. Defaults to `https://identity.bitwarden.com`"; + $properties->identityUrl->default = "https://identity.bitwarden.com"; + $properties->apiUrl = Schema::string(); + $properties->apiUrl->description = "The api url of the targeted Bitwarden instance. Defaults to `https://api.bitwarden.com`"; + $properties->apiUrl->default = "https://api.bitwarden.com"; + $properties->userAgent = Schema::string(); + $properties->userAgent->description = "The user_agent to sent to Bitwarden. Defaults to `Bitwarden Rust-SDK`"; + $properties->userAgent->default = "Bitwarden Rust-SDK"; + $properties->deviceType = new Schema(); + $propertiesDeviceTypeAllOf0 = Schema::string(); + $propertiesDeviceTypeAllOf0->enum = array( + self::ANDROID, + self::I_OS, + self::CHROME_EXTENSION, + self::FIREFOX_EXTENSION, + self::OPERA_EXTENSION, + self::EDGE_EXTENSION, + self::WINDOWS_DESKTOP, + self::MAC_OS_DESKTOP, + self::LINUX_DESKTOP, + self::CHROME_BROWSER, + self::FIREFOX_BROWSER, + self::OPERA_BROWSER, + self::EDGE_BROWSER, + self::IE_BROWSER, + self::UNKNOWN_BROWSER, + self::ANDROID_AMAZON, + self::UWP, + self::SAFARI_BROWSER, + self::VIVALDI_BROWSER, + self::VIVALDI_EXTENSION, + self::SAFARI_EXTENSION, + self::SDK, + ); + $propertiesDeviceTypeAllOf0->setFromRef('#/definitions/DeviceType'); + $properties->deviceType->allOf[0] = $propertiesDeviceTypeAllOf0; + $properties->deviceType->description = "Device type to send to Bitwarden. Defaults to SDK"; + $properties->deviceType->default = "SDK"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->schema = "http://json-schema.org/draft-07/schema#"; + $ownerSchema->title = "ClientSettings"; + $ownerSchema->description = "Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. They are optional and uneditable once the client is initialized.\n\nDefaults to\n\n``` # use bitwarden::client::client_settings::{ClientSettings, DeviceType}; # use assert_matches::assert_matches; let settings = ClientSettings { identity_url: \"https://identity.bitwarden.com\".to_string(), api_url: \"https://api.bitwarden.com\".to_string(), user_agent: \"Bitwarden Rust-SDK\".to_string(), device_type: DeviceType::SDK, }; let default = ClientSettings::default(); assert_matches!(settings, default); ```\n\nTargets `localhost:8080` for debug builds."; + } +} diff --git a/languages/php/src/schemas/Command.php b/languages/php/src/schemas/Command.php new file mode 100644 index 000000000..cbd649c2f --- /dev/null +++ b/languages/php/src/schemas/Command.php @@ -0,0 +1,44 @@ +projects = ProjectsCommand::schema(); + $properties->secrets = SecretsCommand::schema(); + $properties->accessTokenLogin = AccessTokenLoginRequest::schema(); + + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + + $ownerSchema->oneOf = array( + self::names()->projects, + self::names()->secrets, + self::names()->accessTokenLogin, + ); + } +} diff --git a/languages/php/src/schemas/ProjectCreateRequest.php b/languages/php/src/schemas/ProjectCreateRequest.php new file mode 100644 index 000000000..6a4e0f082 --- /dev/null +++ b/languages/php/src/schemas/ProjectCreateRequest.php @@ -0,0 +1,43 @@ +organizationId = Schema::string(); + $properties->organizationId->description = "Organization where the project will be created"; + $properties->organizationId->format = "uuid"; + $properties->name = Schema::string(); + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->name, + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/ProjectCreateRequest'); + } +} diff --git a/languages/php/src/schemas/ProjectGetRequest.php b/languages/php/src/schemas/ProjectGetRequest.php new file mode 100644 index 000000000..972bf18ec --- /dev/null +++ b/languages/php/src/schemas/ProjectGetRequest.php @@ -0,0 +1,37 @@ +id = Schema::string(); + $properties->id->description = "ID of the project to retrieve"; + $properties->id->format = "uuid"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->id, + ); + $ownerSchema->setFromRef('#/definitions/ProjectGetRequest'); + } +} diff --git a/languages/php/src/schemas/ProjectPutRequest.php b/languages/php/src/schemas/ProjectPutRequest.php new file mode 100644 index 000000000..96b9705e7 --- /dev/null +++ b/languages/php/src/schemas/ProjectPutRequest.php @@ -0,0 +1,50 @@ +id = Schema::string(); + $properties->id->description = "ID of the project to modify"; + $properties->id->format = "uuid"; + $properties->organizationId = Schema::string(); + $properties->organizationId->description = "Organization ID of the project to modify"; + $properties->organizationId->format = "uuid"; + $properties->name = Schema::string(); + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->id, + self::names()->name, + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/ProjectPutRequest'); + } +} diff --git a/languages/php/src/schemas/ProjectsCommand.php b/languages/php/src/schemas/ProjectsCommand.php new file mode 100644 index 000000000..22645db3c --- /dev/null +++ b/languages/php/src/schemas/ProjectsCommand.php @@ -0,0 +1,55 @@ + Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the projects whose IDs match the provided ones + * + * Returns: [ProjectsDeleteResponse](bitwarden::secrets_manager::projects::ProjectsDeleteResponse) + */ +class ProjectsCommand extends BitwardenClassStructure +{ + public ?\stdClass $delete; + + public ?\stdClass $get; + + public ?\stdClass $list; + + public ?\stdClass $create; + + public ?\stdClass $update; + + + /** + * @param Properties|static $properties + * @param Schema $ownerSchema + */ + public static function setUpProperties($properties, Schema $ownerSchema) + { + $properties->delete = ProjectsDeleteRequest::schema() ? ProjectsDeleteRequest::schema() : null; + $properties->get = ProjectGetRequest::schema() ? ProjectGetRequest::schema() : null; + $properties->list = ProjectsListRequest::schema() ? ProjectsListRequest::schema() : null; + $properties->update = ProjectPutRequest::schema() ? ProjectPutRequest::schema() : null; + $properties->create = ProjectCreateRequest::schema() ? ProjectCreateRequest::schema() : null; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->description = "> Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the projects whose IDs match the provided ones\n\nReturns: [ProjectsDeleteResponse](bitwarden::secrets_manager::projects::ProjectsDeleteResponse)"; + + $ownerSchema->oneOf = array( + self::names()->create, + self::names()->delete, + self::names()->get, + self::names()->list, + self::names()->update, + ); + } +} diff --git a/languages/php/src/schemas/ProjectsDeleteRequest.php b/languages/php/src/schemas/ProjectsDeleteRequest.php new file mode 100644 index 000000000..87a7cfad7 --- /dev/null +++ b/languages/php/src/schemas/ProjectsDeleteRequest.php @@ -0,0 +1,39 @@ +ids = Schema::arr(); + $properties->ids->items = Schema::string(); + $properties->ids->items->format = "uuid"; + $properties->ids->description = "IDs of the projects to delete"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->ids, + ); + $ownerSchema->setFromRef('#/definitions/ProjectsDeleteRequest'); + } +} diff --git a/languages/php/src/schemas/ProjectsListRequest.php b/languages/php/src/schemas/ProjectsListRequest.php new file mode 100644 index 000000000..cc1a9474f --- /dev/null +++ b/languages/php/src/schemas/ProjectsListRequest.php @@ -0,0 +1,38 @@ +organizationId = Schema::string(); + $properties->organizationId->description = "Organization to retrieve all the projects from"; + $properties->organizationId->format = "uuid"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/ProjectsListRequest'); + } +} diff --git a/languages/php/src/schemas/SecretCreateRequest.php b/languages/php/src/schemas/SecretCreateRequest.php new file mode 100644 index 000000000..d34b36e98 --- /dev/null +++ b/languages/php/src/schemas/SecretCreateRequest.php @@ -0,0 +1,58 @@ +organizationId = Schema::string(); + $properties->organizationId->description = "Organization where the secret will be created"; + $properties->organizationId->format = "uuid"; + $properties->key = Schema::string(); + $properties->value = Schema::string(); + $properties->note = Schema::string(); + $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); + $properties->projectIds->items = Schema::string(); + $properties->projectIds->items->format = "uuid"; + $properties->projectIds->description = "IDs of the projects that this secret will belong to"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->key, + self::names()->note, + self::names()->organizationId, + self::names()->value, + ); + $ownerSchema->setFromRef('#/definitions/SecretCreateRequest'); + } +} diff --git a/languages/php/src/schemas/SecretGetRequest.php b/languages/php/src/schemas/SecretGetRequest.php new file mode 100644 index 000000000..f31f7cad3 --- /dev/null +++ b/languages/php/src/schemas/SecretGetRequest.php @@ -0,0 +1,38 @@ +id = Schema::string(); + $properties->id->description = "ID of the secret to retrieve"; + $properties->id->format = "uuid"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->id, + ); + $ownerSchema->setFromRef('#/definitions/SecretGetRequest'); + } +} diff --git a/languages/php/src/schemas/SecretIdentifiersRequest.php b/languages/php/src/schemas/SecretIdentifiersRequest.php new file mode 100644 index 000000000..b4e75b801 --- /dev/null +++ b/languages/php/src/schemas/SecretIdentifiersRequest.php @@ -0,0 +1,38 @@ +organizationId = Schema::string(); + $properties->organizationId->description = "Organization to retrieve all the secrets from"; + $properties->organizationId->format = "uuid"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->organizationId, + ); + $ownerSchema->setFromRef('#/definitions/SecretIdentifiersRequest'); + } +} diff --git a/languages/php/src/schemas/SecretPutRequest.php b/languages/php/src/schemas/SecretPutRequest.php new file mode 100644 index 000000000..d890a909d --- /dev/null +++ b/languages/php/src/schemas/SecretPutRequest.php @@ -0,0 +1,64 @@ +id = Schema::string(); + $properties->id->description = "ID of the secret to modify"; + $properties->id->format = "uuid"; + $properties->organizationId = Schema::string(); + $properties->organizationId->description = "Organization ID of the secret to modify"; + $properties->organizationId->format = "uuid"; + $properties->key = Schema::string(); + $properties->value = Schema::string(); + $properties->note = Schema::string(); + $properties->projectIds = (new Schema())->setType([Schema::_ARRAY, Schema::NULL]); + $properties->projectIds->items = Schema::string(); + $properties->projectIds->items->format = "uuid"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->id, + self::names()->key, + self::names()->note, + self::names()->organizationId, + self::names()->value, + ); + $ownerSchema->setFromRef('#/definitions/SecretPutRequest'); + } +} diff --git a/languages/php/src/schemas/SecretVerificationRequest.php b/languages/php/src/schemas/SecretVerificationRequest.php new file mode 100644 index 000000000..95cfd1e15 --- /dev/null +++ b/languages/php/src/schemas/SecretVerificationRequest.php @@ -0,0 +1,35 @@ +masterPassword = (new Schema())->setType([Schema::STRING, Schema::NULL]); + $properties->masterPassword->description = "The user's master password to use for user verification. If supplied, this will be used for verification purposes."; + $properties->otp = (new Schema())->setType([Schema::STRING, Schema::NULL]); + $properties->otp->description = "Alternate user verification method through OTP. This is provided for users who have no master password due to use of Customer Managed Encryption. Must be present and valid if master_password is absent."; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->setFromRef('#/definitions/SecretVerificationRequest'); + } +} diff --git a/languages/php/src/schemas/SecretsCommand.php b/languages/php/src/schemas/SecretsCommand.php new file mode 100644 index 000000000..1ed8c97c5 --- /dev/null +++ b/languages/php/src/schemas/SecretsCommand.php @@ -0,0 +1,56 @@ + Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the secrets whose IDs match the provided ones + * + * Returns: [SecretsDeleteResponse](bitwarden::secrets_manager::secrets::SecretsDeleteResponse) + */ +class SecretsCommand extends BitwardenClassStructure +{ + public ?\stdClass $delete; + + public ?\stdClass $get; + + public ?\stdClass $getByIds; + + public ?\stdClass $list; + + public ?\stdClass $create; + + public ?\stdClass $put; + + /** + * @param Properties|static $properties + * @param Schema $ownerSchema + */ + public static function setUpProperties($properties, Schema $ownerSchema) + { + $properties->delete = SecretsDeleteRequest::schema() ? SecretsDeleteRequest::schema() : null; + $properties->getByIds = SecretsGetRequest::schema() ? SecretGetRequest::schema() : null; + $properties->create = SecretCreateRequest::schema() ? SecretCreateRequest::schema() : null; + $properties->put = SecretPutRequest::schema() ? SecretPutRequest::schema() : null; + $properties->list = SecretIdentifiersRequest::schema() ? SecretIdentifiersRequest::schema() : null; + $properties->get = SecretsGetRequest::schema() ? SecretGetRequest::schema() : null; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->description = "> Requires Authentication > Requires using an Access Token for login or calling Sync at least once Deletes all the secrets whose IDs match the provided ones\n\nReturns: [SecretsDeleteResponse](bitwarden::secrets_manager::secrets::SecretsDeleteResponse)"; + $ownerSchema->oneOf = array( + self::names()->create, + self::names()->put, + self::names()->list, + self::names()->getByIds, + self::names()->delete, + ); + } +} diff --git a/languages/php/src/schemas/SecretsDeleteRequest.php b/languages/php/src/schemas/SecretsDeleteRequest.php new file mode 100644 index 000000000..35138fcb1 --- /dev/null +++ b/languages/php/src/schemas/SecretsDeleteRequest.php @@ -0,0 +1,39 @@ +ids = Schema::arr(); + $properties->ids->items = Schema::string(); + $properties->ids->items->format = "uuid"; + $properties->ids->description = "IDs of the secrets to delete"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->ids, + ); + $ownerSchema->setFromRef('#/definitions/SecretsDeleteRequest'); + } +} diff --git a/languages/php/src/schemas/SecretsGetRequest.php b/languages/php/src/schemas/SecretsGetRequest.php new file mode 100644 index 000000000..4758dabf4 --- /dev/null +++ b/languages/php/src/schemas/SecretsGetRequest.php @@ -0,0 +1,39 @@ +ids = Schema::arr(); + $properties->ids->items = Schema::string(); + $properties->ids->items->format = "uuid"; + $properties->ids->description = "IDs of the secrets to retrieve"; + $ownerSchema->type = Schema::OBJECT; + $ownerSchema->additionalProperties = false; + $ownerSchema->required = array( + self::names()->ids, + ); + $ownerSchema->setFromRef('#/definitions/SecretsGetRequest'); + } +} From 12fa28a5b94dc7274b9f158ceca1f233aa334205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 1 Dec 2023 14:12:29 +0100 Subject: [PATCH 079/378] Unpin wasm-bindgen (#373) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective wasm-bindgen was pinned because version 0.2.88 had some accidental backwards incompatible breaking changes. Those are fixed in 0.2.89 so we can remove the pin now --- Cargo.lock | 20 ++++++++++---------- crates/bitwarden-wasm/Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50e263401..ad20c5f96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3707,9 +3707,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "serde", @@ -3719,9 +3719,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -3746,9 +3746,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3756,9 +3756,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -3769,9 +3769,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm-bindgen-test" diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 7ad0d1c3e..9a14d26b7 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -13,7 +13,7 @@ console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.63" log = "0.4.20" serde = { version = "1.0.193", features = ["derive"] } -wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.89", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.36" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } From 20c38c91d168ceadf807a6c24570cc997c954047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 1 Dec 2023 16:45:50 +0100 Subject: [PATCH 080/378] Reduce the number of CI jobs that are run on PRs (#375) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective With the recent addition of all the SDK language bindings, we've added a lot of CI jobs on PRs that are unnecessary and slow down builds. By switching them to run only on merge we should save some CI time. Ultimately, we'd want some way to make it so that the `Build Rust Cross Platform` get only called once and reused for every language SDK, but for now this should help. --- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-java.yml | 2 +- .github/workflows/publish-php.yml | 2 +- .github/workflows/publish-ruby.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 272fec363..1889d5656 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -1,7 +1,7 @@ name: Build .NET SDK on: - pull_request: + push: branches: - master diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index e500424dd..aa99523a7 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -1,7 +1,7 @@ name: Build Java SDK on: - pull_request: + push: branches: - master diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index b443f2057..bc1478bc5 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -1,7 +1,7 @@ name: Publish PHP SDK on: - pull_request: + push: branches: - master diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index da641dce5..b4e022243 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -1,7 +1,7 @@ name: Publish Ruby SDK on: - pull_request: + push: branches: - master From 267d79fe6055db6f911317c4605d3812f1adcb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 1 Dec 2023 17:17:45 +0100 Subject: [PATCH 081/378] Add binary files to gitignore (#376) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective These files have to be copied in specific places when building the SDK bindings, and having them tracked by git is quite annoying. --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 007c3e839..18d2d6639 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,13 @@ bld/ [Bb]in/ [Oo]bj/ +# Binary files +*.dylib +*.a +*.so +*.dll +*.class + # Editor directories and files .idea xcuserdata/ From 87327115365d0e75ac32e5714c12566dae647cfd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:12:38 +0100 Subject: [PATCH 082/378] [deps]: Update Rust crate wiremock to 0.5.22 (#379) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [wiremock](https://togithub.com/LukeMathWalker/wiremock-rs) | dev-dependencies | patch | `0.5.21` -> `0.5.22` | --- ### Release Notes
LukeMathWalker/wiremock-rs (wiremock) ### [`v0.5.22`](https://togithub.com/LukeMathWalker/wiremock-rs/compare/v0.5.21...v0.5.22) [Compare Source](https://togithub.com/LukeMathWalker/wiremock-rs/compare/v0.5.21...v0.5.22)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad20c5f96..49abafb26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4017,9 +4017,9 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.21" +version = "0.5.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "079aee011e8a8e625d16df9e785de30a6b77f80a6126092d76a57375f96448da" +checksum = "13a3a53eaf34f390dd30d7b1b078287dd05df2aa2e21a589ccb80f5c7253c2e9" dependencies = [ "assert-json-diff", "async-trait", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index aea2cfe9e..308f98850 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -60,4 +60,4 @@ uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" tokio = { version = "1.34.0", features = ["rt", "macros"] } -wiremock = "0.5.21" +wiremock = "0.5.22" From ac167df7ecbf39e90e5df8fcd8b809c697ebb961 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:13:46 +0100 Subject: [PATCH 083/378] [deps]: Update Rust crate clap to 4.4.10 (#378) --- Cargo.lock | 8 ++++---- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49abafb26..cc507ac33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -657,9 +657,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.8" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" dependencies = [ "clap_builder", "clap_derive", @@ -667,9 +667,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 0966f7885..86ca2fac1 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.8", features = ["derive"] } +clap = { version = "4.4.10", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 9ceb2b153..706628f53 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.8", features = ["derive", "env"] } +clap = { version = "4.4.10", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 95dbef003..cef520b1a 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.8", features = ["derive", "env", "string"] } +clap = { version = "4.4.10", features = ["derive", "env", "string"] } clap_complete = "4.4.4" color-eyre = "0.6" comfy-table = "^7.1.0" From 4dfc1150e7a82b68b271e625eeca8f8237e750a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:15:07 +0100 Subject: [PATCH 084/378] [deps]: Update System.Text.Json to v7.0.4 (#380) --- languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj index c110785a9..951b893ab 100644 --- a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj +++ b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj @@ -24,7 +24,7 @@ - + From ac340edb88d7813caecd2c552fef2b85204e19da Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 00:15:50 +0100 Subject: [PATCH 085/378] [deps]: Update quicktype-core to v23.0.80 (#382) --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ee8982ec..71dd5d501 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.79", + "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.79", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.79.tgz", - "integrity": "sha512-Auzy8AhorFt6YGeB53/dzUSINmKKassAyCsr2wpNgG9XoC3i6oUoLuySNUzYIkyCFCGmKdBRBQeyAqPOVteoYw==", + "version": "23.0.80", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.80.tgz", + "integrity": "sha512-dd+aJRzAl3MzkaXJMjUu0j60y82gwX/RRr3EvW/aScQKycvkgwliNDN2tIiLB06EKBzjgC9mtlMqKyRg2rYKhQ==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index 97f08c571..3c475897d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.0", - "quicktype-core": "23.0.79", + "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", "typescript": "5.2.2" From c4ee7bcf568d265947e1469f76dc8e8fc0a5393e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:53:52 +0100 Subject: [PATCH 086/378] [deps]: Update Rust crate async-lock to 3.2.0 (#389) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-lock](https://togithub.com/smol-rs/async-lock) | dependencies | minor | `3.1.2` -> `3.2.0` | --- ### Release Notes
smol-rs/async-lock (async-lock) ### [`v3.2.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-320) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v3.1.2...v3.2.0) - Add missing methods for blocking on locking with types wrapped in `Arc` ([#​71](https://togithub.com/smol-rs/async-lock/issues/71)).
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden-uniffi/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc507ac33..5aa51175d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -203,9 +203,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.2" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea8b3453dd7cc96711834b75400d671b73e3656975fa68d9f277163b7f7e316" +checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" dependencies = [ "event-listener 4.0.0", "event-listener-strategy", diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index c1a47ea29..ecde30a4b 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "3.1.2" +async-lock = "3.2.0" chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", From 9244d76b7e910d72f19f780d6e9189d58e268838 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:57:27 +0100 Subject: [PATCH 087/378] [deps]: Lock file maintenance (#391) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 177 ++++++++++++++------- crates/bitwarden-napi/package-lock.json | 12 +- languages/js_webassembly/package-lock.json | 72 ++++----- package-lock.json | 30 ++-- 4 files changed, 179 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5aa51175d..d1c2dc9c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -763,9 +763,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] @@ -830,9 +830,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -840,9 +840,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -961,9 +961,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ "powerfmt", ] @@ -1049,12 +1049,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1142,18 +1142,18 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs-err" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5fd9bcbe8b1087cbd395b51498c01bc997cef73e778a80b77a811af5e2d29f" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" dependencies = [ "autocfg", ] @@ -1317,9 +1317,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1329,15 +1329,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -1378,9 +1378,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -1544,9 +1544,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1576,7 +1576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", ] [[package]] @@ -1666,9 +1666,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -1726,9 +1726,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -2058,9 +2058,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -2099,9 +2099,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", @@ -2203,9 +2203,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project-lite" @@ -2280,9 +2280,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -2599,9 +2599,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ "const-oid", "digest", @@ -2625,15 +2625,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3011,9 +3011,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -3625,9 +3625,9 @@ checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -3734,9 +3734,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if", "js-sys", @@ -3775,9 +3775,9 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm-bindgen-test" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" +checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3789,19 +3789,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.37" +version = "0.3.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" +checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" dependencies = [ "proc-macro2", "quote", + "syn 2.0.39", ] [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", @@ -3882,6 +3883,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -3912,6 +3922,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3924,6 +3949,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -3936,6 +3967,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -3948,6 +3985,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -3960,6 +4003,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -3972,6 +4021,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -3984,6 +4039,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -3996,6 +4057,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.19" diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 3ccf3a7cb..a53303523 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "peer": true, "dependencies": { @@ -196,9 +196,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json index d5345c00a..c4a2126e6 100644 --- a/languages/js_webassembly/package-lock.json +++ b/languages/js_webassembly/package-lock.json @@ -116,9 +116,9 @@ } }, "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.3.tgz", - "integrity": "sha512-6mfQ6iNvhSKCZJoY6sIG3m0pKkdUcweVNOLuBBKvoWGzl2yRxOJcYOTRyLKt3nxXvBLJWa6QkW//tgbIwJehmA==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", "dev": true, "dependencies": { "@types/express-serve-static-core": "*", @@ -126,9 +126,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.44.7", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz", - "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==", + "version": "8.44.8", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", + "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -209,18 +209,18 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/node-forge": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.9.tgz", - "integrity": "sha512-meK88cx/sTalPSLSoCzkiUB4VPIFHmxtXm5FaaqRDqBX2i/Sy8bJ4odsan0b20RBjPh06dAQ+OTTdnyQyhJZyQ==", + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", + "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", "dev": true, "dependencies": { "@types/node": "*" @@ -284,9 +284,9 @@ } }, "node_modules/@types/ws": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.9.tgz", - "integrity": "sha512-jbdrY0a8lxfdTp/+r7Z4CkycbOFN8WX+IOchLJr3juT/xzbJ8URyTVSJ/hvNdadTgM1mnedb47n+Y31GsFnQlg==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dev": true, "dependencies": { "@types/node": "*" @@ -765,9 +765,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -784,9 +784,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -836,9 +836,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001563", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -917,9 +917,9 @@ } }, "node_modules/clean-css": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", - "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", "dev": true, "dependencies": { "source-map": "~0.6.0" @@ -1278,9 +1278,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.588", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", - "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", + "version": "1.4.601", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz", + "integrity": "sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==", "dev": true }, "node_modules/encodeurl": { @@ -2544,9 +2544,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -3661,9 +3661,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "peer": true, "bin": { diff --git a/package-lock.json b/package-lock.json index 71dd5d501..d9f57608b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.9.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.2.tgz", - "integrity": "sha512-WHZXKFCEyIUJzAwh3NyyTHYSR35SevJ6mZ1nWwJafKtiQbqRTIKSRcw3Ma3acqgsent3RRDqeVwpHntMk+9irg==", + "version": "20.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", + "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", "dev": true, "peer": true, "dependencies": { @@ -373,9 +373,9 @@ } }, "node_modules/@types/urijs": { - "version": "1.19.23", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.23.tgz", - "integrity": "sha512-3Zbk6RzmIpvKTNEHO2RcPOGHM++BQEITMqBRR1Ju32WbruhV/pygYgxiP3xA0b1B88zjzs0Izzjxsbj768+IjA==", + "version": "1.19.25", + "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.25.tgz", + "integrity": "sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==", "dev": true }, "node_modules/abort-controller": { @@ -584,9 +584,9 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz", - "integrity": "sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "engines": { "node": ">=6" @@ -1252,9 +1252,9 @@ } }, "node_modules/lru-cache": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.3.tgz", - "integrity": "sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", "dev": true, "engines": { "node": "14 || >=16.14" From d1ddaa7916ce29dbda28d116bb9fa485ba65a337 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:35:07 +0100 Subject: [PATCH 088/378] [deps]: Update typescript to v5.3.2 (#385) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9f57608b..bb67d4e04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", - "typescript": "5.2.2" + "typescript": "5.3.2" } }, "node_modules/@babel/runtime": { @@ -1936,9 +1936,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", + "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 3c475897d..363d8b34c 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,6 @@ "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", - "typescript": "5.2.2" + "typescript": "5.3.2" } } From 3d6b4a48c668346938425041273a8b27068578fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:35:29 +0100 Subject: [PATCH 089/378] [deps]: Update rust-wasm-bindgen monorepo (#383) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-wasm/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 9a14d26b7..dc5bf9ba5 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -10,13 +10,13 @@ crate-type = ["cdylib", "rlib"] [dependencies] console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } -js-sys = "0.3.63" +js-sys = "0.3.66" log = "0.4.20" serde = { version = "1.0.193", features = ["derive"] } wasm-bindgen = { version = "0.2.89", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.36" +wasm-bindgen-futures = "0.4.39" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [dev-dependencies] -wasm-bindgen-test = "0.3.36" +wasm-bindgen-test = "0.3.39" From 03495907dd6358253db830ca83e7e7edca1db1ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 12:09:22 +0100 Subject: [PATCH 090/378] [deps]: Lock file maintenance (#394) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> From 48aeb58eb63050c658259bfd188dd5fae9da9488 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 4 Dec 2023 18:01:57 +0100 Subject: [PATCH 091/378] Initial TOTP implementation (#392) --- Cargo.lock | 7 + crates/bitwarden-uniffi/src/vault/mod.rs | 16 +- crates/bitwarden/Cargo.toml | 2 + .../bitwarden/src/mobile/vault/client_totp.rs | 9 +- crates/bitwarden/src/vault/mod.rs | 3 +- crates/bitwarden/src/vault/totp.rs | 252 +++++++++++++++++- 6 files changed, 273 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1c2dc9c0..3a67b163f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,6 +332,7 @@ dependencies = [ "bitwarden-api-identity", "cbc", "chrono", + "data-encoding", "getrandom 0.2.11", "hkdf", "hmac", @@ -929,6 +930,12 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + [[package]] name = "deadpool" version = "0.9.5" diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index 79b3e5835..bd5f5332c 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use bitwarden::vault::TotpResponse; use chrono::{DateTime, Utc}; -use crate::Client; +use crate::{error::Result, Client}; pub mod ciphers; pub mod collections; @@ -47,13 +47,11 @@ impl ClientVault { /// - A base32 encoded string /// - OTP Auth URI /// - Steam URI - pub async fn generate_totp(&self, key: String, time: Option>) -> TotpResponse { - self.0 - .0 - .read() - .await - .vault() - .generate_totp(key, time) - .await + pub async fn generate_totp( + &self, + key: String, + time: Option>, + ) -> Result { + Ok(self.0 .0.read().await.vault().generate_totp(key, time)?) } } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 308f98850..a9e432c27 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -30,9 +30,11 @@ bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } chrono = { version = ">=0.4.26, <0.5", features = [ + "clock", "serde", "std", ], default-features = false } +data-encoding = ">=2.5.0, <3.0" # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } hkdf = ">=0.12.3, <0.13" diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs index 97eb243af..75bfd204c 100644 --- a/crates/bitwarden/src/mobile/vault/client_totp.rs +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -1,5 +1,6 @@ use chrono::{DateTime, Utc}; +use crate::error::Result; use crate::vault::{generate_totp, TotpResponse}; use super::client_vault::ClientVault; @@ -12,7 +13,11 @@ impl<'a> ClientVault<'a> { /// - OTP Auth URI /// - Steam URI /// - pub async fn generate_totp(&'a self, key: String, time: Option>) -> TotpResponse { - generate_totp(key, time).await + pub fn generate_totp( + &'a self, + key: String, + time: Option>, + ) -> Result { + generate_totp(key, time) } } diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index 12910283c..ca9b12c1c 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -10,4 +10,5 @@ pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; pub use send::{Send, SendListView, SendView}; -pub use totp::{generate_totp, TotpResponse}; +pub(crate) use totp::generate_totp; +pub use totp::TotpResponse; diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 7e701f92e..e080a85a9 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -1,7 +1,23 @@ +use std::{collections::HashMap, str::FromStr}; + +use crate::error::{Error, Result}; use chrono::{DateTime, Utc}; +use data_encoding::BASE32; +use hmac::{Hmac, Mac}; +use reqwest::Url; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +type HmacSha1 = Hmac; +type HmacSha256 = Hmac; +type HmacSha512 = Hmac; + +const STEAM_CHARS: &str = "23456789BCDFGHJKMNPQRTVWXY"; + +const DEFAULT_ALGORITHM: Algorithm = Algorithm::Sha1; +const DEFAULT_DIGITS: u32 = 6; +const DEFAULT_PERIOD: u32 = 30; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -22,9 +38,237 @@ pub struct TotpResponse { /// - Steam URI /// /// Supports providing an optional time, and defaults to current system time if none is provided. -pub async fn generate_totp(_key: String, _time: Option>) -> TotpResponse { - TotpResponse { - code: "000 000".to_string(), - period: 30, +/// +/// Arguments: +/// - `key` - The key to generate the TOTP code from +/// - `time` - The time in UTC to generate the TOTP code for, defaults to current system time +pub(crate) fn generate_totp(key: String, time: Option>) -> Result { + let params: Totp = key.parse()?; + + let time = time.unwrap_or_else(Utc::now); + + let otp = params.derive_otp(time.timestamp()); + + Ok(TotpResponse { + code: otp, + period: params.period, + }) +} + +#[derive(Clone, Copy, Debug)] +enum Algorithm { + Sha1, + Sha256, + Sha512, + Steam, +} + +impl Algorithm { + // Derive the HMAC hash for the given algorithm + fn derive_hash(&self, key: &[u8], time: &[u8]) -> Vec { + fn compute_digest(digest: D, time: &[u8]) -> Vec { + digest.chain_update(time).finalize().into_bytes().to_vec() + } + + match self { + Algorithm::Sha1 => compute_digest( + HmacSha1::new_from_slice(key).expect("hmac new_from_slice should not fail"), + time, + ), + Algorithm::Sha256 => compute_digest( + HmacSha256::new_from_slice(key).expect("hmac new_from_slice should not fail"), + time, + ), + Algorithm::Sha512 => compute_digest( + HmacSha512::new_from_slice(key).expect("hmac new_from_slice should not fail"), + time, + ), + Algorithm::Steam => compute_digest( + HmacSha1::new_from_slice(key).expect("hmac new_from_slice should not fail"), + time, + ), + } + } +} + +#[derive(Debug)] +struct Totp { + algorithm: Algorithm, + digits: u32, + period: u32, + secret: Vec, +} + +impl Totp { + fn derive_otp(&self, time: i64) -> String { + let time = time / self.period as i64; + + let hash = self + .algorithm + .derive_hash(&self.secret, time.to_be_bytes().as_ref()); + let binary = derive_binary(hash); + + if let Algorithm::Steam = self.algorithm { + derive_steam_otp(binary, self.digits) + } else { + let otp = binary % 10_u32.pow(self.digits); + format!("{1:00$}", self.digits as usize, otp) + } + } +} + +impl FromStr for Totp { + type Err = Error; + + /// Parses the provided key and returns the corresponding `Totp`. + /// + /// Key can be either: + /// - A base32 encoded string + /// - OTP Auth URI + /// - Steam URI + fn from_str(key: &str) -> Result { + fn decode_secret(secret: &str) -> Result> { + BASE32 + .decode(secret.as_bytes()) + .map_err(|_| Error::Internal("Unable to decode secret")) + } + + let params = if key.starts_with("otpauth://") { + let url = Url::parse(key).map_err(|_| Error::Internal("Unable to parse URL"))?; + let parts: HashMap<_, _> = url.query_pairs().collect(); + + Totp { + algorithm: parts + .get("algorithm") + .and_then(|v| match v.to_uppercase().as_ref() { + "SHA1" => Some(Algorithm::Sha1), + "SHA256" => Some(Algorithm::Sha256), + "SHA512" => Some(Algorithm::Sha512), + _ => None, + }) + .unwrap_or(DEFAULT_ALGORITHM), + digits: parts + .get("digits") + .and_then(|v| v.parse().ok()) + .map(|v: u32| v.clamp(0, 10)) + .unwrap_or(DEFAULT_DIGITS), + period: parts + .get("period") + .and_then(|v| v.parse().ok()) + .map(|v: u32| v.max(1)) + .unwrap_or(DEFAULT_PERIOD), + secret: decode_secret( + &parts + .get("secret") + .map(|v| v.to_string()) + .ok_or(Error::Internal("Missing secret in otpauth URI"))?, + )?, + } + } else if let Some(secret) = key.strip_prefix("steam://") { + Totp { + algorithm: Algorithm::Steam, + digits: 5, + period: DEFAULT_PERIOD, + secret: decode_secret(secret)?, + } + } else { + Totp { + algorithm: DEFAULT_ALGORITHM, + digits: DEFAULT_DIGITS, + period: DEFAULT_PERIOD, + secret: decode_secret(key)?, + } + }; + + Ok(params) + } +} + +/// Derive the Steam OTP from the hash with the given number of digits. +fn derive_steam_otp(binary: u32, digits: u32) -> String { + let mut full_code = binary & 0x7fffffff; + + (0..digits) + .map(|_| { + let index = full_code as usize % STEAM_CHARS.len(); + let char = STEAM_CHARS + .chars() + .nth(index) + .expect("Should always be within range"); + full_code /= STEAM_CHARS.len() as u32; + char + }) + .collect() +} + +/// Derive the OTP from the hash with the given number of digits. +fn derive_binary(hash: Vec) -> u32 { + let offset = (hash.last().unwrap_or(&0) & 15) as usize; + + ((hash[offset] & 127) as u32) << 24 + | (hash[offset + 1] as u32) << 16 + | (hash[offset + 2] as u32) << 8 + | hash[offset + 3] as u32 +} + +#[cfg(test)] +mod tests { + use super::*; + use chrono::Utc; + + #[test] + fn test_generate_totp() { + let key = "WQIQ25BRKZYCJVYP".to_string(); + let time = Some( + DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") + .unwrap() + .with_timezone(&Utc), + ); + let response = generate_totp(key, time).unwrap(); + + assert_eq!(response.code, "194506".to_string()); + assert_eq!(response.period, 30); + } + + #[test] + fn test_generate_otpauth() { + let key = "otpauth://totp/test-account?secret=WQIQ25BRKZYCJVYP".to_string(); + let time = Some( + DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") + .unwrap() + .with_timezone(&Utc), + ); + let response = generate_totp(key, time).unwrap(); + + assert_eq!(response.code, "194506".to_string()); + assert_eq!(response.period, 30); + } + + #[test] + fn test_generate_otpauth_period() { + let key = "otpauth://totp/test-account?secret=WQIQ25BRKZYCJVYP&period=60".to_string(); + let time = Some( + DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") + .unwrap() + .with_timezone(&Utc), + ); + let response = generate_totp(key, time).unwrap(); + + assert_eq!(response.code, "730364".to_string()); + assert_eq!(response.period, 60); + } + + #[test] + fn test_generate_steam() { + let key = "steam://HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".to_string(); + let time = Some( + DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") + .unwrap() + .with_timezone(&Utc), + ); + let response = generate_totp(key, time).unwrap(); + + assert_eq!(response.code, "7W6CJ".to_string()); + assert_eq!(response.period, 30); } } From 7fc3b8436612b6218ca039ff530e12e7d7232a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 4 Dec 2023 19:19:11 +0100 Subject: [PATCH 092/378] [PM-3435] Passphrase generator (#262) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Added passphrase generator, including `bw` cli support --------- Co-authored-by: Hinton --- .../src/tool/generators/client_generator.rs | 26 +- crates/bitwarden/src/tool/generators/mod.rs | 4 +- .../src/tool/generators/passphrase.rs | 236 ++++++++++++++++++ .../bitwarden/src/tool/generators/password.rs | 17 -- crates/bw/src/main.rs | 32 ++- languages/kotlin/doc.md | 16 +- 6 files changed, 299 insertions(+), 32 deletions(-) create mode 100644 crates/bitwarden/src/tool/generators/passphrase.rs diff --git a/crates/bitwarden/src/tool/generators/client_generator.rs b/crates/bitwarden/src/tool/generators/client_generator.rs index 0384eec6a..8af8ecd19 100644 --- a/crates/bitwarden/src/tool/generators/client_generator.rs +++ b/crates/bitwarden/src/tool/generators/client_generator.rs @@ -1,8 +1,7 @@ use crate::{ error::Result, - tool::generators::password::{ - passphrase, password, PassphraseGeneratorRequest, PasswordGeneratorRequest, - }, + tool::generators::passphrase::{passphrase, PassphraseGeneratorRequest}, + tool::generators::password::{password, PasswordGeneratorRequest}, Client, }; @@ -15,6 +14,27 @@ impl<'a> ClientGenerator<'a> { password(input) } + /// Generates a random passphrase. + /// A passphrase is a combination of random words separated by a character. + /// An example of passphrase is `correct horse battery staple`. + /// + /// The number of words and their case, the word separator, and the inclusion of + /// a number in the passphrase can be customized using the `input` parameter. + /// + /// # Examples + /// + /// ``` + /// use bitwarden::{Client, tool::PassphraseGeneratorRequest, error::Result}; + /// async fn test() -> Result<()> { + /// let input = PassphraseGeneratorRequest { + /// num_words: 4, + /// ..Default::default() + /// }; + /// let passphrase = Client::new(None).generator().passphrase(input).await.unwrap(); + /// println!("{}", passphrase); + /// Ok(()) + /// } + /// ``` pub async fn passphrase(&self, input: PassphraseGeneratorRequest) -> Result { passphrase(input) } diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs index 4d991b765..12c526930 100644 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ b/crates/bitwarden/src/tool/generators/mod.rs @@ -1,5 +1,7 @@ mod client_generator; +mod passphrase; mod password; pub use client_generator::ClientGenerator; -pub use password::{PassphraseGeneratorRequest, PasswordGeneratorRequest}; +pub use passphrase::PassphraseGeneratorRequest; +pub use password::PasswordGeneratorRequest; diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden/src/tool/generators/passphrase.rs new file mode 100644 index 000000000..e62fa8f9a --- /dev/null +++ b/crates/bitwarden/src/tool/generators/passphrase.rs @@ -0,0 +1,236 @@ +use crate::{ + error::{Error, Result}, + wordlist::EFF_LONG_WORD_LIST, +}; +use rand::{seq::SliceRandom, Rng, RngCore}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +/// Passphrase generator request options. +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct PassphraseGeneratorRequest { + /// Number of words in the generated passphrase. + /// This value must be between 3 and 20. + pub num_words: u8, + /// Character separator between words in the generated passphrase. The value cannot be empty. + pub word_separator: String, + /// When set to true, capitalize the first letter of each word in the generated passphrase. + pub capitalize: bool, + /// When set to true, include a number at the end of one of the words in the generated passphrase. + pub include_number: bool, +} + +impl Default for PassphraseGeneratorRequest { + fn default() -> Self { + Self { + num_words: 3, + word_separator: ' '.to_string(), + capitalize: false, + include_number: false, + } + } +} + +const MINIMUM_PASSPHRASE_NUM_WORDS: u8 = 3; +const MAXIMUM_PASSPHRASE_NUM_WORDS: u8 = 20; + +/// Represents a set of valid options to generate a passhprase with. +/// To get an instance of it, use [`PassphraseGeneratorRequest::validate_options`](PassphraseGeneratorRequest::validate_options) +struct ValidPassphraseGeneratorOptions { + pub(super) num_words: u8, + pub(super) word_separator: String, + pub(super) capitalize: bool, + pub(super) include_number: bool, +} + +impl PassphraseGeneratorRequest { + /// Validates the request and returns an immutable struct with valid options to use with the passphrase generator. + fn validate_options(self) -> Result { + // TODO: Add password generator policy checks + + if !(MINIMUM_PASSPHRASE_NUM_WORDS..=MAXIMUM_PASSPHRASE_NUM_WORDS).contains(&self.num_words) + { + return Err(Error::Internal("'num_words' must be between 3 and 20")); + } + + if self.word_separator.chars().next().is_none() { + return Err(Error::Internal("'word_separator' cannot be empty")); + }; + + Ok(ValidPassphraseGeneratorOptions { + num_words: self.num_words, + word_separator: self.word_separator, + capitalize: self.capitalize, + include_number: self.include_number, + }) + } +} + +/// Implementation of the random passphrase generator. This is not accessible to the public API. +/// See [`ClientGenerator::passphrase`](crate::ClientGenerator::passphrase) for the API function. +/// +/// # Arguments: +/// * `options`: Valid parameters used to generate the passphrase. To create it, use +/// [`PassphraseGeneratorRequest::validate_options`](PassphraseGeneratorRequest::validate_options). +pub(super) fn passphrase(request: PassphraseGeneratorRequest) -> Result { + let options = request.validate_options()?; + Ok(passphrase_with_rng(rand::thread_rng(), options)) +} + +fn passphrase_with_rng(mut rng: impl RngCore, options: ValidPassphraseGeneratorOptions) -> String { + let mut passphrase_words = gen_words(&mut rng, options.num_words); + if options.include_number { + include_number_in_words(&mut rng, &mut passphrase_words); + } + if options.capitalize { + capitalize_words(&mut passphrase_words); + } + passphrase_words.join(&options.word_separator) +} + +fn gen_words(mut rng: impl RngCore, num_words: u8) -> Vec { + (0..num_words) + .map(|_| { + EFF_LONG_WORD_LIST + .choose(&mut rng) + .expect("slice is not empty") + .to_string() + }) + .collect() +} + +fn include_number_in_words(mut rng: impl RngCore, words: &mut [String]) { + let number_idx = rng.gen_range(0..words.len()); + words[number_idx].push_str(&rng.gen_range(0..=9).to_string()); +} + +fn capitalize_words(words: &mut [String]) { + words + .iter_mut() + .for_each(|w| *w = capitalize_first_letter(w)); +} + +fn capitalize_first_letter(s: &str) -> String { + // Unicode case conversion can change the length of the string, so we can't capitalize in place. + // Instead we extract the first character and convert it to uppercase. This returns + // an iterator which we collect into a string, and then append the rest of the input. + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +#[cfg(test)] +mod tests { + use rand::SeedableRng; + + use super::*; + + #[test] + fn test_gen_words() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + assert_eq!( + &gen_words(&mut rng, 4), + &["subsystem", "undertook", "silenced", "dinginess"] + ); + assert_eq!(&gen_words(&mut rng, 1), &["numbing"]); + assert_eq!(&gen_words(&mut rng, 2), &["catnip", "jokester"]); + } + + #[test] + fn test_capitalize() { + assert_eq!(capitalize_first_letter("hello"), "Hello"); + assert_eq!(capitalize_first_letter("1ello"), "1ello"); + assert_eq!(capitalize_first_letter("Hello"), "Hello"); + assert_eq!(capitalize_first_letter("h"), "H"); + assert_eq!(capitalize_first_letter(""), ""); + + // Also supports non-ascii, though the EFF list doesn't have any + assert_eq!(capitalize_first_letter("áéíóú"), "Áéíóú"); + } + + #[test] + fn test_capitalize_words() { + let mut words = vec!["hello".into(), "world".into()]; + capitalize_words(&mut words); + assert_eq!(words, &["Hello", "World"]); + } + + #[test] + fn test_include_number() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let mut words = vec!["hello".into(), "world".into()]; + include_number_in_words(&mut rng, &mut words); + assert_eq!(words, &["hello", "world7"]); + + let mut words = vec!["This".into(), "is".into(), "a".into(), "test".into()]; + include_number_in_words(&mut rng, &mut words); + assert_eq!(words, &["This", "is", "a1", "test"]); + } + + #[test] + fn test_separator() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let input = PassphraseGeneratorRequest { + num_words: 4, + word_separator: "👨🏻‍❤️‍💋‍👨🏻".into(), // This emoji is 35 bytes long, but represented as a single character + capitalize: false, + include_number: true, + } + .validate_options() + .unwrap(); + assert_eq!( + passphrase_with_rng(&mut rng, input), + "subsystem4👨🏻‍❤️‍💋‍👨🏻undertook👨🏻‍❤️‍💋‍👨🏻silenced👨🏻‍❤️‍💋‍👨🏻dinginess" + ); + } + + #[test] + fn test_passphrase() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let input = PassphraseGeneratorRequest { + num_words: 4, + word_separator: "-".into(), + capitalize: true, + include_number: true, + } + .validate_options() + .unwrap(); + assert_eq!( + passphrase_with_rng(&mut rng, input), + "Subsystem4-Undertook-Silenced-Dinginess" + ); + + let input = PassphraseGeneratorRequest { + num_words: 3, + word_separator: " ".into(), + capitalize: false, + include_number: true, + } + .validate_options() + .unwrap(); + assert_eq!( + passphrase_with_rng(&mut rng, input), + "drew7 hankering cabana" + ); + + let input = PassphraseGeneratorRequest { + num_words: 5, + word_separator: ";".into(), + capitalize: false, + include_number: false, + } + .validate_options() + .unwrap(); + assert_eq!( + passphrase_with_rng(&mut rng, input), + "duller;backlight;factual;husked;remover" + ); + } +} diff --git a/crates/bitwarden/src/tool/generators/password.rs b/crates/bitwarden/src/tool/generators/password.rs index 0a3874082..237394f56 100644 --- a/crates/bitwarden/src/tool/generators/password.rs +++ b/crates/bitwarden/src/tool/generators/password.rs @@ -27,23 +27,6 @@ pub struct PasswordGeneratorRequest { pub min_special: Option, } -/// Passphrase generator request. -/// -/// The default separator is `-` and default number of words is 3. -#[derive(Serialize, Deserialize, Debug, JsonSchema, Default)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -#[cfg_attr(feature = "mobile", derive(uniffi::Record))] -pub struct PassphraseGeneratorRequest { - pub num_words: Option, - pub word_separator: Option, - pub capitalize: Option, - pub include_number: Option, -} - pub(super) fn password(_input: PasswordGeneratorRequest) -> Result { Ok("pa11w0rd".to_string()) } - -pub(super) fn passphrase(_input: PassphraseGeneratorRequest) -> Result { - Ok("correct-horse-battery-staple".to_string()) -} diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index 609650ab1..c4664c7f4 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -1,5 +1,7 @@ use bitwarden::{ - auth::RegisterRequest, client::client_settings::ClientSettings, tool::PasswordGeneratorRequest, + auth::RegisterRequest, + client::client_settings::ClientSettings, + tool::{PassphraseGeneratorRequest, PasswordGeneratorRequest}, }; use bitwarden_cli::{install_color_eyre, text_prompt_when_none, Color}; use clap::{command, Args, CommandFactory, Parser, Subcommand}; @@ -87,7 +89,7 @@ enum ItemCommands { #[derive(Subcommand, Clone)] enum GeneratorCommands { Password(PasswordGeneratorArgs), - Passphrase {}, + Passphrase(PassphraseGeneratorArgs), } #[derive(Args, Clone)] @@ -113,6 +115,18 @@ struct PasswordGeneratorArgs { length: u8, } +#[derive(Args, Clone)] +struct PassphraseGeneratorArgs { + #[arg(long, default_value = "3", help = "Number of words in the passphrase")] + words: u8, + #[arg(long, default_value = " ", help = "Separator between words")] + separator: char, + #[arg(long, action, help = "Capitalize the first letter of each word")] + capitalize: bool, + #[arg(long, action, help = "Include a number in one of the words")] + include_number: bool, +} + #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); @@ -206,7 +220,19 @@ async fn process_commands() -> Result<()> { println!("{}", password); } - GeneratorCommands::Passphrase {} => todo!(), + GeneratorCommands::Passphrase(args) => { + let passphrase = client + .generator() + .passphrase(PassphraseGeneratorRequest { + num_words: args.words, + word_separator: args.separator.to_string(), + capitalize: args.capitalize, + include_number: args.include_number, + }) + .await?; + + println!("{}", passphrase); + } }, }; diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 652e09813..a84397719 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -1120,23 +1120,23 @@ implementations.
- - + + - - + + - - + + - - + +
numWordsinteger,nullintegerNumber of words in the generated passphrase. This value must be between 3 and 20.
wordSeparatorstring,nullstringCharacter separator between words in the generated passphrase. If the value is set, it cannot be empty.
capitalizeboolean,nullbooleanWhen set to true, capitalize the first letter of each word in the generated passphrase.
includeNumberboolean,nullbooleanWhen set to true, include a number at the end of one of the words in the generated passphrase.
From f684cc9ae7a17b535ca3cf9c8d4bb3a1f04ace16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 4 Dec 2023 20:14:41 +0100 Subject: [PATCH 093/378] Generate better schema types (#341) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective The `quicktype` schema generation seems to have trouble with types in schema files being referenced from other types in separate schema files, which created duplicate classes, with a lot of strange names. Instead of generating one individual file for each response, we create a big struct with all the options. This seems to solve the issue of references between schema files, and so no duplicate classes are created. Note that the way that the file is loaded in `quicktype` is different. By default, `quicktype` generates JSON conversion helper functions only for the root type, which would be the big struct `SchemaTypes`. By importing the file with `#/definitions/` appended, we only bring the sub schemas as root types, and ignore `SchemaTypes`, which we don't care about. Examples of the schema changes, using C# as an example: - `ProjectsResponse` previously contained an array of `DatumElement`, which were identical to `ProjectResponse`. Now it properly contains an array of `ProjectResponse`. This is also applicable to `SecretsResponse` which contained an array of `DatumClass` - Previously it would generate multiple variants for `Argon2ID`, named: `FluffyArgon2Id` and `PurpleArgon2Id`, now there is only one `Argon2Id`. This is applicable to the two factor response types, which change in the same way This is working correctly with the Java, Go, C++, PHP and Ruby bindings. --- crates/sdk-schemas/src/main.rs | 60 +++++++++++++++++----------------- support/scripts/schemas.ts | 22 +++++-------- 2 files changed, 38 insertions(+), 44 deletions(-) diff --git a/crates/sdk-schemas/src/main.rs b/crates/sdk-schemas/src/main.rs index ef7a2db83..0cfc045a0 100644 --- a/crates/sdk-schemas/src/main.rs +++ b/crates/sdk-schemas/src/main.rs @@ -1,8 +1,7 @@ use std::{fs::File, io::Write}; use anyhow::Result; -use itertools::Itertools; -use schemars::{schema::RootSchema, schema_for}; +use schemars::{schema::RootSchema, schema_for, JsonSchema}; /// Creates a json schema file for any type passed in using Schemars. The filename and path of the generated /// schema file is derived from the namespace passed into the macro or supplied as the first argument. @@ -45,6 +44,8 @@ use schemars::{schema::RootSchema, schema_for}; /// will generate `Response.json` at `{{pwd}}/path/to/folder/Response.json` macro_rules! write_schema_for { ($type:ty) => { + use itertools::Itertools; + let schema = schema_for!($type); let type_name = stringify!($type); @@ -65,12 +66,6 @@ macro_rules! write_schema_for { }; } -macro_rules! write_schema_for_response { - ( $($type:ty),+ $(,)? ) => { - $( write_schema_for!("response", bitwarden_json::response::Response<$type>); )+ - }; -} - fn write_schema(schema: RootSchema, dir_path: String, type_name: String) -> Result<()> { let file_name = type_name .split("::") @@ -88,34 +83,39 @@ fn write_schema(schema: RootSchema, dir_path: String, type_name: String) -> Resu Ok(()) } -fn main() -> Result<()> { +use bitwarden_json::response::Response; + +#[allow(dead_code)] +#[derive(JsonSchema)] +struct SchemaTypes { // Input types for new Client - write_schema_for!(bitwarden::client::client_settings::ClientSettings); + client_settings: bitwarden::client::client_settings::ClientSettings, + // Input types for Client::run_command - write_schema_for!(bitwarden_json::command::Command); + input_command: bitwarden_json::command::Command, // Output types for Client::run_command - // Only add structs which are direct results of SDK commands. - write_schema_for_response! { - bitwarden::auth::login::ApiKeyLoginResponse, - bitwarden::auth::login::PasswordLoginResponse, - bitwarden::auth::login::AccessTokenLoginResponse, - bitwarden::secrets_manager::secrets::SecretIdentifiersResponse, - bitwarden::secrets_manager::secrets::SecretResponse, - bitwarden::secrets_manager::secrets::SecretsResponse, - bitwarden::secrets_manager::secrets::SecretsDeleteResponse, - bitwarden::secrets_manager::projects::ProjectResponse, - bitwarden::secrets_manager::projects::ProjectsResponse, - bitwarden::secrets_manager::projects::ProjectsDeleteResponse, - }; + api_key_login: Response, + password_login: Response, + access_token_login: Response, + secret_identifiers: Response, + secret: Response, + secrets: Response, + secrets_delete: Response, + project: Response, + projects: Response, + projects_delete: Response, - // Same as above, but for the internal feature #[cfg(feature = "internal")] - write_schema_for_response! { - bitwarden::platform::FingerprintResponse, - bitwarden::platform::SyncResponse, - bitwarden::platform::UserApiKeyResponse, - }; + fingerprint: Response, + #[cfg(feature = "internal")] + sync: Response, + #[cfg(feature = "internal")] + user_api_key: Response, +} + +fn main() -> Result<()> { + write_schema_for!("schema_types", SchemaTypes); #[cfg(feature = "internal")] write_schema_for!(bitwarden_uniffi::docs::DocRef); diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 9e25bedc5..602a68bbb 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -22,22 +22,16 @@ async function* walk(dir: string): AsyncIterable { async function main() { const schemaInput = new JSONSchemaInput(new FetchingJSONSchemaStore()); - - const filenames: string[] = []; - for await (const p of walk("./support/schemas")) { - filenames.push(p); - } - - filenames.sort(); - - for (const f of filenames) { - const buffer = fs.readFileSync(f); - const relative = path.relative(path.join(process.cwd(), "support/schemas"), f); - await schemaInput.addSource({ name: relative, schema: buffer.toString() }); - } - const inputData = new InputData(); inputData.addInput(schemaInput); + inputData.addSource( + "schema", + { + name: "SchemaTypes", + uris: ["support/schemas/schema_types/SchemaTypes.json#/definitions/"], + }, + () => new JSONSchemaInput(new FetchingJSONSchemaStore()), + ); const ts = await quicktype({ inputData, From c006cbb2a04bce4afe90c12719986c68386aa4cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 5 Dec 2023 14:53:03 +0100 Subject: [PATCH 094/378] [PM-3434] Password generator (#261) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement password generation The `min_` fields were set to bool incorrectly I assume, so I changed them to u8. At the moment if all the minimums turn out larger than the length, I just expand the length, but that seems wrong. I feel like it would be best to return an error in that case instead of changing any values behind the user, thoughts? --- .../src/tool/generators/client_generator.rs | 21 + .../bitwarden/src/tool/generators/password.rs | 396 +++++++++++++++++- crates/bw/src/main.rs | 2 +- 3 files changed, 401 insertions(+), 18 deletions(-) diff --git a/crates/bitwarden/src/tool/generators/client_generator.rs b/crates/bitwarden/src/tool/generators/client_generator.rs index 8af8ecd19..4675ad99d 100644 --- a/crates/bitwarden/src/tool/generators/client_generator.rs +++ b/crates/bitwarden/src/tool/generators/client_generator.rs @@ -10,6 +10,27 @@ pub struct ClientGenerator<'a> { } impl<'a> ClientGenerator<'a> { + /// Generates a random password. + /// + /// The character sets and password length can be customized using the `input` parameter. + /// + /// # Examples + /// + /// ``` + /// use bitwarden::{Client, tool::PasswordGeneratorRequest, error::Result}; + /// async fn test() -> Result<()> { + /// let input = PasswordGeneratorRequest { + /// lowercase: true, + /// uppercase: true, + /// numbers: true, + /// length: 20, + /// ..Default::default() + /// }; + /// let password = Client::new(None).generator().password(input).await.unwrap(); + /// println!("{}", password); + /// Ok(()) + /// } + /// ``` pub async fn password(&self, input: PasswordGeneratorRequest) -> Result { password(input) } diff --git a/crates/bitwarden/src/tool/generators/password.rs b/crates/bitwarden/src/tool/generators/password.rs index 237394f56..cf986495c 100644 --- a/crates/bitwarden/src/tool/generators/password.rs +++ b/crates/bitwarden/src/tool/generators/password.rs @@ -1,32 +1,394 @@ -use crate::error::Result; +use std::collections::BTreeSet; + +use rand::{distributions::Distribution, seq::SliceRandom, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -/// Password generator request. If all options are false, the default is to -/// generate a password with: -/// - lowercase -/// - uppercase -/// - numbers -/// -/// The default length is 16. -#[derive(Serialize, Deserialize, Debug, JsonSchema, Default)] +use crate::error::{Error, Result}; + +/// Password generator request options. +#[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct PasswordGeneratorRequest { + /// Include lowercase characters (a-z). pub lowercase: bool, + /// Include uppercase characters (A-Z). pub uppercase: bool, + /// Include numbers (0-9). pub numbers: bool, + /// Include special characters: ! @ # $ % ^ & * pub special: bool, - pub length: Option, + /// The length of the generated password. + /// Note that the password length must be greater than the sum of all the minimums. + pub length: u8, + + /// When set to true, the generated password will not contain ambiguous characters. + /// The ambiguous characters are: I, O, l, 0, 1 + pub avoid_ambiguous: bool, // TODO: Should we rename this to include_all_characters? + + /// The minimum number of lowercase characters in the generated password. + /// When set, the value must be between 1 and 9. This value is ignored is lowercase is false + pub min_lowercase: Option, + /// The minimum number of uppercase characters in the generated password. + /// When set, the value must be between 1 and 9. This value is ignored is uppercase is false + pub min_uppercase: Option, + /// The minimum number of numbers in the generated password. + /// When set, the value must be between 1 and 9. This value is ignored is numbers is false + pub min_number: Option, + /// The minimum number of special characters in the generated password. + /// When set, the value must be between 1 and 9. This value is ignored is special is false + pub min_special: Option, +} + +const DEFAULT_PASSWORD_LENGTH: u8 = 16; + +impl Default for PasswordGeneratorRequest { + fn default() -> Self { + Self { + lowercase: true, + uppercase: true, + numbers: true, + special: false, + length: DEFAULT_PASSWORD_LENGTH, + avoid_ambiguous: false, + min_lowercase: None, + min_uppercase: None, + min_number: None, + min_special: None, + } + } +} + +const UPPER_CHARS_AMBIGUOUS: &[char] = &['I', 'O']; +const LOWER_CHARS_AMBIGUOUS: &[char] = &['l']; +const NUMBER_CHARS_AMBIGUOUS: &[char] = &['0', '1']; +const SPECIAL_CHARS: &[char] = &['!', '@', '#', '$', '%', '^', '&', '*']; + +/// A set of characters used to generate a password. This set is backed by a BTreeSet +/// to have consistent ordering between runs. This is not important during normal execution, +/// but it's necessary for the tests to be repeatable. +/// To create an instance, use [`CharSet::default()`](CharSet::default) +#[derive(Clone, Default)] +struct CharSet(BTreeSet); +impl CharSet { + /// Includes the given characters in the set. Any duplicate items will be ignored + pub fn include(self, other: impl IntoIterator) -> Self { + self.include_if(true, other) + } + + /// Includes the given characters in the set if the predicate is true. Any duplicate items will be ignored + pub fn include_if(mut self, predicate: bool, other: impl IntoIterator) -> Self { + if predicate { + self.0.extend(other); + } + self + } + + /// Excludes the given characters from the set. Any missing items will be ignored + pub fn exclude_if<'a>( + self, + predicate: bool, + other: impl IntoIterator, + ) -> Self { + if predicate { + let other: BTreeSet<_> = other.into_iter().copied().collect(); + Self(self.0.difference(&other).copied().collect()) + } else { + self + } + } +} +impl<'a> IntoIterator for &'a CharSet { + type Item = char; + type IntoIter = std::iter::Copied>; + fn into_iter(self) -> Self::IntoIter { + self.0.iter().copied() + } +} +impl Distribution for CharSet { + fn sample(&self, rng: &mut R) -> char { + let idx = rng.gen_range(0..self.0.len()); + *self.0.iter().nth(idx).expect("Valid index") + } +} + +/// Represents a set of valid options to generate a password with. +/// To get an instance of it, use [`PasswordGeneratorRequest::validate_options`](PasswordGeneratorRequest::validate_options) +struct PasswordGeneratorOptions { + pub(super) lower: (CharSet, usize), + pub(super) upper: (CharSet, usize), + pub(super) number: (CharSet, usize), + pub(super) special: (CharSet, usize), + pub(super) all: (CharSet, usize), + + pub(super) length: usize, +} + +impl PasswordGeneratorRequest { + /// Validates the request and returns an immutable struct with valid options to use with the password generator. + fn validate_options(self) -> Result { + // TODO: Add password generator policy checks + + // We always have to have at least one character set enabled + if !self.lowercase && !self.uppercase && !self.numbers && !self.special { + return Err(Error::Internal( + "At least one character set must be enabled", + )); + } + + if self.length < 4 { + return Err(Error::Internal( + "A password must be at least 4 characters long", + )); + } + + // Make sure the minimum values are zero when the character + // set is disabled, and at least one when it's enabled + fn get_minimum(min: Option, enabled: bool) -> usize { + if enabled { + usize::max(min.unwrap_or(1) as usize, 1) + } else { + 0 + } + } + + let length = self.length as usize; + let min_lowercase = get_minimum(self.min_lowercase, self.lowercase); + let min_uppercase = get_minimum(self.min_uppercase, self.uppercase); + let min_number = get_minimum(self.min_number, self.numbers); + let min_special = get_minimum(self.min_special, self.special); + + // Check that the minimum lengths aren't larger than the password length + let minimum_length = min_lowercase + min_uppercase + min_number + min_special; + if minimum_length > length { + return Err(Error::Internal( + "Password length can't be less than the sum of the minimums", + )); + } + + let lower = ( + CharSet::default() + .include_if(self.lowercase, 'a'..='z') + .exclude_if(self.avoid_ambiguous, LOWER_CHARS_AMBIGUOUS), + min_lowercase, + ); + + let upper = ( + CharSet::default() + .include_if(self.uppercase, 'A'..='Z') + .exclude_if(self.avoid_ambiguous, UPPER_CHARS_AMBIGUOUS), + min_uppercase, + ); + + let number = ( + CharSet::default() + .include_if(self.numbers, '0'..='9') + .exclude_if(self.avoid_ambiguous, NUMBER_CHARS_AMBIGUOUS), + min_number, + ); + + let special = ( + CharSet::default().include_if(self.special, SPECIAL_CHARS.iter().copied()), + min_special, + ); + + let all = ( + CharSet::default() + .include(&lower.0) + .include(&upper.0) + .include(&number.0) + .include(&special.0), + length - minimum_length, + ); + + Ok(PasswordGeneratorOptions { + lower, + upper, + number, + special, + all, + length, + }) + } +} + +/// Implementation of the random password generator. This is not accessible to the public API. +/// See [`ClientGenerator::password`](crate::ClientGenerator::password) for the API function. +pub(super) fn password(input: PasswordGeneratorRequest) -> Result { + let options = input.validate_options()?; + Ok(password_with_rng(rand::thread_rng(), options)) +} + +fn password_with_rng(mut rng: impl RngCore, options: PasswordGeneratorOptions) -> String { + let mut buf: Vec = Vec::with_capacity(options.length); + + let opts = [ + &options.all, + &options.upper, + &options.lower, + &options.number, + &options.special, + ]; + for (set, qty) in opts { + buf.extend(set.sample_iter(&mut rng).take(*qty)); + } + + buf.shuffle(&mut rng); - pub avoid_ambiguous: Option, // TODO: Should we rename this to include_all_characters? - pub min_lowercase: Option, - pub min_uppercase: Option, - pub min_number: Option, - pub min_special: Option, + buf.iter().collect() } -pub(super) fn password(_input: PasswordGeneratorRequest) -> Result { - Ok("pa11w0rd".to_string()) +#[cfg(test)] +mod test { + use std::collections::BTreeSet; + + use rand::SeedableRng; + + use super::*; + + // We convert the slices to BTreeSets to be able to use `is_subset` + fn ref_to_set<'a>(chars: impl IntoIterator) -> BTreeSet { + chars.into_iter().copied().collect() + } + fn to_set(chars: impl IntoIterator) -> BTreeSet { + chars.into_iter().collect() + } + + #[test] + fn test_password_gen_all_charsets_enabled() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let options = PasswordGeneratorRequest { + lowercase: true, + uppercase: true, + numbers: true, + special: true, + avoid_ambiguous: false, + ..Default::default() + } + .validate_options() + .unwrap(); + + assert_eq!(to_set(&options.lower.0), to_set('a'..='z')); + assert_eq!(to_set(&options.upper.0), to_set('A'..='Z')); + assert_eq!(to_set(&options.number.0), to_set('0'..='9')); + assert_eq!(to_set(&options.special.0), ref_to_set(SPECIAL_CHARS)); + + let pass = password_with_rng(&mut rng, options); + assert_eq!(pass, "Z!^B5r%hUa23dFM@"); + } + + #[test] + fn test_password_gen_only_letters_enabled() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let options = PasswordGeneratorRequest { + lowercase: true, + uppercase: true, + numbers: false, + special: false, + avoid_ambiguous: false, + ..Default::default() + } + .validate_options() + .unwrap(); + + assert_eq!(to_set(&options.lower.0), to_set('a'..='z')); + assert_eq!(to_set(&options.upper.0), to_set('A'..='Z')); + assert_eq!(to_set(&options.number.0), to_set([])); + assert_eq!(to_set(&options.special.0), to_set([])); + + let pass = password_with_rng(&mut rng, options); + assert_eq!(pass, "NQiFrGufQMiNUAmj"); + } + + #[test] + fn test_password_gen_only_numbers_and_lower_enabled_no_ambiguous() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let options = PasswordGeneratorRequest { + lowercase: true, + uppercase: false, + numbers: true, + special: false, + avoid_ambiguous: true, + ..Default::default() + } + .validate_options() + .unwrap(); + + assert!(to_set(&options.lower.0).is_subset(&to_set('a'..='z'))); + assert!(to_set(&options.lower.0).is_disjoint(&ref_to_set(LOWER_CHARS_AMBIGUOUS))); + + assert!(to_set(&options.number.0).is_subset(&to_set('0'..='9'))); + assert!(to_set(&options.number.0).is_disjoint(&ref_to_set(NUMBER_CHARS_AMBIGUOUS))); + + assert_eq!(to_set(&options.upper.0), to_set([])); + assert_eq!(to_set(&options.special.0), to_set([])); + + let pass = password_with_rng(&mut rng, options); + assert_eq!(pass, "mnjabfz5ct272prf"); + } + + #[test] + fn test_password_gen_only_upper_and_special_enabled_no_ambiguous() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let options = PasswordGeneratorRequest { + lowercase: false, + uppercase: true, + numbers: false, + special: true, + avoid_ambiguous: true, + ..Default::default() + } + .validate_options() + .unwrap(); + + assert!(to_set(&options.upper.0).is_subset(&to_set('A'..='Z'))); + assert!(to_set(&options.upper.0).is_disjoint(&ref_to_set(UPPER_CHARS_AMBIGUOUS))); + + assert_eq!(to_set(&options.special.0), ref_to_set(SPECIAL_CHARS)); + + assert_eq!(to_set(&options.lower.0), to_set([])); + assert_eq!(to_set(&options.number.0), to_set([])); + + let pass = password_with_rng(&mut rng, options); + assert_eq!(pass, "B*GBQANS%UZPQD!K"); + } + + #[test] + fn test_password_gen_minimum_limits() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + + let options = PasswordGeneratorRequest { + lowercase: true, + uppercase: true, + numbers: true, + special: true, + avoid_ambiguous: false, + length: 24, + min_lowercase: Some(5), + min_uppercase: Some(5), + min_number: Some(5), + min_special: Some(5), + } + .validate_options() + .unwrap(); + + assert_eq!(to_set(&options.lower.0), to_set('a'..='z')); + assert_eq!(to_set(&options.upper.0), to_set('A'..='Z')); + assert_eq!(to_set(&options.number.0), to_set('0'..='9')); + assert_eq!(to_set(&options.special.0), ref_to_set(SPECIAL_CHARS)); + + assert_eq!(options.lower.1, 5); + assert_eq!(options.upper.1, 5); + assert_eq!(options.number.1, 5); + assert_eq!(options.special.1, 5); + + let pass = password_with_rng(&mut rng, options); + assert_eq!(pass, "236q5!a#R%PG5rI%k1!*@uRt"); + } } diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index c4664c7f4..236aef22d 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -213,7 +213,7 @@ async fn process_commands() -> Result<()> { uppercase: args.uppercase, numbers: args.numbers, special: args.special, - length: Some(args.length), + length: args.length, ..Default::default() }) .await?; From f8ba13a9a6a9aedfe6da3dedf40d38bd44b64789 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:44:14 -0500 Subject: [PATCH 095/378] [deps]: Update actions/setup-dotnet action to v4 (#395) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/publish-dotnet.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 1889d5656..7ebb03526 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -30,7 +30,7 @@ jobs: path: languages/csharp/Bitwarden.Sdk - name: Set up .NET Core - uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 with: global-json-file: languages/csharp/global.json diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index c86b90dd1..b52656de2 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -32,7 +32,7 @@ jobs: path: languages/csharp/Bitwarden.Sdk - name: Set up .NET Core - uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0 + uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 with: global-json-file: languages/csharp/global.json From e5a35bc5127d250aa0a7ecdd8e2a99dc2ed4db8a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:47:27 -0500 Subject: [PATCH 096/378] [deps]: Update actions/setup-java action to v4 (#390) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-java.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index d04d15a45..e3abd0430 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -80,7 +80,7 @@ jobs: key: cargo-combine-cache - name: Setup Java - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: distribution: temurin java-version: 17 diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index aa99523a7..653b5337b 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -30,7 +30,7 @@ jobs: path: languages/java/src/main/java/bit/sdk/schema/ - name: Setup Java - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0 # v3.13.0 + uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 # v4.0.0 with: distribution: temurin java-version: 17 From 2e09ae0f9cd8f1621be6b06b1aba68c93d8e73ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:48:54 -0500 Subject: [PATCH 097/378] [deps]: Update actions/checkout action to v4 (#387) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-php.yml | 2 +- .github/workflows/publish-ruby.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index bc1478bc5..e425e26eb 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup PHP with PECL extension uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # 2.26.0 diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index b4e022243..abd472c64 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -20,7 +20,7 @@ jobs: - build_rust steps: - name: Checkout Repository - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby uses: ruby/setup-ruby@54a18e26dbbb1eabc604f317ade9a5788dddef81 # v1.159.0 From f43b6970561b76c8c179cb4f8cf753da10c10f40 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 09:50:10 -0500 Subject: [PATCH 098/378] [deps]: Update gh minor (#381) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-java.yml | 4 ++-- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/publish-php.yml | 2 +- .github/workflows/publish-ruby.yml | 2 +- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/release-napi.yml | 2 +- .github/workflows/version-bump.yml | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 653b5337b..002164647 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout Repository - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download Java schemas artifact uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 @@ -60,7 +60,7 @@ jobs: path: languages/java/src/main/resources/windows-x64 - name: Publish Maven - uses: gradle/gradle-build-action@b5126f31dbc19dd434c3269bf8c28c315e121da2 # v2.8.1 + uses: gradle/gradle-build-action@87a9a15658c426a54dd469d4fc7dc1a73ca9d4a6 # v2.10.0 with: arguments: publish build-root-directory: languages/java diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index b0517ea36..1d69b1190 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -72,7 +72,7 @@ jobs: if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index e425e26eb..b033319ec 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup PHP with PECL extension - uses: shivammathur/setup-php@7fdd3ece872ec7ec4c098ae5ab7637d5e0a96067 # 2.26.0 + uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # 2.28.0 with: php-version: "8.0" tools: composer diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index abd472c64..fa46af292 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@54a18e26dbbb1eabc604f317ade9a5788dddef81 # v1.159.0 + uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0 with: ruby-version: 3.2 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index b5a03ad47..010238f40 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -103,7 +103,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 + uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 9ef782b7f..aad7a0a46 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -128,7 +128,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 + uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 1e7b2e022..3171cfb33 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -126,7 +126,7 @@ jobs: run: npm run tsc - name: Login to Azure - uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 + uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 9fb441fa9..5e403ac5b 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -43,7 +43,7 @@ jobs: run: cargo install cargo-edit - name: Login to Azure - Prod Subscription - uses: Azure/login@4c88f01b0e3a5600e08a37889921afd060f75cf0 # v1.5.0 + uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} From 6ffef566754a3c75e4384fc4e7efe989abbd76eb Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Tue, 5 Dec 2023 10:22:35 -0500 Subject: [PATCH 099/378] SM-1023: Remove Instant from Client in SDK (#397) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Refactor out the `Instant` type in Client and use unix timestamps. This is to support this PR: https://github.com/bitwarden/sdk/pull/388 where we need to serialize token expiry times. It also brings benefits to other areas like WASM, where `Instant` doesn't exist. ## Code changes - **crates/bitwarden/src/auth/renew.rs:** Update the `renew_token` function to use timestamps instead of the `Instant` type - **crates/bitwarden/src/client/client.rs:** Update `Client` to store the unix timestamp for token expiration ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bitwarden/src/auth/renew.rs | 6 +++--- crates/bitwarden/src/client/client.rs | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden/src/auth/renew.rs b/crates/bitwarden/src/auth/renew.rs index 3b2dbef7d..a8bfac51f 100644 --- a/crates/bitwarden/src/auth/renew.rs +++ b/crates/bitwarden/src/auth/renew.rs @@ -1,4 +1,4 @@ -use std::time::{Duration, Instant}; +use chrono::Utc; #[cfg(feature = "internal")] use crate::{auth::api::request::ApiTokenRequest, client::UserLoginMethod}; @@ -9,10 +9,10 @@ use crate::{ }; pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { - const TOKEN_RENEW_MARGIN: Duration = Duration::from_secs(5 * 60); + const TOKEN_RENEW_MARGIN_SECONDS: i64 = 5 * 60; if let (Some(expires), Some(login_method)) = (&client.token_expires_in, &client.login_method) { - if expires > &(Instant::now() + TOKEN_RENEW_MARGIN) { + if Utc::now().timestamp() < expires - TOKEN_RENEW_MARGIN_SECONDS { return Ok(()); } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 5133a5c01..6d1503312 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,4 @@ -use std::time::{Duration, Instant}; - +use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -69,7 +68,7 @@ pub(crate) enum ServiceAccountLoginMethod { pub struct Client { token: Option, pub(crate) refresh_token: Option, - pub(crate) token_expires_in: Option, + pub(crate) token_expires_in: Option, pub(crate) login_method: Option, /// Use Client::get_api_configurations() to access this. @@ -190,7 +189,7 @@ impl Client { ) { self.token = Some(token.clone()); self.refresh_token = refresh_token; - self.token_expires_in = Some(Instant::now() + Duration::from_secs(expires_in)); + self.token_expires_in = Some(Utc::now().timestamp() + expires_in as i64); self.login_method = Some(login_method); self.__api_configurations.identity.oauth_access_token = Some(token.clone()); self.__api_configurations.api.oauth_access_token = Some(token); From 327cbb8f85b0b4f406bdf2ba680f1aa8fda8b6a2 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 5 Dec 2023 16:46:58 +0100 Subject: [PATCH 100/378] Fix regex (#396) --- .github/workflows/delete-old-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index 323a9a0a2..50c3a8fef 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -22,4 +22,4 @@ jobs: min-versions-to-keep: 25 # Ignore versions only containing version numbers - ignore-versions: '^\\d*\\.\\d*\\.\\d*(-SNAPSHOT)?$' + ignore-versions: '^\d*\.\d*\.\d*(-SNAPSHOT)?$' From 7ececc54b7888e0a12f26de93772b460aa97cfd2 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 6 Dec 2023 10:03:48 -0800 Subject: [PATCH 101/378] rename Python package to `bitwarden_sdk` (#399) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [x] Other ## Objective Rename the Python package. This should be merged before #369. ## Code changes - **`languages/python/setup.py`:** Rename package - **`languages/python/bitwarden_sdk`:** Rename directory to match package name - **`.gitignore`:** Changed path to `schemas.py` - **`.github/workflows/generate_schemas.yml`:** Changed path to `schemas.py` ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- .github/workflows/generate_schemas.yml | 2 +- .gitignore | 2 +- .../python/{BitwardenClient => bitwarden_sdk}/__init__.py | 0 .../{BitwardenClient => bitwarden_sdk}/bitwarden_client.py | 0 languages/python/example.py | 4 ++-- languages/python/setup.py | 4 ++-- 6 files changed, 6 insertions(+), 6 deletions(-) rename languages/python/{BitwardenClient => bitwarden_sdk}/__init__.py (100%) rename languages/python/{BitwardenClient => bitwarden_sdk}/bitwarden_client.py (100%) diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 1d69b1190..29798032e 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -54,7 +54,7 @@ jobs: uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: schemas.py - path: ${{ github.workspace }}/languages/python/BitwardenClient/schemas.py + path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact diff --git a/.gitignore b/.gitignore index 18d2d6639..6ddcd3205 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ support/schemas crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts languages/csharp/Bitwarden.Sdk/schemas.cs languages/js_webassembly/bitwarden_client/schemas.ts -languages/python/BitwardenClient/schemas.py +languages/python/bitwarden_sdk/schemas.py languages/cpp/include/schemas.hpp languages/go/schema.go languages/java/src/main/java/com/bitwarden/sdk/schema diff --git a/languages/python/BitwardenClient/__init__.py b/languages/python/bitwarden_sdk/__init__.py similarity index 100% rename from languages/python/BitwardenClient/__init__.py rename to languages/python/bitwarden_sdk/__init__.py diff --git a/languages/python/BitwardenClient/bitwarden_client.py b/languages/python/bitwarden_sdk/bitwarden_client.py similarity index 100% rename from languages/python/BitwardenClient/bitwarden_client.py rename to languages/python/bitwarden_sdk/bitwarden_client.py diff --git a/languages/python/example.py b/languages/python/example.py index 2ee1cb280..b3f2ab006 100644 --- a/languages/python/example.py +++ b/languages/python/example.py @@ -1,8 +1,8 @@ import json import logging import sys -from BitwardenClient.bitwarden_client import BitwardenClient -from BitwardenClient.schemas import client_settings_from_dict, DeviceType +from bitwarden_sdk.bitwarden_client import BitwardenClient +from bitwarden_sdk.schemas import client_settings_from_dict, DeviceType # Create the BitwardenClient, which is used to interact with the SDK client = BitwardenClient(client_settings_from_dict({ diff --git a/languages/python/setup.py b/languages/python/setup.py index 7976ebcba..b243a4fe8 100644 --- a/languages/python/setup.py +++ b/languages/python/setup.py @@ -2,11 +2,11 @@ from setuptools_rust import Binding, RustExtension setup( - name="BitwardenClient", + name="bitwarden_sdk", description="A Bitwarden Client for python", version="0.1", rust_extensions=[RustExtension( "bitwarden_py", path="../../crates/bitwarden-py/Cargo.toml", binding=Binding.PyO3)], - packages=['bitwardenclient'], + packages=['bitwarden_sdk'], zip_safe=False, ) From 030e8424ce75ae0969851b244cde5ea599e932bc Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 6 Dec 2023 13:20:37 -0800 Subject: [PATCH 102/378] Fix broken schema generation (#403) ## Type of change - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Fix broken schema generation workflow from #399. ## Code changes - **./support/scripts/schemas.ts:** Update the Python schemas dir ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- support/scripts/schemas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 602a68bbb..0ca6f023b 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -50,7 +50,7 @@ async function main() { }, }); - writeToFile("./languages/python/BitwardenClient/schemas.py", python.lines); + writeToFile("./languages/python/bitwarden_sdk/schemas.py", python.lines); const ruby = await quicktype({ inputData, From f9f1e5a5681a5bbf9b15584ec3632c258555cf6d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:07:23 +0100 Subject: [PATCH 103/378] [deps]: Update typescript to v5.3.3 (#384) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index a53303523..df8824a29 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -196,9 +196,9 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", From 660211082ef415486c5f78b7ae77ab678cc326d9 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 7 Dec 2023 14:37:28 +0100 Subject: [PATCH 104/378] Mock exports (#404) --- crates/bitwarden/src/tool/exporters/client_exporter.rs | 1 + crates/bitwarden/src/tool/exporters/mod.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden/src/tool/exporters/client_exporter.rs b/crates/bitwarden/src/tool/exporters/client_exporter.rs index f14cbc846..9e0dfd5fc 100644 --- a/crates/bitwarden/src/tool/exporters/client_exporter.rs +++ b/crates/bitwarden/src/tool/exporters/client_exporter.rs @@ -10,6 +10,7 @@ pub struct ClientExporters<'a> { } impl<'a> ClientExporters<'a> { + /// **Draft:** Export the vault as a CSV, JSON, or encrypted JSON file. pub async fn export_vault( &self, folders: Vec, diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 1170dbd38..d03ddeb77 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -20,9 +20,14 @@ pub enum ExportFormat { pub(super) fn export_vault( _folders: Vec, _ciphers: Vec, - _format: ExportFormat, + format: ExportFormat, ) -> Result { - todo!(); + Ok(match format { + ExportFormat::Csv => "Csv".to_owned(), + ExportFormat::Json => "Json".to_owned(), + ExportFormat::AccountEncryptedJson => "AccountEncryptedJson".to_owned(), + ExportFormat::EncryptedJson { .. } => "EncryptedJson".to_owned(), + }) } pub(super) fn export_organization_vault( From 557fb14b9e783eaa3bc2db2d34056fa4979cdc4b Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 7 Dec 2023 15:38:40 +0100 Subject: [PATCH 105/378] [PM-4930] Implement password validation (#401) --- crates/bitwarden-uniffi/src/auth/mod.rs | 20 ++++- crates/bitwarden-uniffi/src/docs.rs | 2 + crates/bitwarden/src/auth/client_auth.rs | 8 +- crates/bitwarden/src/auth/login/mod.rs | 13 +-- crates/bitwarden/src/auth/login/password.rs | 15 ++-- crates/bitwarden/src/auth/login/two_factor.rs | 11 ++- crates/bitwarden/src/auth/mod.rs | 44 ++++++++++ crates/bitwarden/src/auth/password.rs | 65 +++++++++++++++ crates/bitwarden/src/crypto/master_key.rs | 8 +- crates/bitwarden/src/crypto/mod.rs | 4 +- crates/bitwarden/src/mobile/client_kdf.rs | 7 +- crates/bitwarden/src/mobile/kdf.rs | 3 +- languages/kotlin/doc.md | 83 ++++++++++--------- 13 files changed, 215 insertions(+), 68 deletions(-) diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index a5107768e..cbd2b8e90 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use bitwarden::{ auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}, client::kdf::Kdf, + crypto::HashPurpose, }; use crate::{error::Result, Client}; @@ -50,6 +51,7 @@ impl ClientAuth { email: String, password: String, kdf_params: Kdf, + purpose: HashPurpose, ) -> Result { Ok(self .0 @@ -57,7 +59,7 @@ impl ClientAuth { .read() .await .kdf() - .hash_password(email, password, kdf_params) + .hash_password(email, password, kdf_params, purpose) .await?) } @@ -76,4 +78,20 @@ impl ClientAuth { .auth() .make_register_keys(email, password, kdf)?) } + + /// Validate the user password + /// + /// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with + /// `HashPurpose::LocalAuthentication` during login and persist it. If the login method has no + /// password, use the email OTP. + pub async fn validate_password(&self, password: String, password_hash: String) -> Result { + Ok(self + .0 + .0 + .write() + .await + .auth() + .validate_password(password, password_hash.to_string()) + .await?) + } } diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index d66c78002..e7acbdcae 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,6 +1,7 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, client::kdf::Kdf, + crypto::HashPurpose, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, platform::FingerprintRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, @@ -27,6 +28,7 @@ pub enum DocRef { // Crypto InitUserCryptoRequest(InitUserCryptoRequest), InitOrgCryptoRequest(InitOrgCryptoRequest), + HashPurpose(HashPurpose), // Generators PasswordGeneratorRequest(PasswordGeneratorRequest), diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index aa1615c3b..3c096835a 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -9,7 +9,9 @@ use crate::{ ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, }, - password::{password_strength, satisfies_policy, MasterPasswordPolicyOptions}, + password::{ + password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, + }, register::{make_register_keys, register}, RegisterKeyResponse, RegisterRequest, }, @@ -90,6 +92,10 @@ impl<'a> ClientAuth<'a> { pub async fn send_two_factor_email(&mut self, tf: &TwoFactorEmailRequest) -> Result<()> { send_two_factor_email(self.client, tf).await } + + pub async fn validate_password(&self, password: String, password_hash: String) -> Result { + validate_password(self.client, password, password_hash).await + } } impl<'a> Client { diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 4ec9d1b49..d2f66b569 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -1,9 +1,6 @@ #[cfg(feature = "internal")] use { - crate::{ - client::{kdf::Kdf, Client}, - error::Result, - }, + crate::{client::Client, error::Result}, bitwarden_api_identity::{ apis::accounts_api::accounts_prelogin_post, models::{PreloginRequestModel, PreloginResponseModel}, @@ -39,14 +36,6 @@ pub(super) use access_token::login_access_token; #[cfg(feature = "secrets")] pub use access_token::{AccessTokenLoginRequest, AccessTokenLoginResponse}; -#[cfg(feature = "internal")] -async fn determine_password_hash(email: &str, kdf: &Kdf, password: &str) -> Result { - use crate::crypto::{HashPurpose, MasterKey}; - - let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; - master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization) -} - #[cfg(feature = "internal")] pub(crate) async fn request_prelogin( client: &mut Client, diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index a320131ea..08d7d2054 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -5,10 +5,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "internal")] use crate::{ - auth::{ - api::request::PasswordTokenRequest, - login::{determine_password_hash, TwoFactorRequest}, - }, + auth::{api::request::PasswordTokenRequest, login::TwoFactorRequest}, client::{kdf::Kdf, LoginMethod}, crypto::EncString, Client, @@ -26,12 +23,18 @@ pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { - use crate::client::UserLoginMethod; + use crate::{auth::determine_password_hash, client::UserLoginMethod, crypto::HashPurpose}; info!("password logging in"); debug!("{:#?}, {:#?}", client, input); - let password_hash = determine_password_hash(&input.email, &input.kdf, &input.password).await?; + let password_hash = determine_password_hash( + &input.email, + &input.kdf, + &input.password, + HashPurpose::ServerAuthorization, + ) + .await?; let response = request_identity_tokens(client, input, &password_hash).await?; if let IdentityTokenResponse::Authenticated(r) = &response { diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index d8ede2473..cf3cb7907 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -3,8 +3,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use super::determine_password_hash; -use crate::{error::Result, Client}; +use crate::{auth::determine_password_hash, crypto::HashPurpose, error::Result, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -22,7 +21,13 @@ pub(crate) async fn send_two_factor_email( // TODO: This should be resolved from the client let kdf = client.auth().prelogin(input.email.clone()).await?; - let password_hash = determine_password_hash(&input.email, &kdf, &input.password).await?; + let password_hash = determine_password_hash( + &input.email, + &kdf, + &input.password, + HashPurpose::ServerAuthorization, + ) + .await?; let config = client.get_api_configurations().await; bitwarden_api_api::apis::two_factor_api::two_factor_send_email_login_post( diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 023f3270b..49be82d1c 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -11,3 +11,47 @@ pub use jwt_token::JWTToken; mod register; #[cfg(feature = "internal")] pub use register::{RegisterKeyResponse, RegisterRequest}; + +#[cfg(feature = "internal")] +use crate::{ + client::kdf::Kdf, + crypto::{HashPurpose, MasterKey}, + error::Result, +}; + +#[cfg(feature = "internal")] +async fn determine_password_hash( + email: &str, + kdf: &Kdf, + password: &str, + purpose: HashPurpose, +) -> Result { + let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; + master_key.derive_master_key_hash(password.as_bytes(), purpose) +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroU32; + + use super::*; + + #[cfg(feature = "internal")] + #[tokio::test] + async fn test_determine_password_hash() { + use super::determine_password_hash; + + let password = "password123"; + let email = "test@bitwarden.com"; + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(100_000).unwrap(), + }; + let purpose = HashPurpose::LocalAuthorization; + + let result = determine_password_hash(email, &kdf, password, purpose) + .await + .unwrap(); + + assert_eq!(result, "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU="); + } +} diff --git a/crates/bitwarden/src/auth/password.rs b/crates/bitwarden/src/auth/password.rs index a38c75ab6..eec68861a 100644 --- a/crates/bitwarden/src/auth/password.rs +++ b/crates/bitwarden/src/auth/password.rs @@ -1,5 +1,13 @@ use schemars::JsonSchema; +use super::determine_password_hash; +use crate::{ + client::{LoginMethod, UserLoginMethod}, + crypto::HashPurpose, + error::{Error, Result}, + Client, +}; + pub(super) fn password_strength( _password: String, _email: String, @@ -16,6 +24,33 @@ pub(super) fn satisfies_policy( true } +/// Validate if the provided password matches the password hash stored in the client. +pub(super) async fn validate_password( + client: &Client, + password: String, + password_hash: String, +) -> Result { + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + if let LoginMethod::User(login_method) = login_method { + match login_method { + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. } => { + let hash = + determine_password_hash(email, kdf, &password, HashPurpose::LocalAuthorization) + .await?; + + Ok(hash == password_hash) + } + } + } else { + Err(Error::NotAuthenticated) + } +} + #[derive(Debug, JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] #[allow(dead_code)] @@ -32,3 +67,33 @@ pub struct MasterPasswordPolicyOptions { /// the user will be forced to update their password. enforce_on_login: bool, } + +#[cfg(test)] + +mod tests { + + #[cfg(feature = "mobile")] + #[tokio::test] + async fn test_validate_password() { + use std::num::NonZeroU32; + + use super::validate_password; + use crate::client::{kdf::Kdf, Client, LoginMethod, UserLoginMethod}; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + email: "test@bitwarden.com".to_string(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(100_000).unwrap(), + }, + client_id: "1".to_string(), + })); + + let password = "password123".to_string(); + let password_hash = "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU=".to_string(); + + let result = validate_password(&client, password, password_hash).await; + + assert!(result.unwrap()); + } +} diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index fdcf93dde..88e5b9327 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -1,6 +1,7 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; use rand::Rng; +use schemars::JsonSchema; use sha2::Digest; use super::{ @@ -9,10 +10,11 @@ use super::{ }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; -#[derive(Copy, Clone)] -pub(crate) enum HashPurpose { +#[derive(Copy, Clone, JsonSchema)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum HashPurpose { ServerAuthorization = 1, - // LocalAuthorization = 2, + LocalAuthorization = 2, } /// A Master Key. diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index b030a5107..fc79ad8f5 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -42,7 +42,9 @@ pub(crate) use shareable_key::derive_shareable_key; #[cfg(feature = "internal")] mod master_key; #[cfg(feature = "internal")] -pub(crate) use master_key::{HashPurpose, MasterKey}; +pub use master_key::HashPurpose; +#[cfg(feature = "internal")] +pub(crate) use master_key::MasterKey; #[cfg(feature = "internal")] mod user_key; #[cfg(feature = "internal")] diff --git a/crates/bitwarden/src/mobile/client_kdf.rs b/crates/bitwarden/src/mobile/client_kdf.rs index 320a03571..6b895f78a 100644 --- a/crates/bitwarden/src/mobile/client_kdf.rs +++ b/crates/bitwarden/src/mobile/client_kdf.rs @@ -1,4 +1,6 @@ -use crate::{client::kdf::Kdf, error::Result, mobile::kdf::hash_password, Client}; +use crate::{ + client::kdf::Kdf, crypto::HashPurpose, error::Result, mobile::kdf::hash_password, Client, +}; pub struct ClientKdf<'a> { pub(crate) client: &'a crate::Client, @@ -10,8 +12,9 @@ impl<'a> ClientKdf<'a> { email: String, password: String, kdf_params: Kdf, + purpose: HashPurpose, ) -> Result { - hash_password(self.client, email, password, kdf_params).await + hash_password(self.client, email, password, kdf_params, purpose).await } } diff --git a/crates/bitwarden/src/mobile/kdf.rs b/crates/bitwarden/src/mobile/kdf.rs index a34b339bb..de2fcc79f 100644 --- a/crates/bitwarden/src/mobile/kdf.rs +++ b/crates/bitwarden/src/mobile/kdf.rs @@ -10,8 +10,9 @@ pub async fn hash_password( email: String, password: String, kdf_params: Kdf, + purpose: HashPurpose, ) -> Result { let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf_params)?; - master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization) + master_key.derive_master_key_hash(password.as_bytes(), purpose) } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index a84397719..f9f47db64 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -105,6 +105,7 @@ Hash the user password - email: String - password: String - kdf_params: [Kdf](#kdf) +- purpose: [HashPurpose](#hashpurpose) **Output**: std::result::Result @@ -121,6 +122,22 @@ Generate keys needed for registration process **Output**: std::result::Result +### `validate_password` + +Validate the user password + +To retrieve the user's password hash, use [`ClientAuth::hash_password`] with +`HashPurpose::LocalAuthentication` during login and persist it. If the login method has no +password, use the email OTP. + +**Arguments**: + +- self: +- password: String +- password_hash: String + +**Output**: std::result::Result<,BitwardenError> + ## ClientCiphers ### `encrypt` @@ -493,7 +510,7 @@ The key can be either: - key: String - time: Option -**Output**: [TotpResponse](#totpresponse) +**Output**: std::result::Result # References @@ -901,6 +918,16 @@ implementations. +## `HashPurpose` + + + + + + + +
KeyTypeDescription
+ ## `InitOrgCryptoRequest` @@ -1126,7 +1153,7 @@ implementations. - + @@ -1151,52 +1178,52 @@ implementations. - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + +
wordSeparator stringCharacter separator between words in the generated passphrase. If the value is set, it cannot be empty.Character separator between words in the generated passphrase. The value cannot be empty.
capitalize
lowercase booleanInclude lowercase characters (a-z).
uppercase booleanInclude uppercase characters (A-Z).
numbers booleanInclude numbers (0-9).
special booleanInclude special characters: ! @ # $ % ^ & *
lengthinteger,nullintegerThe length of the generated password. Note that the password length must be greater than the sum of all the minimums.
avoidAmbiguousboolean,nullbooleanWhen set to true, the generated password will not contain ambiguous characters. The ambiguous characters are: I, O, l, 0, 1
minLowercaseboolean,nullinteger,nullThe minimum number of lowercase characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is lowercase is false
minUppercaseboolean,nullinteger,nullThe minimum number of uppercase characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is uppercase is false
minNumberboolean,nullinteger,nullThe minimum number of numbers in the generated password. When set, the value must be between 1 and 9. This value is ignored is numbers is false
minSpecialboolean,nullinteger,nullThe minimum number of special characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is special is false
@@ -1399,23 +1426,3 @@ implementations. - -## `TotpResponse` - - - - - - - - - - - - - - - - - -
KeyTypeDescription
codestringGenerated TOTP code
periodintegerTime period
From a4bf99b3ab50fbb02758b24a01229854d7633667 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 7 Dec 2023 17:54:44 +0100 Subject: [PATCH 106/378] Rename service_account_id to access_token_id (#405) --- .../src/auth/api/request/access_token_request.rs | 4 ++-- crates/bitwarden/src/auth/login/access_token.rs | 4 ++-- crates/bitwarden/src/auth/renew.rs | 4 ++-- crates/bitwarden/src/client/access_token.rs | 10 +++++----- crates/bitwarden/src/client/client.rs | 2 +- crates/bws/src/main.rs | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/bitwarden/src/auth/api/request/access_token_request.rs b/crates/bitwarden/src/auth/api/request/access_token_request.rs index b5035269b..9f41d6b40 100644 --- a/crates/bitwarden/src/auth/api/request/access_token_request.rs +++ b/crates/bitwarden/src/auth/api/request/access_token_request.rs @@ -13,10 +13,10 @@ pub struct AccessTokenRequest { } impl AccessTokenRequest { - pub fn new(service_account_id: Uuid, client_secret: &String) -> Self { + pub fn new(access_token_id: Uuid, client_secret: &String) -> Self { let obj = Self { scope: "api.secrets".to_string(), - client_id: service_account_id.to_string(), + client_id: access_token_id.to_string(), client_secret: client_secret.to_string(), grant_type: "client_credentials".to_string(), }; diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 1ec8c8b34..8d5996119 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -59,7 +59,7 @@ pub(crate) async fn login_access_token( r.refresh_token.clone(), r.expires_in, LoginMethod::ServiceAccount(ServiceAccountLoginMethod::AccessToken { - service_account_id: access_token.service_account_id, + access_token_id: access_token.access_token_id, client_secret: access_token.client_secret, organization_id, }), @@ -76,7 +76,7 @@ async fn request_access_token( input: &AccessToken, ) -> Result { let config = client.get_api_configurations().await; - AccessTokenRequest::new(input.service_account_id, &input.client_secret) + AccessTokenRequest::new(input.access_token_id, &input.client_secret) .send(config) .await } diff --git a/crates/bitwarden/src/auth/renew.rs b/crates/bitwarden/src/auth/renew.rs index a8bfac51f..7973947ab 100644 --- a/crates/bitwarden/src/auth/renew.rs +++ b/crates/bitwarden/src/auth/renew.rs @@ -44,11 +44,11 @@ pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { }, LoginMethod::ServiceAccount(s) => match s { ServiceAccountLoginMethod::AccessToken { - service_account_id, + access_token_id, client_secret, .. } => { - AccessTokenRequest::new(*service_account_id, client_secret) + AccessTokenRequest::new(*access_token_id, client_secret) .send(&client.__api_configurations) .await? } diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index b68d78572..db6b78f20 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -10,7 +10,7 @@ use crate::{ }; pub struct AccessToken { - pub service_account_id: Uuid, + pub access_token_id: Uuid, pub client_secret: String, pub encryption_key: SymmetricCryptoKey, } @@ -22,7 +22,7 @@ impl FromStr for AccessToken { let (first_part, encryption_key) = key.split_once(':').ok_or(AccessTokenInvalidError::NoKey)?; - let [version, service_account_id, client_secret]: [&str; 3] = first_part + let [version, access_token_id, client_secret]: [&str; 3] = first_part .split('.') .collect::>() .try_into() @@ -32,7 +32,7 @@ impl FromStr for AccessToken { return Err(AccessTokenInvalidError::WrongVersion.into()); } - let Ok(service_account_id) = service_account_id.parse() else { + let Ok(access_token_id) = access_token_id.parse() else { return Err(AccessTokenInvalidError::InvalidUuid.into()); }; @@ -49,7 +49,7 @@ impl FromStr for AccessToken { derive_shareable_key(encryption_key, "accesstoken", Some("sm-access-token")); Ok(AccessToken { - service_account_id, + access_token_id, client_secret: client_secret.to_owned(), encryption_key, }) @@ -69,7 +69,7 @@ mod tests { let token = AccessToken::from_str(access_token).unwrap(); assert_eq!( - &token.service_account_id.to_string(), + &token.access_token_id.to_string(), "ec2c1d46-6a4b-4751-a310-af9601317f2d" ); assert_eq!(token.client_secret, "C2IgxjjLF7qSshsbwe8JGcbM075YXw"); diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 6d1503312..2b6b76a2f 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -58,7 +58,7 @@ pub(crate) enum UserLoginMethod { #[derive(Debug, Clone)] pub(crate) enum ServiceAccountLoginMethod { AccessToken { - service_account_id: Uuid, + access_token_id: Uuid, client_secret: String, organization_id: Uuid, }, diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 6f27a0e4d..22e3b5dcd 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -272,7 +272,7 @@ async fn process_commands() -> Result<()> { profile } else if let Some(access_token) = cli.access_token { AccessToken::from_str(&access_token)? - .service_account_id + .access_token_id .to_string() } else { String::from("default") @@ -619,7 +619,7 @@ fn get_config_profile( profile.to_owned() } else { AccessToken::from_str(access_token)? - .service_account_id + .access_token_id .to_string() }; From 5cf658daf4057da469f4035bc5dd5269270e2a7d Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 7 Dec 2023 17:54:58 +0100 Subject: [PATCH 107/378] Parse exp from JWT (#406) --- crates/bitwarden/src/auth/jwt_token.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs index 14cbaf84f..9097b84f2 100644 --- a/crates/bitwarden/src/auth/jwt_token.rs +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -13,6 +13,7 @@ use crate::{error::Result, util::BASE64_ENGINE}; /// TODO: We need to expand this to support user based JWT tokens. #[derive(serde::Deserialize)] pub struct JWTToken { + pub exp: u64, pub sub: String, pub email: Option, pub organization: Option, @@ -62,6 +63,7 @@ mod tests { f3LEddAPV8cAFza4DjA8pZJLFrMyRvMXcL_PjKF8qPVzqVWh03lfJ4clOIxR2gOuWIc902Y5E"; let token: JWTToken = jwt.parse().unwrap(); + assert_eq!(token.exp, 1675107177); assert_eq!(token.sub, "e25d37f3-b603-40de-84ba-af96012f5a42"); assert_eq!(token.email.as_deref(), Some("test@bitwarden.com")); assert_eq!(token.organization.as_deref(), None); From e6977ae187f0cfe90c5be4cc6a79a2375be2b1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 8 Dec 2023 13:37:06 +0100 Subject: [PATCH 108/378] Add missing hashPurpose to mobile demo apps (#407) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Noticed the mobile demo apps weren't updated with the new hashPurpose parameter, also ran formatting over the files --- .../com/bitwarden/myapplication/MainActivity.kt | 10 ++++++---- languages/swift/iOS/App/ContentView.swift | 14 +++++++------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index 3c03c6bca..b41b12b8c 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp import androidx.fragment.app.FragmentActivity import com.bitwarden.core.DateTime import com.bitwarden.core.Folder +import com.bitwarden.core.HashPurpose import com.bitwarden.core.InitOrgCryptoRequest import com.bitwarden.core.InitUserCryptoMethod import com.bitwarden.core.InitUserCryptoRequest @@ -58,9 +59,9 @@ import javax.net.ssl.X509TrustManager /** * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. - * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't - * handle a lot of errors and edge cases that a production application would need to deal with. - * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. */ @@ -181,7 +182,8 @@ class MainActivity : FragmentActivity() { prelogin_body.kdfParallelism!! ) } - val masterPasswordHash = client.auth().hashPassword(EMAIL, PASSWORD, kdf) + val masterPasswordHash = + client.auth().hashPassword(EMAIL, PASSWORD, kdf, HashPurpose.SERVER_AUTHORIZATION) ///////////////////////////// Login ///////////////////////////// diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index 5df7dc3fd..c2b488b8f 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -10,9 +10,9 @@ import SwiftUI /** * IMPORTANT: This file is provided only for the purpose of demostrating the use of the SDK functionality. - * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't - * handle a lot of errors and edge cases that a production application would need to deal with. - * Developers are encouraged to review and improve the code as needed to meet their security requirements. + * It hasn't gone through a throrough security review and should not be considered production ready. It also doesn't + * handle a lot of errors and edge cases that a production application would need to deal with. + * Developers are encouraged to review and improve the code as needed to meet their security requirements. * Additionally, we recommend to consult with security experts and conduct thorough testing before using the code in production. */ @@ -49,8 +49,8 @@ struct ContentView: View { Button(action: { Task { do { - try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics) - try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) } catch { print("ERROR:", error) } @@ -64,7 +64,7 @@ struct ContentView: View { Button(action: { Task { do { - try await clientExampleBiometrics(clientCrypto: client.crypto()) + try await clientExampleBiometrics(clientCrypto: client.crypto()) try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) } catch { print("ERROR:", error) @@ -117,7 +117,7 @@ struct ContentView: View { } let passwordHash = try await clientAuth.hashPassword( - email: EMAIL, password: PASSWORD, kdfParams: kdf) + email: EMAIL, password: PASSWORD, kdfParams: kdf, purpose: .serverAuthorization) ///////////////////////////// Login ///////////////////////////// From 94710e002713c5baf0fc890a9d974d02ef12ec05 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:07:24 +0100 Subject: [PATCH 109/378] [deps]: Update prettier to v3.1.1 (#418) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb67d4e04..faafd1f1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.1.0", + "prettier": "3.1.1", "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", @@ -1470,9 +1470,9 @@ } }, "node_modules/prettier": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.0.tgz", - "integrity": "sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index 363d8b34c..0332edade 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.1.0", + "prettier": "3.1.1", "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.1", From 34422641d04d168a1600c65ccc319e037cee3720 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:07:52 +0100 Subject: [PATCH 110/378] [deps]: Update Rust crate tokio to 1.35.0 (#416) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden-py/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a67b163f..1e351679e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3256,9 +3256,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 94e9e6a43..3a7c5ca58 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -18,7 +18,7 @@ bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3-build-config = { version = "0.20.0" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] -tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index a9e432c27..01d6a0c11 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -61,5 +61,5 @@ uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" -tokio = { version = "1.34.0", features = ["rt", "macros"] } +tokio = { version = "1.35.0", features = ["rt", "macros"] } wiremock = "0.5.22" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 706628f53..5f05fcfa3 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" log = "0.4.20" -tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ "internal", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index cef520b1a..300830e64 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -36,7 +36,7 @@ serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.50" -tokio = { version = "1.34.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.6.1", features = ["serde"] } From 0a31e05d8d0d7d4832b96f51fe9b3d41fcbc62f6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:20:38 +0100 Subject: [PATCH 111/378] [deps]: Update Rust crate clap to 4.4.11 (#410) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e351679e..7c3426929 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -658,9 +658,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.10" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 86ca2fac1..2591035c2 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.10", features = ["derive"] } +clap = { version = "4.4.11", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 5f05fcfa3..53712100e 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.10", features = ["derive", "env"] } +clap = { version = "4.4.11", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 300830e64..ba59ece0e 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.10", features = ["derive", "env", "string"] } +clap = { version = "4.4.11", features = ["derive", "env", "string"] } clap_complete = "4.4.4" color-eyre = "0.6" comfy-table = "^7.1.0" From e1bf48b26afb82be56422988c3465826ecfa92c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 11 Dec 2023 11:22:38 +0100 Subject: [PATCH 112/378] Use tokio executor for uniffi async (#408) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective When testing the username generator using uniffi, I noticed that uniffi was using it's own async executor by default, while reqwest was expecting tokio, which caused errors. I've changed all uniffi exported async functions to use tokio by default, to avoid these issues. --- Cargo.lock | 14 ++++++++++++++ crates/bitwarden-uniffi/src/auth/mod.rs | 2 +- crates/bitwarden-uniffi/src/crypto.rs | 2 +- crates/bitwarden-uniffi/src/platform/mod.rs | 2 +- crates/bitwarden-uniffi/src/tool/mod.rs | 4 ++-- crates/bitwarden-uniffi/src/vault/ciphers.rs | 2 +- crates/bitwarden-uniffi/src/vault/collections.rs | 2 +- crates/bitwarden-uniffi/src/vault/folders.rs | 2 +- crates/bitwarden-uniffi/src/vault/mod.rs | 2 +- .../bitwarden-uniffi/src/vault/password_history.rs | 2 +- crates/bitwarden-uniffi/src/vault/sends.rs | 2 +- crates/bitwarden/Cargo.toml | 2 +- 12 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c3426929..e7ba84c53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,6 +201,19 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-compat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f68a707c1feb095d8c07f8a65b9f506b117d30af431cab89374357de7c11461b" +dependencies = [ + "futures-core", + "futures-io", + "once_cell", + "pin-project-lite", + "tokio", +] + [[package]] name = "async-lock" version = "3.2.0" @@ -3556,6 +3569,7 @@ version = "0.25.2" source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "anyhow", + "async-compat", "bytes", "camino", "log", diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index cbd2b8e90..ded3f776a 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -11,7 +11,7 @@ use crate::{error::Result, Client}; #[derive(uniffi::Object)] pub struct ClientAuth(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientAuth { /// **API Draft:** Calculate Password Strength pub async fn password_strength( diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 804202e2f..995750b7f 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -7,7 +7,7 @@ use crate::{error::Result, Client}; #[derive(uniffi::Object)] pub struct ClientCrypto(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientCrypto { /// Initialization method for the user crypto. Needs to be called before any other crypto operations. pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { diff --git a/crates/bitwarden-uniffi/src/platform/mod.rs b/crates/bitwarden-uniffi/src/platform/mod.rs index f4eaaa095..f03ed01e5 100644 --- a/crates/bitwarden-uniffi/src/platform/mod.rs +++ b/crates/bitwarden-uniffi/src/platform/mod.rs @@ -7,7 +7,7 @@ use crate::{error::Result, Client}; #[derive(uniffi::Object)] pub struct ClientPlatform(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientPlatform { /// Fingerprint pub async fn fingerprint(&self, req: FingerprintRequest) -> Result { diff --git a/crates/bitwarden-uniffi/src/tool/mod.rs b/crates/bitwarden-uniffi/src/tool/mod.rs index 3243cceb6..6622a1b2d 100644 --- a/crates/bitwarden-uniffi/src/tool/mod.rs +++ b/crates/bitwarden-uniffi/src/tool/mod.rs @@ -10,7 +10,7 @@ use crate::{error::Result, Client}; #[derive(uniffi::Object)] pub struct ClientGenerators(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientGenerators { /// **API Draft:** Generate Password pub async fn password(&self, settings: PasswordGeneratorRequest) -> Result { @@ -40,7 +40,7 @@ impl ClientGenerators { #[derive(uniffi::Object)] pub struct ClientExporters(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientExporters { /// **API Draft:** Export user vault pub async fn export_vault( diff --git a/crates/bitwarden-uniffi/src/vault/ciphers.rs b/crates/bitwarden-uniffi/src/vault/ciphers.rs index 3122fe2c1..eb8543947 100644 --- a/crates/bitwarden-uniffi/src/vault/ciphers.rs +++ b/crates/bitwarden-uniffi/src/vault/ciphers.rs @@ -7,7 +7,7 @@ use crate::{Client, Result}; #[derive(uniffi::Object)] pub struct ClientCiphers(pub Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientCiphers { /// Encrypt cipher pub async fn encrypt(&self, cipher_view: CipherView) -> Result { diff --git a/crates/bitwarden-uniffi/src/vault/collections.rs b/crates/bitwarden-uniffi/src/vault/collections.rs index 0a1ab8976..53a7500ec 100644 --- a/crates/bitwarden-uniffi/src/vault/collections.rs +++ b/crates/bitwarden-uniffi/src/vault/collections.rs @@ -7,7 +7,7 @@ use crate::{Client, Result}; #[derive(uniffi::Object)] pub struct ClientCollections(pub Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientCollections { /// Decrypt collection pub async fn decrypt(&self, collection: Collection) -> Result { diff --git a/crates/bitwarden-uniffi/src/vault/folders.rs b/crates/bitwarden-uniffi/src/vault/folders.rs index d9f955b97..7cbbdc0ae 100644 --- a/crates/bitwarden-uniffi/src/vault/folders.rs +++ b/crates/bitwarden-uniffi/src/vault/folders.rs @@ -7,7 +7,7 @@ use crate::{Client, Result}; #[derive(uniffi::Object)] pub struct ClientFolders(pub Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientFolders { /// Encrypt folder pub async fn encrypt(&self, folder: FolderView) -> Result { diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index bd5f5332c..435e7f355 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -14,7 +14,7 @@ pub mod sends; #[derive(uniffi::Object)] pub struct ClientVault(pub(crate) Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientVault { /// Folder operations pub fn folders(self: Arc) -> Arc { diff --git a/crates/bitwarden-uniffi/src/vault/password_history.rs b/crates/bitwarden-uniffi/src/vault/password_history.rs index 9042aa8ad..470e28822 100644 --- a/crates/bitwarden-uniffi/src/vault/password_history.rs +++ b/crates/bitwarden-uniffi/src/vault/password_history.rs @@ -7,7 +7,7 @@ use crate::{Client, Result}; #[derive(uniffi::Object)] pub struct ClientPasswordHistory(pub Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientPasswordHistory { /// Encrypt password history pub async fn encrypt(&self, password_history: PasswordHistoryView) -> Result { diff --git a/crates/bitwarden-uniffi/src/vault/sends.rs b/crates/bitwarden-uniffi/src/vault/sends.rs index 6e2f1b879..e306168b8 100644 --- a/crates/bitwarden-uniffi/src/vault/sends.rs +++ b/crates/bitwarden-uniffi/src/vault/sends.rs @@ -7,7 +7,7 @@ use crate::{Client, Result}; #[derive(uniffi::Object)] pub struct ClientSends(pub Arc); -#[uniffi::export] +#[uniffi::export(async_runtime = "tokio")] impl ClientSends { /// Encrypt send pub async fn encrypt(&self, send: SendView) -> Result { diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 01d6a0c11..4d92e4270 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -56,7 +56,7 @@ sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" -uniffi = { version = "=0.25.2", optional = true } +uniffi = { version = "=0.25.2", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] From ebe2acb36b7aa8c4c558721ca546e1b202a57a2e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:41:46 +0100 Subject: [PATCH 113/378] [deps]: Update @napi-rs/cli to v2.17.0 (#415) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index df8824a29..00e591aaf 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -55,9 +55,9 @@ } }, "node_modules/@napi-rs/cli": { - "version": "2.16.5", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.16.5.tgz", - "integrity": "sha512-mFEzwrg4IOLngGd2/P6yeqIWgwQNn59Z08n1rndu6kLDq1gg954NH9cM1O9Da0RJuybt46p43lqgSsnAY2mxqA==", + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.17.0.tgz", + "integrity": "sha512-/M7MZ3dIqyFs6c0Bxtk+SOobPq6vYWYqBLYCOKx3dYWqoyJNBEgmDKUTrxIZu9eHw9Ill3WyEoHPqS9P99cd8A==", "dev": true, "bin": { "napi": "scripts/index.js" From 784c0ef7ad838cb28b7d2b4f03dbbb54c0c6914c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:11:44 -0500 Subject: [PATCH 114/378] [deps]: Update actions/setup-go action to v5 (#417) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/golang-release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/golang-release.yml b/.github/workflows/golang-release.yml index 6f41bcd3e..f42d428f9 100644 --- a/.github/workflows/golang-release.yml +++ b/.github/workflows/golang-release.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go environment - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ${{ env.GO_VERSION }} @@ -56,7 +56,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Go environment - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: ${{ env.GO_VERSION }} From 18036ea12d5fbb900b776265ae01cc06a57cde35 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:12:07 -0500 Subject: [PATCH 115/378] [deps]: Update dtolnay/rust-toolchain digest to be73d79 (#409) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 4 ++-- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-rust-crates.yml | 4 ++-- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/rust-test.yml | 4 ++-- .github/workflows/version-bump.yml | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index e3abd0430..22eda7f88 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 @@ -70,7 +70,7 @@ jobs: fetch-depth: 0 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 9aa39ab51..4239a9a0a 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -63,7 +63,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -158,7 +158,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 16f87a177..d5bd935e9 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -61,7 +61,7 @@ jobs: cache-dependency-path: crates/bitwarden-napi/package-lock.json - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 203276556..7504887f0 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -37,7 +37,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -67,7 +67,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 7cfa9b078..39039359f 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index b2085892a..f164a2433 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: nightly targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 29798032e..efd7dd68d 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cb1fb2b67..04b28ed25 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 010238f40..aef94b37e 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -115,7 +115,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index aad7a0a46..04863f34e 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -140,7 +140,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index d4177bea1..2ea0ad5eb 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable @@ -59,7 +59,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 5e403ac5b..9881b9b0e 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable From e270190d5a1727b640cf763b6bc2df1aab416082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 11 Dec 2023 21:19:11 +0100 Subject: [PATCH 116/378] Run clippy linting on tests too (#420) --- .github/workflows/lint.yml | 2 +- .../api/response/identity_payload_response.rs | 19 +------------------ .../api/response/identity_refresh_response.rs | 18 +----------------- .../api/response/identity_token_response.rs | 2 +- crates/bitwarden/src/vault/send.rs | 2 +- 5 files changed, 5 insertions(+), 38 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 04b28ed25..d6e57740e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -49,6 +49,6 @@ jobs: RUSTDOCFLAGS: "-D warnings" - name: Cargo clippy - run: cargo clippy --all-features + run: cargo clippy --all-features --tests env: RUSTFLAGS: "-D warnings" diff --git a/crates/bitwarden/src/auth/api/response/identity_payload_response.rs b/crates/bitwarden/src/auth/api/response/identity_payload_response.rs index b35b398d7..47543510b 100644 --- a/crates/bitwarden/src/auth/api/response/identity_payload_response.rs +++ b/crates/bitwarden/src/auth/api/response/identity_payload_response.rs @@ -1,6 +1,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq)] +#[cfg_attr(test, derive(Default))] pub struct IdentityTokenPayloadResponse { pub access_token: String, pub expires_in: u64, @@ -10,21 +11,3 @@ pub struct IdentityTokenPayloadResponse { pub(crate) encrypted_payload: String, } - -#[cfg(test)] -mod test { - use super::*; - - impl Default for IdentityTokenPayloadResponse { - fn default() -> Self { - Self { - access_token: Default::default(), - expires_in: Default::default(), - refresh_token: Default::default(), - token_type: Default::default(), - scope: Default::default(), - encrypted_payload: Default::default(), - } - } - } -} diff --git a/crates/bitwarden/src/auth/api/response/identity_refresh_response.rs b/crates/bitwarden/src/auth/api/response/identity_refresh_response.rs index eaf5c142f..c5733bd36 100644 --- a/crates/bitwarden/src/auth/api/response/identity_refresh_response.rs +++ b/crates/bitwarden/src/auth/api/response/identity_refresh_response.rs @@ -1,6 +1,7 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, PartialEq)] +#[cfg_attr(test, derive(Default))] pub struct IdentityTokenRefreshResponse { pub access_token: String, pub expires_in: u64, @@ -8,20 +9,3 @@ pub struct IdentityTokenRefreshResponse { token_type: String, scope: String, } - -#[cfg(test)] -mod test { - use super::*; - - impl Default for IdentityTokenRefreshResponse { - fn default() -> Self { - Self { - access_token: Default::default(), - expires_in: Default::default(), - refresh_token: Default::default(), - token_type: Default::default(), - scope: Default::default(), - } - } - } -} diff --git a/crates/bitwarden/src/auth/api/response/identity_token_response.rs b/crates/bitwarden/src/auth/api/response/identity_token_response.rs index ae6cc81e5..b22263bc5 100644 --- a/crates/bitwarden/src/auth/api/response/identity_token_response.rs +++ b/crates/bitwarden/src/auth/api/response/identity_token_response.rs @@ -57,7 +57,7 @@ mod test { #[test] fn two_factor() { - let expected = Box::new(IdentityTwoFactorResponse::default()); + let expected = Box::::default(); let two_factor = serde_json::to_string(&expected).unwrap(); let expected = IdentityTokenResponse::TwoFactorRequired(expected); let actual = parse_identity_response(StatusCode::BAD_REQUEST, two_factor).unwrap(); diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 5c463a0cf..3aec03639 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -280,7 +280,7 @@ mod tests { iterations: 345123.try_into().unwrap(), }, }, - "asdfasdfasdf".into(), + "asdfasdfasdf", "2.majkL1/hNz9yptLqNAUSnw==|RiOzMTTJMG948qu8O3Zm1EQUO2E8BuTwFKnO9LWQjMzxMWJM5GbyOq2/A+tumPbTERt4JWur/FKfgHb+gXuYiEYlXPMuVBvT7nv4LPytJuM=|IVqMxHJeR1ZXY0sGngTC0x+WqbG8p6V+BTrdgBbQXjM=".parse().unwrap(), "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw=".parse().unwrap(), ).unwrap(); From d4571858fcf840cf081186773cc0c6f5f8c56f44 Mon Sep 17 00:00:00 2001 From: Leandro Carneiro <42899277+carnei-ro@users.noreply.github.com> Date: Tue, 12 Dec 2023 08:10:08 -0300 Subject: [PATCH 117/378] Disable bitwarden-c from printing command input (#422) --- crates/bitwarden-c/src/c.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bitwarden-c/src/c.rs b/crates/bitwarden-c/src/c.rs index 99180367b..f9ac57f30 100644 --- a/crates/bitwarden-c/src/c.rs +++ b/crates/bitwarden-c/src/c.rs @@ -12,7 +12,6 @@ pub async extern "C" fn run_command( ) -> *mut c_char { let client = unsafe { ffi_ref!(client_ptr) }; let input_str = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr).to_bytes() }).unwrap(); - println!("{}", input_str); let result = client.run_command(input_str).await; match std::ffi::CString::new(result) { From afb1f7810d033ba5fc2bc58a1b453a3c0df7984e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 12 Dec 2023 14:21:35 +0100 Subject: [PATCH 118/378] Remove dependency on assert_matches (#419) --- Cargo.lock | 7 ------- crates/bitwarden/Cargo.toml | 1 - crates/bitwarden/src/client/client_settings.rs | 4 ---- 3 files changed, 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7ba84c53..0b89bd2e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,12 +184,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "assert_matches" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" - [[package]] name = "async-channel" version = "1.9.0" @@ -339,7 +333,6 @@ version = "0.3.1" dependencies = [ "aes", "argon2", - "assert_matches", "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 4d92e4270..8f7c1f4d1 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -24,7 +24,6 @@ aes = ">=0.8.2, <0.9" argon2 = { version = ">=0.5.0, <0.6", features = [ "alloc", ], default-features = false } -assert_matches = ">=1.5.0, <2.0" base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } diff --git a/crates/bitwarden/src/client/client_settings.rs b/crates/bitwarden/src/client/client_settings.rs index 68ef7b3a9..172baf733 100644 --- a/crates/bitwarden/src/client/client_settings.rs +++ b/crates/bitwarden/src/client/client_settings.rs @@ -8,7 +8,6 @@ use serde::{Deserialize, Serialize}; /// /// ``` /// # use bitwarden::client::client_settings::{ClientSettings, DeviceType}; -/// # use assert_matches::assert_matches; /// let settings = ClientSettings { /// identity_url: "https://identity.bitwarden.com".to_string(), /// api_url: "https://api.bitwarden.com".to_string(), @@ -16,10 +15,7 @@ use serde::{Deserialize, Serialize}; /// device_type: DeviceType::SDK, /// }; /// let default = ClientSettings::default(); -/// assert_matches!(settings, default); /// ``` -/// -/// Targets `localhost:8080` for debug builds. #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(default, rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] From 826d272516b4963db77d1448f4512606c7158c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 12 Dec 2023 14:46:48 +0100 Subject: [PATCH 119/378] [PM-4694] Implement PIN unlock (#421) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement support for deriving the PIN encrypted user key and initializing crypto with it. Updated the mobile app demos to use this new functionality. --- crates/bitwarden-uniffi/src/crypto.rs | 10 +- crates/bitwarden/src/client/client.rs | 24 +++- crates/bitwarden/src/crypto/master_key.rs | 41 ++++-- .../src/crypto/symmetric_crypto_key.rs | 10 ++ crates/bitwarden/src/mobile/client_crypto.rs | 9 +- crates/bitwarden/src/mobile/crypto.rs | 118 +++++++++++++++++- .../bitwarden/myapplication/MainActivity.kt | 89 ++++++++++++- languages/kotlin/doc.md | 39 ++++++ languages/swift/iOS/App/ContentView.swift | 61 ++++++++- 9 files changed, 381 insertions(+), 20 deletions(-) diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 995750b7f..25d577ba5 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -1,6 +1,8 @@ use std::sync::Arc; -use bitwarden::mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}; +use bitwarden::mobile::crypto::{ + DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, +}; use crate::{error::Result, Client}; @@ -45,4 +47,10 @@ impl ClientCrypto { .get_user_encryption_key() .await?) } + + /// Generates a PIN protected user key from the provided PIN. The result can be stored and later used + /// to initialize another client instance by using the PIN and the PIN key with `initialize_user_crypto`. + pub async fn derive_pin_key(&self, pin: String) -> Result { + Ok(self.0 .0.write().await.crypto().derive_pin_key(pin).await?) + } } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 2b6b76a2f..2165b8dc7 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -224,10 +224,9 @@ impl Client { #[cfg(feature = "mobile")] pub(crate) fn initialize_user_crypto_decrypted_key( &mut self, - decrypted_user_key: &str, + user_key: SymmetricCryptoKey, private_key: EncString, ) -> Result<&EncryptionSettings> { - let user_key = decrypted_user_key.parse::()?; self.encryption_settings = Some(EncryptionSettings::new_decrypted_key( user_key, private_key, @@ -238,6 +237,27 @@ impl Client { .expect("It was initialized on the previous line")) } + #[cfg(feature = "mobile")] + pub(crate) fn initialize_user_crypto_pin( + &mut self, + pin: &str, + pin_protected_user_key: EncString, + private_key: EncString, + ) -> Result<&EncryptionSettings> { + use crate::crypto::MasterKey; + + let pin_key = match &self.login_method { + Some(LoginMethod::User( + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. }, + )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, + _ => return Err(Error::NotAuthenticated), + }; + + let decrypted_user_key = pin_key.decrypt_user_key(pin_protected_user_key)?; + self.initialize_user_crypto_decrypted_key(decrypted_user_key, private_key) + } + pub(crate) fn initialize_crypto_single_key( &mut self, key: SymmetricCryptoKey, diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 88e5b9327..9786da3c2 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -52,6 +52,16 @@ impl MasterKey { let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_slice()) } + + pub(crate) fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result { + let stretched_key = stretch_master_key(self)?; + + EncString::encrypt_aes256_hmac( + user_key.to_vec().as_slice(), + stretched_key.mac_key.unwrap(), + stretched_key.key, + ) + } } /// Generate a new random user key and encrypt it with the master key. @@ -62,15 +72,9 @@ fn make_user_key( let mut user_key = [0u8; 64]; rng.fill(&mut user_key); - let stretched_key = stretch_master_key(master_key)?; - let protected = EncString::encrypt_aes256_hmac( - &user_key, - stretched_key.mac_key.unwrap(), - stretched_key.key, - )?; - - let u: &[u8] = &user_key; - Ok((UserKey::new(SymmetricCryptoKey::try_from(u)?), protected)) + let user_key = SymmetricCryptoKey::try_from(user_key.as_slice())?; + let protected = master_key.encrypt_user_key(&user_key)?; + Ok((UserKey::new(user_key), protected)) } /// Derive a generic key from a secret and salt using the provided KDF. @@ -285,4 +289,23 @@ mod tests { "Decrypted key doesn't match user key" ); } + + #[test] + fn test_make_user_key2() { + let master_key = MasterKey(SymmetricCryptoKey::generate("test1")); + + let user_key = SymmetricCryptoKey::generate("test2"); + + let encrypted = master_key.encrypt_user_key(&user_key).unwrap(); + let decrypted = master_key.decrypt_user_key(encrypted).unwrap(); + + assert_eq!( + decrypted.key, user_key.key, + "Decrypted key doesn't match user key" + ); + assert_eq!( + decrypted.mac_key, user_key.mac_key, + "Decrypted key doesn't match user key" + ); + } } diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs index 7b2086f75..5bce9e65d 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs @@ -35,6 +35,16 @@ impl SymmetricCryptoKey { BASE64_ENGINE.encode(&buf) } + + #[cfg(feature = "internal")] + pub(super) fn to_vec(&self) -> Vec { + let mut buf = Vec::new(); + buf.extend_from_slice(&self.key); + if let Some(mac) = self.mac_key { + buf.extend_from_slice(&mac); + } + buf + } } impl FromStr for SymmetricCryptoKey { diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index 118e02726..cddb7c140 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -3,8 +3,8 @@ use crate::Client; use crate::{ error::Result, mobile::crypto::{ - get_user_encryption_key, initialize_org_crypto, initialize_user_crypto, - InitOrgCryptoRequest, InitUserCryptoRequest, + derive_pin_key, get_user_encryption_key, initialize_org_crypto, initialize_user_crypto, + DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, }, }; @@ -27,6 +27,11 @@ impl<'a> ClientCrypto<'a> { pub async fn get_user_encryption_key(&mut self) -> Result { get_user_encryption_key(self.client).await } + + #[cfg(feature = "internal")] + pub async fn derive_pin_key(&mut self, pin: String) -> Result { + derive_pin_key(self.client, pin) + } } impl<'a> Client { diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 9c2c8478f..edb44fadc 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -40,10 +40,18 @@ pub enum InitUserCryptoMethod { /// The user's decrypted encryption key, obtained using `get_user_encryption_key` decrypted_user_key: String, }, + Pin { + /// The user's PIN + pin: String, + /// The user's symmetric crypto key, encrypted with the PIN. Use `derive_pin_key` to obtain this. + pin_protected_user_key: EncString, + }, } #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { + use crate::crypto::SymmetricCryptoKey; + let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), email: req.email, @@ -59,7 +67,14 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ client.initialize_user_crypto(&password, user_key, private_key)?; } InitUserCryptoMethod::DecryptedKey { decrypted_user_key } => { - client.initialize_user_crypto_decrypted_key(&decrypted_user_key, private_key)?; + let user_key = decrypted_user_key.parse::()?; + client.initialize_user_crypto_decrypted_key(user_key, private_key)?; + } + InitUserCryptoMethod::Pin { + pin, + pin_protected_user_key, + } => { + client.initialize_user_crypto_pin(&pin, pin_protected_user_key, private_key)?; } } @@ -91,3 +106,104 @@ pub async fn get_user_encryption_key(client: &mut Client) -> Result { Ok(user_key.to_base64()) } + +#[cfg(feature = "internal")] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct DerivePinKeyResponse { + pin_protected_user_key: EncString, + encrypted_pin: EncString, +} + +#[cfg(feature = "internal")] +pub fn derive_pin_key(client: &mut Client, pin: String) -> Result { + use crate::{ + client::{LoginMethod, UserLoginMethod}, + crypto::{KeyEncryptable, MasterKey}, + }; + + let derived_key = match &client.login_method { + Some(LoginMethod::User( + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. }, + )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, + _ => return Err(Error::NotAuthenticated), + }; + + let user_key = client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + + Ok(DerivePinKeyResponse { + pin_protected_user_key: derived_key.encrypt_user_key(user_key)?, + encrypted_pin: pin.encrypt_with_key(user_key)?, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{client::kdf::Kdf, Client}; + + #[tokio::test] + async fn test_initialize_user_crypto_pin() { + let mut client = Client::new(None); + + let priv_key = "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw="; + + initialize_user_crypto( + &mut client, + InitUserCryptoRequest { + kdf_params: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + email: "test@bitwarden.com".into(), + private_key: priv_key.to_owned(), + method: InitUserCryptoMethod::Password { + password: "asdfasdfasdf".into(), + user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".into(), + }, + }, + ) + .await + .unwrap(); + + let pin_key = derive_pin_key(&mut client, "1234".into()).unwrap(); + + let mut client2 = Client::new(None); + + initialize_user_crypto( + &mut client2, + InitUserCryptoRequest { + kdf_params: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + email: "test@bitwarden.com".into(), + private_key: priv_key.to_owned(), + method: InitUserCryptoMethod::Pin { + pin: "1234".into(), + pin_protected_user_key: pin_key.pin_protected_user_key, + }, + }, + ) + .await + .unwrap(); + + assert_eq!( + client + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64(), + client2 + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64() + ); + } +} diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index b41b12b8c..c38c14a07 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -72,6 +72,8 @@ const val IDENTITY_URL = SERVER_URL + "identity/" const val EMAIL = "test@bitwarden.com" const val PASSWORD = "asdfasdfasdf" +const val PIN = "1234" + // We should separate keys for each user by appending the user_id const val BIOMETRIC_KEY = "biometric_key" @@ -99,10 +101,12 @@ class MainActivity : FragmentActivity() { ) { val setupBiometrics = remember { mutableStateOf(true) } + val setupPin = remember { mutableStateOf(true) } val outputText = remember { mutableStateOf("") } Row { - Checkbox(checked = setupBiometrics.value, + Checkbox( + checked = setupBiometrics.value, onCheckedChange = { isChecked -> setupBiometrics.value = isChecked }) @@ -112,10 +116,20 @@ class MainActivity : FragmentActivity() { ) } + Row { + Checkbox(checked = setupPin.value, onCheckedChange = { isChecked -> + setupPin.value = isChecked + }) + Text( + "Setup pin unlock after login", + modifier = Modifier.align(CenterVertically) + ) + } + Button({ GlobalScope.launch { clientExamplePassword( - client, http, outputText, setupBiometrics.value + client, http, outputText, setupBiometrics.value, setupPin.value ) } }) { @@ -136,6 +150,14 @@ class MainActivity : FragmentActivity() { Text("Unlock with biometrics") } + Button({ + GlobalScope.launch { + clientExamplePin(client, http, outputText) + } + }) { + Text("Unlock with PIN") + } + Button({ GlobalScope.launch { client.destroy() @@ -157,7 +179,11 @@ class MainActivity : FragmentActivity() { } private suspend fun clientExamplePassword( - client: Client, http: HttpClient, outputText: MutableState, setupBiometrics: Boolean + client: Client, + http: HttpClient, + outputText: MutableState, + setupBiometrics: Boolean, + setupPin: Boolean ) { println("### Logging in with username and password ###") ///////////////////////////// Get master password hash ///////////////////////////// @@ -248,6 +274,25 @@ class MainActivity : FragmentActivity() { } } } + + if (setupPin) { + val pinOptions = client.crypto().derivePinKey(PIN); + + val sharedPref = getPreferences(Context.MODE_PRIVATE) + with(sharedPref.edit()) { + putString("accessToken", accessToken) + putString("privateKey", loginBody.PrivateKey) + + putInt("kdfType", prelogin_body.kdf.toInt()) + putInt("kdfIterations", prelogin_body.kdfIterations.toInt()) + putInt("kdfMemory", (prelogin_body.kdfMemory ?: 0u).toInt()) + putInt("kdfParallelism", (prelogin_body.kdfParallelism ?: 0u).toInt()) + + putString("encryptedPin", pinOptions.encryptedPin) + putString("pinProtectedUserKey", pinOptions.pinProtectedUserKey) + apply() + } + } } private suspend fun clientExampleBiometrics( @@ -290,6 +335,44 @@ class MainActivity : FragmentActivity() { } } + private suspend fun clientExamplePin( + client: Client, http: HttpClient, outputText: MutableState + ) { + println("### Unlocking with PIN ###") + + val pref = getPreferences(Context.MODE_PRIVATE) + accessToken = pref.getString("accessToken", "").orEmpty() + val privateKey = pref.getString("privateKey", "") + + val kdf = if (pref.getInt("kdfType", 0) == 0) { + Kdf.Pbkdf2(pref.getInt("kdfIterations", 0).toUInt()) + } else { + Kdf.Argon2id( + pref.getInt("kdfIterations", 0).toUInt(), + pref.getInt("kdfMemory", 0).toUInt(), + pref.getInt("kdfParallelism", 0).toUInt() + ) + } + + val encryptedPin = pref.getString("encryptedPin", "")!! + val pinProtectedUserKey = pref.getString("pinProtectedUserKey", "")!! + + GlobalScope.launch { + client.crypto().initializeUserCrypto( + InitUserCryptoRequest( + kdfParams = kdf, + email = EMAIL, + privateKey = privateKey!!, + method = InitUserCryptoMethod.Pin( + pinProtectedUserKey = pinProtectedUserKey, pin = PIN + ) + ) + ) + + decryptVault(client, http, outputText) + } + } + suspend fun decryptVault(client: Client, http: HttpClient, outputText: MutableState) { ///////////////////////////// Sync ///////////////////////////// diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index f9f47db64..9249751f0 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -233,6 +233,19 @@ as it can be used to decrypt all of the user's data **Output**: std::result::Result +### `derive_pin_key` + +Generates a PIN protected user key from the provided PIN. The result can be stored and later used to +initialize another client instance by using the PIN and the PIN key with +`initialize_user_crypto`. + +**Arguments**: + +- self: +- pin: String + +**Output**: std::result::Result + ## ClientExporters ### `export_vault` @@ -998,6 +1011,32 @@ implementations. + + pin + object + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescription
pinstringThe user's PIN
pin_protected_user_keyThe user's symmetric crypto key, encrypted with the PIN. Use `derive_pin_key` to obtain this.
+ + ## `InitUserCryptoRequest` diff --git a/languages/swift/iOS/App/ContentView.swift b/languages/swift/iOS/App/ContentView.swift index c2b488b8f..b5fc0d4f0 100644 --- a/languages/swift/iOS/App/ContentView.swift +++ b/languages/swift/iOS/App/ContentView.swift @@ -23,6 +23,8 @@ let IDENTITY_URL = SERVER_URL + "identity/" let EMAIL = "test@bitwarden.com" let PASSWORD = "asdfasdfasdf" +let PIN = "1234" + struct ContentView: View { private var http: URLSession @@ -40,16 +42,18 @@ struct ContentView: View { } @State var setupBiometrics: Bool = true + @State var setupPin: Bool = true @State var outputText: String = "" var body: some View { VStack { Toggle("Setup biometric unlock after login", isOn: $setupBiometrics).padding(.init(top: 0, leading: 20, bottom: 0, trailing: 20)) + Toggle("Setup PIN unlock after login", isOn: $setupPin).padding(.init(top: 0, leading: 20, bottom: 0, trailing: 20)) Button(action: { Task { do { - try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics) + try await clientExamplePassword(clientAuth: client.auth(), clientCrypto: client.crypto(), setupBiometrics: setupBiometrics, setupPin: setupPin) try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) } catch { print("ERROR:", error) @@ -74,6 +78,19 @@ struct ContentView: View { Text("Unlock with biometrics") }) + Button(action: { + Task { + do { + try await clientExamplePin(clientCrypto: client.crypto()) + try await decryptVault(clientCrypto: client.crypto(), clientVault: client.vault()) + } catch { + print("ERROR:", error) + } + } + }, label: { + Text("Unlock with PIN") + }) + Button(action: { client = Client(settings: nil) }, label: { @@ -85,7 +102,7 @@ struct ContentView: View { .padding() } - func clientExamplePassword(clientAuth: ClientAuthProtocol, clientCrypto: ClientCryptoProtocol, setupBiometrics: Bool) async throws { + func clientExamplePassword(clientAuth: ClientAuthProtocol, clientCrypto: ClientCryptoProtocol, setupBiometrics: Bool, setupPin: Bool) async throws { ////////////////////////////// Get master password hash ////////////////////////////// struct PreloginRequest: Codable { let email: String } @@ -183,6 +200,22 @@ struct ContentView: View { let key = try await clientCrypto.getUserEncryptionKey() biometricStoreValue(value: key) } + + if (setupPin) { + let pinOptions = try await clientCrypto.derivePinKey(pin: PIN) + + let defaults = UserDefaults.standard + defaults.set(loginData.PrivateKey, forKey: "privateKey") + defaults.set(preloginData.kdf, forKey: "kdfType") + defaults.set(preloginData.kdfIterations, forKey: "kdfIterations") + defaults.set(preloginData.kdfMemory, forKey: "kdfMemory") + defaults.set(preloginData.kdfParallelism, forKey: "kdfParallelism") + + defaults.set(pinOptions.encryptedPin, forKey: "encryptedPin") + defaults.set(pinOptions.pinProtectedUserKey, forKey: "pinProtectedUserKey") + + defaults.synchronize() + } } func clientExampleBiometrics(clientCrypto: ClientCryptoProtocol) async throws { @@ -210,6 +243,30 @@ struct ContentView: View { )) } + func clientExamplePin(clientCrypto: ClientCryptoProtocol) async throws { + let defaults = UserDefaults.standard + let privateKey = defaults.string(forKey: "privateKey")! + let kdf = if defaults.integer(forKey: "kdfType") == 0 { + Kdf.pbkdf2(iterations: UInt32(defaults.integer(forKey: "kdfIterations"))) + } else { + Kdf.argon2id( + iterations: UInt32(defaults.integer(forKey: "kdfIterations")), + memory: UInt32(defaults.integer(forKey: "kdfMemory")), + parallelism: UInt32(defaults.integer(forKey: "kdfParallelism")) + ) + } + + let encryptedPin = defaults.string(forKey: "encryptedPin")! + let pinProtectedUserKey = defaults.string(forKey: "pinProtectedUserKey")! + + try await clientCrypto.initializeUserCrypto(req: InitUserCryptoRequest( + kdfParams: kdf, + email: EMAIL, + privateKey: privateKey, + method: InitUserCryptoMethod.pin(pin: PIN, pinProtectedUserKey: pinProtectedUserKey) + )) + } + func decryptVault(clientCrypto: ClientCryptoProtocol, clientVault: ClientVaultProtocol) async throws { ///////////////////////////// Sync ///////////////////////////// From 2c85c94206fd0a91e75dce0951f7eee192e8a827 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 12 Dec 2023 10:22:28 -0500 Subject: [PATCH 120/378] Update Version Bump workflow (#424) --- .github/workflows/version-bump.yml | 117 ++++++++++++++++------------- 1 file changed, 64 insertions(+), 53 deletions(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 9881b9b0e..f136c1dfe 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -1,7 +1,18 @@ --- name: Version Bump +run-name: Version Bump - v${{ inputs.version_number }} on: + workflow_call: + inputs: + project: + description: "Project" + required: true + type: string + version_number: + description: "New version (example: '2024.1.0')" + required: true + type: string workflow_dispatch: inputs: project: @@ -16,16 +27,12 @@ on: - cli - bitwarden-json version_number: - description: "New Version" + description: "New version (example: '2024.1.0')" required: true -defaults: - run: - shell: bash - jobs: bump_version: - name: "Bump ${{ github.event.inputs.project }} Version" + name: "Bump ${{ inputs.project }} Version to v${{ inputs.version_number }}" runs-on: ubuntu-22.04 steps: - name: Checkout Branch @@ -42,7 +49,7 @@ jobs: - name: Install cargo-release run: cargo install cargo-edit - - name: Login to Azure - Prod Subscription + - name: Login to Azure - CI Subscription uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -52,7 +59,9 @@ jobs: uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" - secrets: "github-gpg-private-key, github-gpg-private-key-passphrase" + secrets: "github-gpg-private-key, + github-gpg-private-key-passphrase, + github-pat-bitwarden-devops-bot-repo-scope" - name: Import GPG key uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 @@ -65,69 +74,62 @@ jobs: - name: Create Version Branch id: branch env: - VERSION: ${{ github.event.inputs.version_number }} - PROJECT: ${{ github.event.inputs.project }} + VERSION: ${{ inputs.version_number }} + PROJECT: ${{ inputs.project }} run: git switch -c sdk-${PROJECT}_version_bump_${VERSION} + - name: Create Version Branch + id: create-branch + run: | + NAME=version_bump_${{ github.ref_name }}_${{ inputs.project }}_${{ inputs.version_number }} + git switch -c $NAME + echo "name=$NAME" >> $GITHUB_OUTPUT + ######################## # VERSION BUMP SECTION # ######################## ### napi - name: Bump @bitwarden/sdk-napi Version - if: ${{ github.event.inputs.project == 'napi' }} - env: - VERSION: ${{ github.event.inputs.version_number }} + if: ${{ inputs.project == 'napi' }} working-directory: "crates/bitwarden-napi" run: | npm ci - npm version ${VERSION} + npm version ${{ inputs.version_number }} - name: Bump napi crate Version - if: ${{ github.event.inputs.project == 'napi' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bitwarden-napi ${VERSION} + if: ${{ inputs.project == 'napi' }} + run: cargo-set-version set-version -p bitwarden-napi ${{ inputs.version_number }} ### bitwarden - name: Bump bitwarden crate Version - if: ${{ github.event.inputs.project == 'bitwarden' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bitwarden ${VERSION} + if: ${{ inputs.project == 'bitwarden' }} + run: cargo-set-version set-version -p bitwarden ${{ inputs.version_number }} ### bitwarden-api-api - name: Bump bitwarden-api-api crate Version - if: ${{ github.event.inputs.project == 'bitwarden-api-api' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bitwarden-api-api ${VERSION} + if: ${{ inputs.project == 'bitwarden-api-api' }} + run: cargo-set-version set-version -p bitwarden-api-api ${{ inputs.version_number }} ### bitwarden-api-identity - name: Bump bitwarden-api-identity crate Version - if: ${{ github.event.inputs.project == 'bitwarden-api-identity' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bitwarden-api-identity ${VERSION} + if: ${{ inputs.project == 'bitwarden-api-identity' }} + run: cargo-set-version set-version -p bitwarden-api-identity ${{ inputs.version_number }} ### cli - name: Bump cli Version - if: ${{ github.event.inputs.project == 'cli' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bws ${VERSION} + if: ${{ inputs.project == 'cli' }} + run: cargo-set-version set-version -p bws ${{ inputs.version_number }} ### bitwarden-json - name: Bump bitwarden-json crate Version - if: ${{ github.event.inputs.project == 'bitwarden-json' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - run: cargo-set-version set-version -p bitwarden-json ${VERSION} + if: ${{ inputs.project == 'bitwarden-json' }} + run: cargo-set-version set-version -p bitwarden-json ${{ inputs.version_number }} ############################ # VERSION BUMP SECTION END # @@ -156,28 +158,24 @@ jobs: - name: Commit files if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} - env: - VERSION: ${{ github.event.inputs.version_number }} - PROJECT: ${{ github.event.inputs.project }} - run: git commit -m "Bumped sdk-${PROJECT} version to ${VERSION}" -a + run: git commit -m "Bumped sdk-${{ inputs.project }} version to ${{ inputs.version_number }}" -a - name: Push changes if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} env: - VERSION: ${{ github.event.inputs.version_number }} - PROJECT: ${{ github.event.inputs.project }} - run: git push -u origin sdk-${PROJECT}_version_bump_${VERSION} + PR_BRANCH: ${{ steps.create-branch.outputs.name }} + run: git push -u origin $PR_BRANCH - - name: Create Bump Version PR + - name: Create Version PR if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} + id: create-pr env: - PR_BRANCH: "sdk-${{ github.event.inputs.project }}_version_bump_${{ github.event.inputs.version_number }}" - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - BASE_BRANCH: master - TITLE: "Bump ${{ github.event.inputs.project }} version to ${{ github.event.inputs.version_number }}" + PR_BRANCH: ${{ steps.create-branch.outputs.name }} + GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + TITLE: "Bump version to ${{ inputs.version_number }}" run: | - gh pr create --title "$TITLE" \ - --base "$BASE" \ + PR_URL=$(gh pr create --title "$TITLE" \ + --base "$GITHUB_REF" \ --head "$PR_BRANCH" \ --label "version update" \ --label "automated pr" \ @@ -190,4 +188,17 @@ jobs: - [X] Other ## Objective - Automated ${{ github.event.inputs.project }} version bump to ${{ github.event.inputs.version_number }}" + Automated ${{ inputs.project }} version bump to ${{ inputs.version_number }}") + echo "pr_number=${PR_URL##*/}" >> $GITHUB_OUTPUT + + - name: Approve PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} + run: gh pr review $PR_NUMBER --approve + + - name: Merge PR + env: + GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} + run: gh pr merge $PR_NUMBER --squash --auto --delete-branch From f17bac368509b00e78abd3883f0e4e5525e0e720 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 12 Dec 2023 16:25:39 +0100 Subject: [PATCH 121/378] Map from Requests to Domain models (#298) Implements many of the translators from Request models to Domain models. Wires us up for hooking-up the sync response handling. --- crates/bitwarden/src/admin_console/mod.rs | 3 + crates/bitwarden/src/admin_console/policy.rs | 70 +++++++++++++++++++ crates/bitwarden/src/crypto/enc_string.rs | 24 +++++-- crates/bitwarden/src/lib.rs | 4 +- crates/bitwarden/src/mobile/mod.rs | 12 ---- crates/bitwarden/src/platform/domain.rs | 23 ++++++ crates/bitwarden/src/platform/mod.rs | 1 + crates/bitwarden/src/platform/sync.rs | 60 ++++++++++++---- .../bitwarden/src/vault/cipher/attachment.rs | 21 +++++- crates/bitwarden/src/vault/cipher/card.rs | 18 ++++- crates/bitwarden/src/vault/cipher/cipher.rs | 68 +++++++++++++++++- crates/bitwarden/src/vault/cipher/field.rs | 30 +++++++- crates/bitwarden/src/vault/cipher/identity.rs | 30 +++++++- .../bitwarden/src/vault/cipher/linked_id.rs | 38 ++++++++++ crates/bitwarden/src/vault/cipher/login.rs | 48 ++++++++++++- .../bitwarden/src/vault/cipher/secure_note.rs | 21 +++++- crates/bitwarden/src/vault/collection.rs | 18 ++++- crates/bitwarden/src/vault/folder.rs | 15 +++- crates/bitwarden/src/vault/mod.rs | 3 + .../bitwarden/src/vault/password_history.rs | 14 +++- crates/bitwarden/src/vault/send.rs | 61 +++++++++++++++- crates/bw/src/auth/login.rs | 8 +++ 22 files changed, 545 insertions(+), 45 deletions(-) create mode 100644 crates/bitwarden/src/admin_console/mod.rs create mode 100644 crates/bitwarden/src/admin_console/policy.rs create mode 100644 crates/bitwarden/src/platform/domain.rs diff --git a/crates/bitwarden/src/admin_console/mod.rs b/crates/bitwarden/src/admin_console/mod.rs new file mode 100644 index 000000000..e553456cf --- /dev/null +++ b/crates/bitwarden/src/admin_console/mod.rs @@ -0,0 +1,3 @@ +mod policy; + +pub use policy::Policy; diff --git a/crates/bitwarden/src/admin_console/policy.rs b/crates/bitwarden/src/admin_console/policy.rs new file mode 100644 index 000000000..1b4acc310 --- /dev/null +++ b/crates/bitwarden/src/admin_console/policy.rs @@ -0,0 +1,70 @@ +use std::collections::HashMap; + +use bitwarden_api_api::models::PolicyResponseModel; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use uuid::Uuid; + +use crate::error::{Error, Result}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct Policy { + id: Uuid, + organization_id: Uuid, + r#type: PolicyType, + data: Option>, + enabled: bool, +} + +#[derive(Serialize_repr, Deserialize_repr, Debug, JsonSchema)] +#[repr(u8)] +pub enum PolicyType { + TwoFactorAuthentication = 0, // Requires users to have 2fa enabled + MasterPassword = 1, // Sets minimum requirements for master password complexity + PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases + SingleOrg = 3, // Allows users to only be apart of one organization + RequireSso = 4, // Requires users to authenticate with SSO + PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items + DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends + SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends + ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow + MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout + DisablePersonalVaultExport = 10, // Disable personal vault export + ActivateAutofill = 11, // Activates autofill with page load on the browser extension +} + +impl TryFrom for Policy { + type Error = Error; + + fn try_from(policy: PolicyResponseModel) -> Result { + Ok(Self { + id: policy.id.ok_or(Error::MissingFields)?, + organization_id: policy.organization_id.ok_or(Error::MissingFields)?, + r#type: policy.r#type.ok_or(Error::MissingFields)?.into(), + data: policy.data, + enabled: policy.enabled.ok_or(Error::MissingFields)?, + }) + } +} + +impl From for PolicyType { + fn from(policy_type: bitwarden_api_api::models::PolicyType) -> Self { + match policy_type { + bitwarden_api_api::models::PolicyType::Variant0 => PolicyType::TwoFactorAuthentication, + bitwarden_api_api::models::PolicyType::Variant1 => PolicyType::MasterPassword, + bitwarden_api_api::models::PolicyType::Variant2 => PolicyType::PasswordGenerator, + bitwarden_api_api::models::PolicyType::Variant3 => PolicyType::SingleOrg, + bitwarden_api_api::models::PolicyType::Variant4 => PolicyType::RequireSso, + bitwarden_api_api::models::PolicyType::Variant5 => PolicyType::PersonalOwnership, + bitwarden_api_api::models::PolicyType::Variant6 => PolicyType::DisableSend, + bitwarden_api_api::models::PolicyType::Variant7 => PolicyType::SendOptions, + bitwarden_api_api::models::PolicyType::Variant8 => PolicyType::ResetPassword, + bitwarden_api_api::models::PolicyType::Variant9 => PolicyType::MaximumVaultTimeout, + bitwarden_api_api::models::PolicyType::Variant10 => { + PolicyType::DisablePersonalVaultExport + } + bitwarden_api_api::models::PolicyType::Variant11 => PolicyType::ActivateAutofill, + } + } +} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index 09f877c50..3004d2dea 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -4,14 +4,13 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; use serde::{de::Visitor, Deserialize}; +use super::{KeyDecryptable, KeyEncryptable, LocateKey}; use crate::{ crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; -use super::{KeyDecryptable, KeyEncryptable, LocateKey}; - /// # Encrypted string primitive /// /// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are @@ -165,6 +164,12 @@ impl FromStr for EncString { } impl EncString { + /// Synthetic sugar for mapping `Option` to `Result>` + #[cfg(feature = "internal")] + pub(crate) fn try_from_optional(s: Option) -> Result, Error> { + s.map(|s| s.parse()).transpose() + } + #[cfg(feature = "mobile")] pub(crate) fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { @@ -397,11 +402,22 @@ impl KeyDecryptable for EncString { } } +/// Usually we wouldn't want to expose EncStrings in the API or the schemas. +/// But during the transition phase we will expose endpoints using the EncString type. +impl schemars::JsonSchema for crate::crypto::EncString { + fn schema_name() -> String { + "EncString".to_string() + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + gen.subschema_for::() + } +} + #[cfg(test)] mod tests { - use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; - use super::EncString; + use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; #[test] fn test_enc_string_roundtrip() { diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index 20e36d237..0017ecff9 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -51,6 +51,8 @@ #[cfg(feature = "mobile")] uniffi::setup_scaffolding!(); +#[cfg(feature = "internal")] +pub mod admin_console; pub mod auth; pub mod client; pub mod crypto; @@ -66,7 +68,7 @@ pub mod tool; #[cfg(feature = "mobile")] pub(crate) mod uniffi_support; mod util; -#[cfg(feature = "mobile")] +#[cfg(feature = "internal")] pub mod vault; pub mod wordlist; diff --git a/crates/bitwarden/src/mobile/mod.rs b/crates/bitwarden/src/mobile/mod.rs index fe3083aa8..e0ba50d00 100644 --- a/crates/bitwarden/src/mobile/mod.rs +++ b/crates/bitwarden/src/mobile/mod.rs @@ -8,15 +8,3 @@ mod client_kdf; pub use client_crypto::ClientCrypto; pub use client_kdf::ClientKdf; - -// Usually we wouldn't want to expose EncStrings in the API or the schemas, -// but we need them in the mobile API, so define it here to limit the scope -impl schemars::JsonSchema for crate::crypto::EncString { - fn schema_name() -> String { - "EncString".to_string() - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - gen.subschema_for::() - } -} diff --git a/crates/bitwarden/src/platform/domain.rs b/crates/bitwarden/src/platform/domain.rs new file mode 100644 index 000000000..c903dd5a5 --- /dev/null +++ b/crates/bitwarden/src/platform/domain.rs @@ -0,0 +1,23 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use crate::error::{Error, Result}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +pub struct GlobalDomains { + pub r#type: i32, + pub domains: Vec, + pub excluded: bool, +} + +impl TryFrom for GlobalDomains { + type Error = Error; + + fn try_from(global_domains: bitwarden_api_api::models::GlobalDomains) -> Result { + Ok(Self { + r#type: global_domains.r#type.ok_or(Error::MissingFields)?, + domains: global_domains.domains.ok_or(Error::MissingFields)?, + excluded: global_domains.excluded.ok_or(Error::MissingFields)?, + }) + } +} diff --git a/crates/bitwarden/src/platform/mod.rs b/crates/bitwarden/src/platform/mod.rs index 0224e8d3a..0e234f00b 100644 --- a/crates/bitwarden/src/platform/mod.rs +++ b/crates/bitwarden/src/platform/mod.rs @@ -1,3 +1,4 @@ +mod domain; mod generate_fingerprint; mod get_user_api_key; mod secret_verification_request; diff --git a/crates/bitwarden/src/platform/sync.rs b/crates/bitwarden/src/platform/sync.rs index fd33e4343..870b88ab9 100644 --- a/crates/bitwarden/src/platform/sync.rs +++ b/crates/bitwarden/src/platform/sync.rs @@ -1,14 +1,16 @@ use bitwarden_api_api::models::{ - CipherDetailsResponseModel, ProfileOrganizationResponseModel, ProfileResponseModel, - SyncResponseModel, + DomainsResponseModel, ProfileOrganizationResponseModel, ProfileResponseModel, SyncResponseModel, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; +use super::domain::GlobalDomains; use crate::{ + admin_console::Policy, client::{encryption_settings::EncryptionSettings, Client}, error::{Error, Result}, + vault::{Cipher, Collection, Folder}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -59,15 +61,23 @@ pub struct ProfileOrganizationResponse { #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct CipherDetailsResponse {} +pub struct DomainResponse { + pub equivalent_domains: Vec>, + pub global_equivalent_domains: Vec, +} #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct SyncResponse { /// Data about the user, including their encryption keys and the organizations they are a part of pub profile: ProfileResponse, - /// List of ciphers accesible by the user - pub ciphers: Vec, + pub folders: Vec, + pub collections: Vec, + /// List of ciphers accessible by the user + pub ciphers: Vec, + pub domains: Option, + pub policies: Vec, + pub sends: Vec, } impl SyncResponse { @@ -78,22 +88,27 @@ impl SyncResponse { let profile = *response.profile.ok_or(Error::MissingFields)?; let ciphers = response.ciphers.ok_or(Error::MissingFields)?; + fn try_into_iter(iter: In) -> Result + where + In: IntoIterator, + InItem: TryInto, + Out: FromIterator, + { + iter.into_iter().map(|i| i.try_into()).collect() + } + Ok(SyncResponse { profile: ProfileResponse::process_response(profile, enc)?, - ciphers: ciphers - .into_iter() - .map(CipherDetailsResponse::process_response) - .collect::>()?, + folders: try_into_iter(response.folders.ok_or(Error::MissingFields)?)?, + collections: try_into_iter(response.collections.ok_or(Error::MissingFields)?)?, + ciphers: try_into_iter(ciphers)?, + domains: response.domains.map(|d| (*d).try_into()).transpose()?, + policies: try_into_iter(response.policies.ok_or(Error::MissingFields)?)?, + sends: try_into_iter(response.sends.ok_or(Error::MissingFields)?)?, }) } } -impl CipherDetailsResponse { - fn process_response(_response: CipherDetailsResponseModel) -> Result { - Ok(CipherDetailsResponse {}) - } -} - impl ProfileOrganizationResponse { fn process_response( response: ProfileOrganizationResponseModel, @@ -124,3 +139,18 @@ impl ProfileResponse { }) } } + +impl TryFrom for DomainResponse { + type Error = Error; + fn try_from(value: DomainsResponseModel) -> Result { + Ok(Self { + equivalent_domains: value.equivalent_domains.unwrap_or_default(), + global_equivalent_domains: value + .global_equivalent_domains + .unwrap_or_default() + .into_iter() + .map(|s| s.try_into()) + .collect::>>()?, + }) + } +} diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 101c8f4bc..ace4937da 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -28,7 +28,7 @@ pub struct AttachmentView { pub size: Option, pub size_name: Option, pub file_name: Option, - pub key: Option, + pub key: Option>, // TODO: Should be made into SymmetricCryptoKey } impl KeyEncryptable for AttachmentView { @@ -39,7 +39,7 @@ impl KeyEncryptable for AttachmentView { size: self.size, size_name: self.size_name, file_name: self.file_name.encrypt_with_key(key)?, - key: self.key.encrypt_with_key(key)?, + key: self.key.as_deref().encrypt_with_key(key)?, }) } } @@ -56,3 +56,18 @@ impl KeyDecryptable for Attachment { }) } } + +impl TryFrom for Attachment { + type Error = Error; + + fn try_from(attachment: bitwarden_api_api::models::AttachmentResponseModel) -> Result { + Ok(Self { + id: attachment.id, + url: attachment.url, + size: attachment.size, + size_name: attachment.size_name, + file_name: EncString::try_from_optional(attachment.file_name)?, + key: EncString::try_from_optional(attachment.key)?, + }) + } +} diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 1545ad171..6f96041e9 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,9 +1,10 @@ +use bitwarden_api_api::models::CipherCardModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -55,3 +56,18 @@ impl KeyDecryptable for Card { }) } } + +impl TryFrom for Card { + type Error = Error; + + fn try_from(card: CipherCardModel) -> Result { + Ok(Self { + cardholder_name: EncString::try_from_optional(card.cardholder_name)?, + exp_month: EncString::try_from_optional(card.exp_month)?, + exp_year: EncString::try_from_optional(card.exp_year)?, + code: EncString::try_from_optional(card.code)?, + brand: EncString::try_from_optional(card.brand)?, + number: EncString::try_from_optional(card.number)?, + }) + } +} diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index b95a2f090..e44a3757a 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::CipherDetailsResponseModel; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -12,7 +13,7 @@ use super::{ use crate::{ client::encryption_settings::EncryptionSettings, crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, vault::password_history, }; @@ -332,3 +333,68 @@ impl LocateKey for CipherView { enc.get_key(&self.organization_id) } } + +impl TryFrom for Cipher { + type Error = Error; + + fn try_from(cipher: CipherDetailsResponseModel) -> Result { + Ok(Self { + id: cipher.id, + organization_id: cipher.organization_id, + folder_id: cipher.folder_id, + collection_ids: cipher.collection_ids.unwrap_or_default(), + name: EncString::try_from_optional(cipher.name)?.ok_or(Error::MissingFields)?, + notes: EncString::try_from_optional(cipher.notes)?, + r#type: cipher.r#type.ok_or(Error::MissingFields)?.into(), + login: cipher.login.map(|l| (*l).try_into()).transpose()?, + identity: cipher.identity.map(|i| (*i).try_into()).transpose()?, + card: cipher.card.map(|c| (*c).try_into()).transpose()?, + secure_note: cipher.secure_note.map(|s| (*s).try_into()).transpose()?, + favorite: cipher.favorite.unwrap_or(false), + reprompt: cipher + .reprompt + .map(|r| r.into()) + .unwrap_or(CipherRepromptType::None), + organization_use_totp: cipher.organization_use_totp.unwrap_or(true), + edit: cipher.edit.unwrap_or(true), + view_password: cipher.view_password.unwrap_or(true), + local_data: None, // Not sent from server + attachments: cipher + .attachments + .map(|a| a.into_iter().map(|a| a.try_into()).collect()) + .transpose()?, + fields: cipher + .fields + .map(|f| f.into_iter().map(|f| f.try_into()).collect()) + .transpose()?, + password_history: cipher + .password_history + .map(|p| p.into_iter().map(|p| p.try_into()).collect()) + .transpose()?, + creation_date: cipher.creation_date.ok_or(Error::MissingFields)?.parse()?, + deleted_date: cipher.deleted_date.map(|d| d.parse()).transpose()?, + revision_date: cipher.revision_date.ok_or(Error::MissingFields)?.parse()?, + key: EncString::try_from_optional(cipher.key)?, + }) + } +} + +impl From for CipherType { + fn from(t: bitwarden_api_api::models::CipherType) -> Self { + match t { + bitwarden_api_api::models::CipherType::Variant1 => CipherType::Login, + bitwarden_api_api::models::CipherType::Variant2 => CipherType::SecureNote, + bitwarden_api_api::models::CipherType::Variant3 => CipherType::Card, + bitwarden_api_api::models::CipherType::Variant4 => CipherType::Identity, + } + } +} + +impl From for CipherRepromptType { + fn from(t: bitwarden_api_api::models::CipherRepromptType) -> Self { + match t { + bitwarden_api_api::models::CipherRepromptType::Variant0 => CipherRepromptType::None, + bitwarden_api_api::models::CipherRepromptType::Variant1 => CipherRepromptType::Password, + } + } +} diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 13f7dc9bb..dee71872b 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::CipherFieldModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -5,7 +6,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use super::linked_id::LinkedIdType; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] @@ -61,3 +62,30 @@ impl KeyDecryptable for Field { }) } } + +impl TryFrom for Field { + type Error = Error; + + fn try_from(model: CipherFieldModel) -> Result { + Ok(Self { + name: EncString::try_from_optional(model.name)?, + value: EncString::try_from_optional(model.value)?, + r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + linked_id: model + .linked_id + .map(|id| (id as u32).try_into()) + .transpose()?, + }) + } +} + +impl From for FieldType { + fn from(model: bitwarden_api_api::models::FieldType) -> Self { + match model { + bitwarden_api_api::models::FieldType::Variant0 => FieldType::Text, + bitwarden_api_api::models::FieldType::Variant1 => FieldType::Hidden, + bitwarden_api_api::models::FieldType::Variant2 => FieldType::Boolean, + bitwarden_api_api::models::FieldType::Variant3 => FieldType::Linked, + } + } +} diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index d40991866..922d2aee6 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,9 +1,10 @@ +use bitwarden_api_api::models::CipherIdentityModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -103,3 +104,30 @@ impl KeyDecryptable for Identity { }) } } + +impl TryFrom for Identity { + type Error = Error; + + fn try_from(identity: CipherIdentityModel) -> Result { + Ok(Self { + title: EncString::try_from_optional(identity.title)?, + first_name: EncString::try_from_optional(identity.first_name)?, + middle_name: EncString::try_from_optional(identity.middle_name)?, + last_name: EncString::try_from_optional(identity.last_name)?, + address1: EncString::try_from_optional(identity.address1)?, + address2: EncString::try_from_optional(identity.address2)?, + address3: EncString::try_from_optional(identity.address3)?, + city: EncString::try_from_optional(identity.city)?, + state: EncString::try_from_optional(identity.state)?, + postal_code: EncString::try_from_optional(identity.postal_code)?, + country: EncString::try_from_optional(identity.country)?, + company: EncString::try_from_optional(identity.company)?, + email: EncString::try_from_optional(identity.email)?, + phone: EncString::try_from_optional(identity.phone)?, + ssn: EncString::try_from_optional(identity.ssn)?, + username: EncString::try_from_optional(identity.username)?, + passport_number: EncString::try_from_optional(identity.passport_number)?, + license_number: EncString::try_from_optional(identity.license_number)?, + }) + } +} diff --git a/crates/bitwarden/src/vault/cipher/linked_id.rs b/crates/bitwarden/src/vault/cipher/linked_id.rs index 692d59b77..6fb676dfe 100644 --- a/crates/bitwarden/src/vault/cipher/linked_id.rs +++ b/crates/bitwarden/src/vault/cipher/linked_id.rs @@ -10,6 +10,7 @@ pub enum LinkedIdType { Identity(IdentityLinkedIdType), } +use crate::error::{Error, Result}; #[cfg(feature = "mobile")] use crate::UniffiCustomTypeConverter; #[cfg(feature = "mobile")] @@ -73,6 +74,43 @@ pub enum IdentityLinkedIdType { FullName = 418, } +impl TryFrom for LinkedIdType { + type Error = Error; + + fn try_from(value: u32) -> Result { + match value { + 100 => Ok(LinkedIdType::Login(LoginLinkedIdType::Username)), + 101 => Ok(LinkedIdType::Login(LoginLinkedIdType::Password)), + 300 => Ok(LinkedIdType::Card(CardLinkedIdType::CardholderName)), + 301 => Ok(LinkedIdType::Card(CardLinkedIdType::ExpMonth)), + 302 => Ok(LinkedIdType::Card(CardLinkedIdType::ExpYear)), + 303 => Ok(LinkedIdType::Card(CardLinkedIdType::Code)), + 304 => Ok(LinkedIdType::Card(CardLinkedIdType::Brand)), + 305 => Ok(LinkedIdType::Card(CardLinkedIdType::Number)), + 400 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Title)), + 401 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::MiddleName)), + 402 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address1)), + 403 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address2)), + 404 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Address3)), + 405 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::City)), + 406 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::State)), + 407 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::PostalCode)), + 408 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Country)), + 409 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Company)), + 410 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Email)), + 411 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Phone)), + 412 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Ssn)), + 413 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::Username)), + 414 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::PassportNumber)), + 415 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::LicenseNumber)), + 416 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FirstName)), + 417 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::LastName)), + 418 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FullName)), + _ => Err(Error::MissingFields), + } + } +} + #[cfg(test)] mod tests { diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 7a8e18411..da71f963f 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::{CipherLoginModel, CipherLoginUriModel}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -5,7 +6,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] @@ -106,3 +107,48 @@ impl KeyDecryptable for Login { }) } } + +impl TryFrom for Login { + type Error = Error; + + fn try_from(login: CipherLoginModel) -> Result { + Ok(Self { + username: EncString::try_from_optional(login.username)?, + password: EncString::try_from_optional(login.password)?, + password_revision_date: login + .password_revision_date + .map(|d| d.parse()) + .transpose()?, + uris: login + .uris + .map(|v| v.into_iter().map(|u| u.try_into()).collect()) + .transpose()?, + totp: EncString::try_from_optional(login.totp)?, + autofill_on_page_load: login.autofill_on_page_load, + }) + } +} + +impl TryFrom for LoginUri { + type Error = Error; + + fn try_from(uri: CipherLoginUriModel) -> Result { + Ok(Self { + uri: EncString::try_from_optional(uri.uri)?, + r#match: uri.r#match.map(|m| m.into()), + }) + } +} + +impl From for UriMatchType { + fn from(value: bitwarden_api_api::models::UriMatchType) -> Self { + match value { + bitwarden_api_api::models::UriMatchType::Variant0 => Self::Domain, + bitwarden_api_api::models::UriMatchType::Variant1 => Self::Host, + bitwarden_api_api::models::UriMatchType::Variant2 => Self::StartsWith, + bitwarden_api_api::models::UriMatchType::Variant3 => Self::Exact, + bitwarden_api_api::models::UriMatchType::Variant4 => Self::RegularExpression, + bitwarden_api_api::models::UriMatchType::Variant5 => Self::Never, + } + } +} diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 0c7b4c799..5fbb81811 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,10 +1,11 @@ +use bitwarden_api_api::models::CipherSecureNoteModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] @@ -43,3 +44,21 @@ impl KeyDecryptable for SecureNote { }) } } + +impl TryFrom for SecureNote { + type Error = Error; + + fn try_from(model: CipherSecureNoteModel) -> Result { + Ok(Self { + r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + }) + } +} + +impl From for SecureNoteType { + fn from(model: bitwarden_api_api::models::SecureNoteType) -> Self { + match model { + bitwarden_api_api::models::SecureNoteType::Variant0 => SecureNoteType::Generic, + } + } +} diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 58492ef17..11983dca5 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::CollectionDetailsResponseModel; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -5,7 +6,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -59,3 +60,18 @@ impl KeyDecryptable for Collection { }) } } + +impl TryFrom for Collection { + type Error = Error; + + fn try_from(collection: CollectionDetailsResponseModel) -> Result { + Ok(Collection { + id: collection.id.ok_or(Error::MissingFields)?, + organization_id: collection.organization_id.ok_or(Error::MissingFields)?, + name: collection.name.ok_or(Error::MissingFields)?.parse()?, + external_id: collection.external_id, + hide_passwords: collection.hide_passwords.unwrap_or(false), + read_only: collection.read_only.unwrap_or(false), + }) + } +} diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index f9ae06055..d04bf3110 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::FolderResponseModel; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -5,7 +6,7 @@ use uuid::Uuid; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -47,3 +48,15 @@ impl KeyDecryptable for Folder { }) } } + +impl TryFrom for Folder { + type Error = Error; + + fn try_from(folder: FolderResponseModel) -> Result { + Ok(Folder { + id: folder.id.ok_or(Error::MissingFields)?, + name: EncString::try_from_optional(folder.name)?.ok_or(Error::MissingFields)?, + revision_date: folder.revision_date.ok_or(Error::MissingFields)?.parse()?, + }) + } +} diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index ca9b12c1c..6ac43a4d0 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -3,6 +3,7 @@ mod collection; mod folder; mod password_history; mod send; +#[cfg(feature = "mobile")] mod totp; pub use cipher::{Cipher, CipherListView, CipherView}; @@ -10,5 +11,7 @@ pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; pub use send::{Send, SendListView, SendView}; +#[cfg(feature = "mobile")] pub(crate) use totp::generate_totp; +#[cfg(feature = "mobile")] pub use totp::TotpResponse; diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index da6a4b19e..786c7a8f2 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,10 +1,11 @@ +use bitwarden_api_api::models::CipherPasswordHistoryModel; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -42,3 +43,14 @@ impl KeyDecryptable for PasswordHistory { }) } } + +impl TryFrom for PasswordHistory { + type Error = Error; + + fn try_from(model: CipherPasswordHistoryModel) -> Result { + Ok(Self { + password: model.password.parse()?, + last_used_date: model.last_used_date.parse()?, + }) + } +} diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 3aec03639..255f6b9fd 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,3 +1,4 @@ +use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -9,7 +10,7 @@ use crate::{ derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, }, - error::Result, + error::{Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -264,6 +265,64 @@ impl KeyEncryptable for SendView { } } +impl TryFrom for Send { + type Error = Error; + + fn try_from(send: SendResponseModel) -> Result { + Ok(Send { + id: send.id.ok_or(Error::MissingFields)?, + access_id: send.access_id.ok_or(Error::MissingFields)?, + name: send.name.ok_or(Error::MissingFields)?.parse()?, + notes: EncString::try_from_optional(send.notes)?, + key: send.key.ok_or(Error::MissingFields)?.parse()?, + password: send.password, + r#type: send.r#type.ok_or(Error::MissingFields)?.into(), + file: send.file.map(|f| (*f).try_into()).transpose()?, + text: send.text.map(|t| (*t).try_into()).transpose()?, + max_access_count: send.max_access_count.map(|s| s as u32), + access_count: send.access_count.ok_or(Error::MissingFields)? as u32, + disabled: send.disabled.unwrap_or(false), + hide_email: send.hide_email.unwrap_or(false), + revision_date: send.revision_date.ok_or(Error::MissingFields)?.parse()?, + deletion_date: send.deletion_date.ok_or(Error::MissingFields)?.parse()?, + expiration_date: send.expiration_date.map(|s| s.parse()).transpose()?, + }) + } +} + +impl From for SendType { + fn from(t: bitwarden_api_api::models::SendType) -> Self { + match t { + bitwarden_api_api::models::SendType::Variant0 => SendType::Text, + bitwarden_api_api::models::SendType::Variant1 => SendType::File, + } + } +} + +impl TryFrom for SendFile { + type Error = Error; + + fn try_from(file: SendFileModel) -> Result { + Ok(SendFile { + id: file.id.ok_or(Error::MissingFields)?, + file_name: file.file_name.ok_or(Error::MissingFields)?.parse()?, + size: file.size.ok_or(Error::MissingFields)?.to_string(), + size_name: file.size_name.ok_or(Error::MissingFields)?, + }) + } +} + +impl TryFrom for SendText { + type Error = Error; + + fn try_from(text: SendTextModel) -> Result { + Ok(SendText { + text: EncString::try_from_optional(text.text)?, + hidden: text.hidden.unwrap_or(false), + }) + } +} + #[cfg(test)] mod tests { use super::Send; diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index 1fcd15414..53b9b609e 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -3,6 +3,7 @@ use bitwarden::{ ApiKeyLoginRequest, PasswordLoginRequest, TwoFactorEmailRequest, TwoFactorProvider, TwoFactorRequest, }, + platform::SyncRequest, Client, }; use bitwarden_cli::text_prompt_when_none; @@ -80,6 +81,13 @@ pub(crate) async fn login_password(mut client: Client, email: Option) -> debug!("{:?}", result); } + let res = client + .sync(&SyncRequest { + exclude_subdomains: Some(true), + }) + .await?; + info!("{:#?}", res); + Ok(()) } From ff5bb1f6fb9ea4b775502fb756e60455bf73b383 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 12 Dec 2023 16:25:59 +0100 Subject: [PATCH 122/378] Rework the WASM code (#44) --- .github/workflows/generate_schemas.yml | 2 +- .gitignore | 10 +- Cargo.lock | 2 + crates/bitwarden-wasm/Cargo.toml | 7 +- crates/bitwarden-wasm/README.md | 23 + crates/bitwarden-wasm/build.sh | 23 + crates/bitwarden/Cargo.toml | 4 +- .../sdk-client}/.gitignore | 0 languages/js/sdk-client/package-lock.json | 616 +++ languages/js/sdk-client/package.json | 20 + .../index.ts => js/sdk-client/src/client.ts} | 75 +- languages/js/sdk-client/src/lib.ts | 2 + .../sdk-client/src}/logging_level.ts | 0 languages/js/sdk-client/tsconfig.json | 12 + languages/js/wasm/.gitignore | 6 + languages/js/wasm/index.js | 25 + languages/js/wasm/package.json | 22 + languages/js_webassembly/index.html | 10 - languages/js_webassembly/index.ts | 26 - languages/js_webassembly/package-lock.json | 4195 ----------------- languages/js_webassembly/package.json | 15 - languages/js_webassembly/styles.css | 7 - languages/js_webassembly/tsconfig.json | 11 - languages/js_webassembly/webpack.config.js | 57 - support/scripts/schemas.ts | 2 +- 25 files changed, 807 insertions(+), 4365 deletions(-) create mode 100644 crates/bitwarden-wasm/README.md create mode 100755 crates/bitwarden-wasm/build.sh rename languages/{js_webassembly => js/sdk-client}/.gitignore (100%) create mode 100644 languages/js/sdk-client/package-lock.json create mode 100644 languages/js/sdk-client/package.json rename languages/{js_webassembly/bitwarden_client/index.ts => js/sdk-client/src/client.ts} (62%) create mode 100644 languages/js/sdk-client/src/lib.ts rename languages/{js_webassembly/bitwarden_client => js/sdk-client/src}/logging_level.ts (100%) create mode 100644 languages/js/sdk-client/tsconfig.json create mode 100644 languages/js/wasm/.gitignore create mode 100644 languages/js/wasm/index.js create mode 100644 languages/js/wasm/package.json delete mode 100644 languages/js_webassembly/index.html delete mode 100644 languages/js_webassembly/index.ts delete mode 100644 languages/js_webassembly/package-lock.json delete mode 100644 languages/js_webassembly/package.json delete mode 100644 languages/js_webassembly/styles.css delete mode 100644 languages/js_webassembly/tsconfig.json delete mode 100644 languages/js_webassembly/webpack.config.js diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index efd7dd68d..807da7520 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -40,7 +40,7 @@ jobs: uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: schemas.ts - path: ${{ github.workspace }}/languages/js_webassembly/bitwarden_client/schemas.ts + path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact diff --git a/.gitignore b/.gitignore index 6ddcd3205..23cbaba20 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build/ bld/ [Bb]in/ [Oo]bj/ +*.wasm # Binary files *.dylib @@ -42,6 +43,7 @@ crates/bitwarden-napi/sdk-napi.*.node # Complied TypeScript client crates/bitwarden-napi/dist +languages/js/sdk-client/dist/ # Uniffi languages/swift/BitwardenFFI.xcframework @@ -52,11 +54,11 @@ languages/kotlin/sdk/src/main/java/com/bitwarden/sdk/bitwarden_uniffi.kt languages/kotlin/sdk/src/main/java/com/bitwarden/core/bitwarden.kt # Schemas -support/schemas crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts -languages/csharp/Bitwarden.Sdk/schemas.cs -languages/js_webassembly/bitwarden_client/schemas.ts -languages/python/bitwarden_sdk/schemas.py languages/cpp/include/schemas.hpp +languages/csharp/Bitwarden.Sdk/schemas.cs languages/go/schema.go languages/java/src/main/java/com/bitwarden/sdk/schema +languages/js/sdk-client/src/schemas.ts +languages/python/bitwarden_sdk/schemas.py +support/schemas diff --git a/Cargo.lock b/Cargo.lock index 0b89bd2e0..73609e295 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -647,8 +647,10 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.48.5", ] diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index dc5bf9ba5..176edeaa9 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [lib] -crate-type = ["cdylib", "rlib"] +crate-type = ["cdylib"] [dependencies] console_error_panic_hook = "0.1.7" @@ -16,7 +16,10 @@ serde = { version = "1.0.193", features = ["derive"] } wasm-bindgen = { version = "0.2.89", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.39" -bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } +bitwarden-json = { path = "../bitwarden-json", features = [ + "secrets", + "internal", +] } [dev-dependencies] wasm-bindgen-test = "0.3.39" diff --git a/crates/bitwarden-wasm/README.md b/crates/bitwarden-wasm/README.md new file mode 100644 index 000000000..6fa8870f2 --- /dev/null +++ b/crates/bitwarden-wasm/README.md @@ -0,0 +1,23 @@ +# Bitwarden-wasm + +Requirements: + +- `wasm32-unknown-unknown` rust target. +- `wasm-bindgen-cli` installed. +- `binaryen` installed for `wasm-opt` and `wasm2js`. + +```bash +rustup target add wasm32-unknown-unknown +cargo install -f wasm-bindgen-cli +brew install binaryen +``` + +#### Build + +```bash +# dev +./build.sh + +# release +./build.sh -r +``` diff --git a/crates/bitwarden-wasm/build.sh b/crates/bitwarden-wasm/build.sh new file mode 100755 index 000000000..ae32c775d --- /dev/null +++ b/crates/bitwarden-wasm/build.sh @@ -0,0 +1,23 @@ +# Move to the root of the repository +cd "$(dirname "$0")" +cd ../../ + +if [ "$1" != "-r" ]; then + # Dev + cargo build -p bitwarden -p bitwarden-wasm --target wasm32-unknown-unknown --features wasm-bindgen + wasm-bindgen --target bundler --out-dir languages/js/wasm ./target/wasm32-unknown-unknown/debug/bitwarden_wasm.wasm + wasm-bindgen --target nodejs --out-dir languages/js/wasm/node ./target/wasm32-unknown-unknown/debug/bitwarden_wasm.wasm +else + # Release + cargo build -p bitwarden -p bitwarden-wasm --target wasm32-unknown-unknown --features wasm-bindgen --release + wasm-bindgen --target bundler --out-dir languages/js/wasm ./target/wasm32-unknown-unknown/release/bitwarden_wasm.wasm + wasm-bindgen --target nodejs --out-dir languages/js/wasm/node ./target/wasm32-unknown-unknown/release/bitwarden_wasm.wasm +fi + +# Optimize size +wasm-opt -Os ./languages/js/wasm/bitwarden_wasm_bg.wasm -o ./languages/js/wasm/bitwarden_wasm_bg.wasm +wasm-opt -Os ./languages/js/wasm/node/bitwarden_wasm_bg.wasm -o ./languages/js/wasm/node/bitwarden_wasm_bg.wasm + +# Transpile to JS +wasm2js ./languages/js/wasm/bitwarden_wasm_bg.wasm -o ./languages/js/wasm/bitwarden_wasm_bg.wasm.js +npx terser ./languages/js/wasm/bitwarden_wasm_bg.wasm.js -o ./languages/js/wasm/bitwarden_wasm_bg.wasm.js diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 8f7c1f4d1..a9cafc4da 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -19,6 +19,8 @@ secrets = [] # Secrets manager API internal = [] # Internal testing methods mobile = ["uniffi", "internal"] # Mobile-specific features +wasm-bindgen = ["chrono/wasmbind"] + [dependencies] aes = ">=0.8.2, <0.9" argon2 = { version = ">=0.5.0, <0.6", features = [ @@ -46,7 +48,7 @@ pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = ["json"] } rsa = ">=0.9.2, <0.10" -schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } +schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" serde_qs = ">=0.12.0, <0.13" diff --git a/languages/js_webassembly/.gitignore b/languages/js/sdk-client/.gitignore similarity index 100% rename from languages/js_webassembly/.gitignore rename to languages/js/sdk-client/.gitignore diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json new file mode 100644 index 000000000..ff252e970 --- /dev/null +++ b/languages/js/sdk-client/package-lock.json @@ -0,0 +1,616 @@ +{ + "name": "@bitwarden/sdk-client", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bitwarden/sdk-client", + "devDependencies": { + "@types/node": "^18.15.11", + "rimraf": "^5.0.0", + "typescript": "^5.0.3" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/node": { + "version": "18.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", + "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", + "dev": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", + "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.0", + "minipass": "^5.0.0", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.0.tgz", + "integrity": "sha512-DiEwVPqsieUzZBNxQ2cxznmFzfg/AMgJUjYw5xl6rSmCxAQXECcbSdwcLM6Ds6T09+SBfSNCGPhYUoQ96P4h7A==", + "dev": true, + "dependencies": { + "cliui": "^7.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/lru-cache": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", + "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/minimatch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", + "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "dev": true, + "dependencies": { + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", + "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "dev": true, + "dependencies": { + "glob": "^10.0.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", + "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + } + }, + "dependencies": { + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@types/node": { + "version": "18.16.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", + "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "glob": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", + "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.0", + "minipass": "^5.0.0", + "path-scurry": "^1.7.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jackspeak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.0.tgz", + "integrity": "sha512-DiEwVPqsieUzZBNxQ2cxznmFzfg/AMgJUjYw5xl6rSmCxAQXECcbSdwcLM6Ds6T09+SBfSNCGPhYUoQ96P4h7A==", + "dev": true, + "requires": { + "@pkgjs/parseargs": "^0.11.0", + "cliui": "^7.0.4" + } + }, + "lru-cache": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", + "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "dev": true + }, + "minimatch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", + "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-scurry": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", + "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "dev": true, + "requires": { + "lru-cache": "^9.0.0", + "minipass": "^5.0.0" + } + }, + "rimraf": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", + "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "dev": true, + "requires": { + "glob": "^10.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", + "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } +} diff --git a/languages/js/sdk-client/package.json b/languages/js/sdk-client/package.json new file mode 100644 index 000000000..9e4998b4f --- /dev/null +++ b/languages/js/sdk-client/package.json @@ -0,0 +1,20 @@ +{ + "name": "@bitwarden/sdk-client", + "exports": { + ".": { + "types": "./dist/src/lib.d.ts", + "default": "./dist/src/lib.js" + } + }, + "main": "dist/src/lib.js", + "types": "dist/src/lib.d.ts", + "scripts": { + "build": "npm run clean && tsc", + "clean": "rimraf dist" + }, + "devDependencies": { + "@types/node": "^18.15.11", + "rimraf": "^5.0.0", + "typescript": "^5.0.3" + } +} diff --git a/languages/js_webassembly/bitwarden_client/index.ts b/languages/js/sdk-client/src/client.ts similarity index 62% rename from languages/js_webassembly/bitwarden_client/index.ts rename to languages/js/sdk-client/src/client.ts index 3f858fd39..f77ba1420 100644 --- a/languages/js_webassembly/bitwarden_client/index.ts +++ b/languages/js/sdk-client/src/client.ts @@ -1,8 +1,6 @@ -import * as rust from "../pkg/bitwarden_wasm"; -import { LoggingLevel } from "./logging_level"; import { - ClientSettings, Convert, + ResponseForFingerprintResponse, ResponseForPasswordLoginResponse, ResponseForSecretIdentifiersResponse, ResponseForSecretResponse, @@ -11,20 +9,28 @@ import { ResponseForUserAPIKeyResponse, } from "./schemas"; +interface BitwardenSDKClient { + run_command(js_input: string): Promise; +} + export class BitwardenClient { - client: rust.BitwardenClient; + client: BitwardenSDKClient; - constructor(settings?: ClientSettings, logging_level?: LoggingLevel) { - const settings_json = settings == null ? null : Convert.clientSettingsToJson(settings); - this.client = new rust.BitwardenClient(settings_json, logging_level ?? LoggingLevel.Info); + constructor(client: BitwardenSDKClient) { + this.client = client; } - async login(email: string, password: string): Promise { + async login(email: string, password: string, pbkdf_iter: number): Promise { const response = await this.client.run_command( Convert.commandToJson({ passwordLogin: { email: email, password: password, + kdf: { + pBKDF2: { + iterations: pbkdf_iter, + } + }, }, }) ); @@ -48,14 +54,11 @@ export class BitwardenClient { return Convert.toResponseForUserAPIKeyResponse(response); } - - async sync( - excludeSubdomains: boolean = false - ): Promise { + async sync(excludeSubdomains: boolean = false): Promise { const response = await this.client.run_command( Convert.commandToJson({ sync: { - excludeSubdomains + excludeSubdomains, }, }) ); @@ -63,25 +66,32 @@ export class BitwardenClient { return Convert.toResponseForSyncResponse(response); } - secrets(): SecretsClient { - return new SecretsClient(this.client); - } + async fingerprint(fingerprintMaterial: string, publicKey: string): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + fingerprint: { + fingerprintMaterial: fingerprintMaterial, + publicKey: publicKey, + } + }) + ) + + return Convert.toResponseForFingerprintResponse(response).data.fingerprint; + }; } export class SecretsClient { - client: rust.BitwardenClient; + client: BitwardenSDKClient; - constructor(client: rust.BitwardenClient) { + constructor(client: BitwardenSDKClient) { this.client = client; } - async get( - id: string - ): Promise { + async get(id: string): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - get: { id } + get: { id }, }, }) ); @@ -93,12 +103,12 @@ export class SecretsClient { key: string, note: string, organizationId: string, - value: string, + value: string ): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - create: { key, note, organizationId, value } + create: { key, note, organizationId, value }, }, }) ); @@ -106,13 +116,11 @@ export class SecretsClient { return Convert.toResponseForSecretResponse(response); } - async list( - organizationId: string - ): Promise { + async list(organizationId: string): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - list: { organizationId } + list: { organizationId }, }, }) ); @@ -125,12 +133,12 @@ export class SecretsClient { key: string, note: string, organizationId: string, - value: string, + value: string ): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - update: { id, key, note, organizationId, value } + update: { id, key, note, organizationId, value }, }, }) ); @@ -138,18 +146,15 @@ export class SecretsClient { return Convert.toResponseForSecretResponse(response); } - async delete( - ids: string[] - ): Promise { + async delete(ids: string[]): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - delete: { ids } + delete: { ids }, }, }) ); return Convert.toResponseForSecretsDeleteResponse(response); } - } diff --git a/languages/js/sdk-client/src/lib.ts b/languages/js/sdk-client/src/lib.ts new file mode 100644 index 000000000..7fd93ce86 --- /dev/null +++ b/languages/js/sdk-client/src/lib.ts @@ -0,0 +1,2 @@ +export * from "./client"; +export * from "./schemas"; diff --git a/languages/js_webassembly/bitwarden_client/logging_level.ts b/languages/js/sdk-client/src/logging_level.ts similarity index 100% rename from languages/js_webassembly/bitwarden_client/logging_level.ts rename to languages/js/sdk-client/src/logging_level.ts diff --git a/languages/js/sdk-client/tsconfig.json b/languages/js/sdk-client/tsconfig.json new file mode 100644 index 000000000..453623d5f --- /dev/null +++ b/languages/js/sdk-client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "outDir": "./dist/", + "module": "esnext", + "target": "es5", + "moduleResolution": "node", + "sourceMap": true, + "composite": true, + "declarationMap": true + }, + "include": ["./src/**/*"], +} diff --git a/languages/js/wasm/.gitignore b/languages/js/wasm/.gitignore new file mode 100644 index 000000000..c4f6a47f4 --- /dev/null +++ b/languages/js/wasm/.gitignore @@ -0,0 +1,6 @@ +bitwarden_wasm_bg.js +bitwarden_wasm_bg.wasm +bitwarden_wasm_bg.wasm.d.ts +bitwarden_wasm_bg.wasm.js +bitwarden_wasm.d.ts +bitwarden_wasm.js diff --git a/languages/js/wasm/index.js b/languages/js/wasm/index.js new file mode 100644 index 000000000..c2b512005 --- /dev/null +++ b/languages/js/wasm/index.js @@ -0,0 +1,25 @@ +// https://stackoverflow.com/a/47880734 +const supported = (() => { + try { + if (typeof WebAssembly === "object" + && typeof WebAssembly.instantiate === "function") { + const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)); + if (module instanceof WebAssembly.Module) + return new WebAssembly.Instance(module) instanceof WebAssembly.Instance; + } + } catch (e) { + } + return false; +})(); + +let wasm; + +if (supported) { + wasm = await import('./bitwarden_wasm_bg.wasm'); +} else { + wasm = await import('./bitwarden_wasm_bg.wasm.js'); +} + +import { __wbg_set_wasm } from "./bitwarden_wasm_bg.js"; +__wbg_set_wasm(wasm); +export * from "./bitwarden_wasm_bg.js"; diff --git a/languages/js/wasm/package.json b/languages/js/wasm/package.json new file mode 100644 index 000000000..26379c9a6 --- /dev/null +++ b/languages/js/wasm/package.json @@ -0,0 +1,22 @@ +{ + "name": "@bitwarden/sdk-wasm", + "version": "0.1.0", + "files": [ + "bitwarden_wasm_bg.js", + "bitwarden_wasm_bg.wasm", + "bitwarden_wasm.d.ts", + "bitwarden_wasm.js", + "index.js", + "node/bitwarden_wasm_bg.wasm.d.ts", + "node/bitwarden_wasm_bg.wasm", + "node/bitwarden_wasm.d.ts", + "node/bitwarden_wasm.js" + ], + "main": "node/bitwarden_wasm.js", + "module": "index.js", + "types": "bitwarden_wasm.d.ts", + "sideEffects": [ + "./bitwarden_wasm.js", + "./snippets/*" + ] +} diff --git a/languages/js_webassembly/index.html b/languages/js_webassembly/index.html deleted file mode 100644 index 661517934..000000000 --- a/languages/js_webassembly/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/languages/js_webassembly/index.ts b/languages/js_webassembly/index.ts deleted file mode 100644 index 047a815bb..000000000 --- a/languages/js_webassembly/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { LoggingLevel } from "./bitwarden_client/logging_level"; -import { DeviceType } from "./bitwarden_client/schemas"; - -import("./bitwarden_client").then(async (module) => { - const client = new module.BitwardenClient({ - apiUrl: "http://localhost:8081/api", - identityUrl: "http://localhost:8081/identity", - deviceType: DeviceType.SDK, - userAgent: "Bitwarden JS SDK", - }, LoggingLevel.Debug); - const result = await client.login("test@bitwarden.com", "asdfasdf"); - console.log(`auth result success: ${result.success}`); - - const apikeyResponse = await client.getUserApiKey("asdfasdf"); - console.log(`user API key: ${apikeyResponse.data.apiKey}`); - - const sync = await client.sync(); - console.log("Sync result", sync); - - const org_id = sync.data.profile.organizations[0].id; - - const secret = await client.secrets().create("TEST_KEY", "This is a test secret", org_id, "Secret1234!"); - console.log("New secret: ", secret.data); - - await client.secrets().delete([secret.data.id]); -}); diff --git a/languages/js_webassembly/package-lock.json b/languages/js_webassembly/package-lock.json deleted file mode 100644 index c4a2126e6..000000000 --- a/languages/js_webassembly/package-lock.json +++ /dev/null @@ -1,4195 +0,0 @@ -{ - "name": "js_webassembly", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "devDependencies": { - "html-webpack-plugin": "5.5.3", - "text-encoding": "0.7.0", - "ts-loader": "9.5.1", - "wasm-pack": "0.12.1", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-dev-server": "4.15.1" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", - "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.20", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", - "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.44.8", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz", - "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.41", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", - "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.10.tgz", - "integrity": "sha512-y6PJDYN4xYBxwd22l+OVH35N+1fCYWiuC3aiP2SlXVE6Lo7SS+rSx9r89hLxrP4pn6n1lBGhHJ12pj3F3Mpttw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.9.10", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", - "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", - "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", - "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", - "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", - "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-opt": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6", - "@webassemblyjs/wast-printer": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", - "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", - "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-buffer": "1.11.6", - "@webassemblyjs/wasm-gen": "1.11.6", - "@webassemblyjs/wasm-parser": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", - "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", - "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", - "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/binary-install": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/binary-install/-/binary-install-1.1.0.tgz", - "integrity": "sha512-rkwNGW+3aQVSZoD0/o3mfPN6Yxh3Id0R/xzTVBVVpGNlVz8EGwusksxRlbk/A5iKTZt9zkMn3qIqmAt3vpfbzg==", - "dev": true, - "dependencies": { - "axios": "^0.26.1", - "rimraf": "^3.0.2", - "tar": "^6.1.11" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/bonjour-service": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", - "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", - "dev": true, - "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001566", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", - "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.601", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.601.tgz", - "integrity": "sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.15.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", - "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", - "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", - "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", - "integrity": "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", - "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/launch-editor": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.1.tgz", - "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-inspect": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", - "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", - "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/spdy-transport/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/spdy/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/spdy/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.24.0.tgz", - "integrity": "sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.9", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", - "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.17", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.16.8" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-encoding": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz", - "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==", - "deprecated": "no longer maintained", - "dev": true - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", - "dev": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wasm-pack": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/wasm-pack/-/wasm-pack-0.12.1.tgz", - "integrity": "sha512-dIyKWUumPFsGohdndZjDXRFaokUT/kQS+SavbbiXVAvA/eN4riX5QNdB6AhXQx37zNxluxQkuixZUgJ8adKjOg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "binary-install": "^1.0.1" - }, - "bin": { - "wasm-pack": "run.js" - } - }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/webpack": { - "version": "5.89.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", - "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.0", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.7", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.15.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", - "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } -} diff --git a/languages/js_webassembly/package.json b/languages/js_webassembly/package.json deleted file mode 100644 index d5d7342df..000000000 --- a/languages/js_webassembly/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "scripts": { - "build": "wasm-pack build ../../crates/bitwarden-wasm --out-dir ../../languages/js_webassembly/pkg --dev", - "build:watch": "npm run build && webpack serve" - }, - "devDependencies": { - "html-webpack-plugin": "5.5.3", - "text-encoding": "0.7.0", - "ts-loader": "9.5.1", - "wasm-pack": "0.12.1", - "webpack": "5.89.0", - "webpack-cli": "5.1.4", - "webpack-dev-server": "4.15.1" - } -} diff --git a/languages/js_webassembly/styles.css b/languages/js_webassembly/styles.css deleted file mode 100644 index 4c336b64d..000000000 --- a/languages/js_webassembly/styles.css +++ /dev/null @@ -1,7 +0,0 @@ -html, -body { - height: 400px; - width: 200px; - margin: 0; - box-sizing: border-box; -} diff --git a/languages/js_webassembly/tsconfig.json b/languages/js_webassembly/tsconfig.json deleted file mode 100644 index ac51138c0..000000000 --- a/languages/js_webassembly/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./dist/", - "module": "es2020", - "target": "es5", - "jsx": "react", - "allowJs": true, - "moduleResolution": "node", - "sourceMap": true - } -} diff --git a/languages/js_webassembly/webpack.config.js b/languages/js_webassembly/webpack.config.js deleted file mode 100644 index 430df86f6..000000000 --- a/languages/js_webassembly/webpack.config.js +++ /dev/null @@ -1,57 +0,0 @@ -const path = require("path"); -const HtmlWebpackPlugin = require("html-webpack-plugin"); -const webpack = require("webpack"); - -module.exports = { - entry: "./index.ts", - module: { - rules: [ - { - test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/, - }, - { - test: /\.wasm$/, - type: "webassembly/sync", - }, - ], - }, - resolve: { - extensions: [".tsx", ".ts", ".js"], - }, - output: { - path: path.resolve(__dirname, "dist"), - filename: "index.js", - }, - plugins: [ - new HtmlWebpackPlugin(), - // Have this example work in Edge which doesn't ship `TextEncoder` or - // `TextDecoder` at this time. - new webpack.ProvidePlugin({ - TextDecoder: ["text-encoding", "TextDecoder"], - TextEncoder: ["text-encoding", "TextEncoder"], - }), - ], - experiments: { - syncWebAssembly: true, - }, - devServer: { - proxy: { - "/api": { - target: "http://localhost:4000", - pathRewrite: { "^/api": "" }, - secure: false, - changeOrigin: true, - }, - "/identity": { - target: "http://localhost:33656", - pathRewrite: { "^/identity": "" }, - secure: false, - changeOrigin: true, - }, - }, - }, - mode: "development", - devtool: "source-map", -}; diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index 0ca6f023b..f045b0f5a 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -39,7 +39,7 @@ async function main() { rendererOptions: {}, }); - writeToFile("./languages/js_webassembly/bitwarden_client/schemas.ts", ts.lines); + writeToFile("./languages/js/sdk-client/src/schemas.ts", ts.lines); writeToFile("./crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts", ts.lines); const python = await quicktype({ From 33c8612f301eabe6aec411d89376c2603b0f483d Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:55:32 -0500 Subject: [PATCH 123/378] Fix version bump workflow on call (#426) --- .github/workflows/version-bump.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index f136c1dfe..fd9c9bef7 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -37,6 +37,9 @@ jobs: steps: - name: Checkout Branch uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + repository: bitwarden/sdk + ref: master - name: Install rust uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable @@ -175,7 +178,7 @@ jobs: TITLE: "Bump version to ${{ inputs.version_number }}" run: | PR_URL=$(gh pr create --title "$TITLE" \ - --base "$GITHUB_REF" \ + --base "master" \ --head "$PR_BRANCH" \ --label "version update" \ --label "automated pr" \ From b0243ce4d51a2119228a64530f560b5c7229b7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 12 Dec 2023 17:57:23 +0100 Subject: [PATCH 124/378] Split set_login_method from set_tokens (#425) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective There's no reason for these two to be combined, and it forces `renew_tokens` to clone login_method every time --- crates/bitwarden/src/auth/login/access_token.rs | 8 +++++--- crates/bitwarden/src/auth/login/api_key.rs | 12 ++++++------ crates/bitwarden/src/auth/login/password.rs | 10 +++++----- crates/bitwarden/src/auth/renew.rs | 6 ++---- crates/bitwarden/src/client/client.rs | 9 +++------ 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 8d5996119..147480576 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -58,12 +58,14 @@ pub(crate) async fn login_access_token( r.access_token.clone(), r.refresh_token.clone(), r.expires_in, - LoginMethod::ServiceAccount(ServiceAccountLoginMethod::AccessToken { + ); + client.set_login_method(LoginMethod::ServiceAccount( + ServiceAccountLoginMethod::AccessToken { access_token_id: access_token.access_token_id, client_secret: access_token.client_secret, organization_id, - }), - ); + }, + )); client.initialize_crypto_single_key(encryption_key); } diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index db5cbe01d..6f75b0033 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -36,13 +36,13 @@ pub(crate) async fn login_api_key( r.access_token.clone(), r.refresh_token.clone(), r.expires_in, - LoginMethod::User(UserLoginMethod::ApiKey { - client_id: input.client_id.to_owned(), - client_secret: input.client_secret.to_owned(), - email, - kdf, - }), ); + client.set_login_method(LoginMethod::User(UserLoginMethod::ApiKey { + client_id: input.client_id.to_owned(), + client_secret: input.client_secret.to_owned(), + email, + kdf, + })); let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 08d7d2054..7a93c68e0 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -42,12 +42,12 @@ pub(crate) async fn login_password( r.access_token.clone(), r.refresh_token.clone(), r.expires_in, - LoginMethod::User(UserLoginMethod::Username { - client_id: "web".to_owned(), - email: input.email.to_owned(), - kdf: input.kdf.to_owned(), - }), ); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "web".to_owned(), + email: input.email.to_owned(), + kdf: input.kdf.to_owned(), + })); let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); diff --git a/crates/bitwarden/src/auth/renew.rs b/crates/bitwarden/src/auth/renew.rs index 7973947ab..f215024d2 100644 --- a/crates/bitwarden/src/auth/renew.rs +++ b/crates/bitwarden/src/auth/renew.rs @@ -57,13 +57,11 @@ pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { match res { IdentityTokenResponse::Refreshed(r) => { - let login_method = login_method.to_owned(); - client.set_tokens(r.access_token, r.refresh_token, r.expires_in, login_method); + client.set_tokens(r.access_token, r.refresh_token, r.expires_in); return Ok(()); } IdentityTokenResponse::Authenticated(r) => { - let login_method = login_method.to_owned(); - client.set_tokens(r.access_token, r.refresh_token, r.expires_in, login_method); + client.set_tokens(r.access_token, r.refresh_token, r.expires_in); return Ok(()); } _ => { diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 2165b8dc7..fbbfb8798 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -29,7 +29,7 @@ pub(crate) struct ApiConfigurations { pub device_type: DeviceType, } -#[derive(Debug, Clone)] +#[derive(Debug)] pub(crate) enum LoginMethod { #[cfg(feature = "internal")] User(UserLoginMethod), @@ -38,7 +38,7 @@ pub(crate) enum LoginMethod { ServiceAccount(ServiceAccountLoginMethod), } -#[derive(Debug, Clone)] +#[derive(Debug)] #[cfg(feature = "internal")] pub(crate) enum UserLoginMethod { Username { @@ -55,7 +55,7 @@ pub(crate) enum UserLoginMethod { }, } -#[derive(Debug, Clone)] +#[derive(Debug)] pub(crate) enum ServiceAccountLoginMethod { AccessToken { access_token_id: Uuid, @@ -172,7 +172,6 @@ impl Client { self.encryption_settings.as_ref().ok_or(Error::VaultLocked) } - #[cfg(feature = "mobile")] pub(crate) fn set_login_method(&mut self, login_method: LoginMethod) { use log::debug; @@ -185,12 +184,10 @@ impl Client { token: String, refresh_token: Option, expires_in: u64, - login_method: LoginMethod, ) { self.token = Some(token.clone()); self.refresh_token = refresh_token; self.token_expires_in = Some(Utc::now().timestamp() + expires_in as i64); - self.login_method = Some(login_method); self.__api_configurations.identity.oauth_access_token = Some(token.clone()); self.__api_configurations.api.oauth_access_token = Some(token); } From c76e52e85baef7ebb802a84065da0ff4a1570275 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:58:04 +0100 Subject: [PATCH 125/378] [deps]: Update ts-node to v10.9.2 (#413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [ts-node](https://typestrong.org/ts-node) ([source](https://togithub.com/TypeStrong/ts-node)) | [`10.9.1` -> `10.9.2`](https://renovatebot.com/diffs/npm/ts-node/10.9.1/10.9.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/ts-node/10.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/ts-node/10.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/ts-node/10.9.1/10.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ts-node/10.9.1/10.9.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
TypeStrong/ts-node (ts-node) ### [`v10.9.2`](https://togithub.com/TypeStrong/ts-node/releases/tag/v10.9.2): Fix `tsconfig.json` file not found [Compare Source](https://togithub.com/TypeStrong/ts-node/compare/v10.9.1...v10.9.2) **Fixed** - Fixed `tsconfig.json` file not found on latest TypeScript version ([https://github.com/TypeStrong/ts-node/pull/2091](https://togithub.com/TypeStrong/ts-node/pull/2091))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 8 ++++---- crates/bitwarden-napi/package.json | 2 +- package-lock.json | 8 ++++---- package.json | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 00e591aaf..7a1281560 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -10,7 +10,7 @@ "license": "SEE LICENSE IN LICENSE", "devDependencies": { "@napi-rs/cli": "^2.13.2", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "typescript": "^5.0.0" }, "engines": { @@ -153,9 +153,9 @@ "dev": true }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", diff --git a/crates/bitwarden-napi/package.json b/crates/bitwarden-napi/package.json index a0dbcee3b..509cf1763 100644 --- a/crates/bitwarden-napi/package.json +++ b/crates/bitwarden-napi/package.json @@ -30,7 +30,7 @@ }, "devDependencies": { "@napi-rs/cli": "^2.13.2", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "typescript": "^5.0.0" }, "engines": { diff --git a/package-lock.json b/package-lock.json index faafd1f1c..9a7fa0a74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "prettier": "3.1.1", "quicktype-core": "23.0.80", "rimraf": "5.0.5", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "typescript": "5.3.2" } }, @@ -1875,9 +1875,9 @@ } }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", diff --git a/package.json b/package.json index 0332edade..464d12ecc 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "prettier": "3.1.1", "quicktype-core": "23.0.80", "rimraf": "5.0.5", - "ts-node": "10.9.1", + "ts-node": "10.9.2", "typescript": "5.3.2" } } From 1b5d01b6a920a3c4d9a54decc5df9e23473b8372 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:04:04 +0000 Subject: [PATCH 126/378] [deps]: Update typescript to v5.3.3 (#414) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [typescript](https://www.typescriptlang.org/) ([source](https://togithub.com/Microsoft/TypeScript)) | [`5.3.2` -> `5.3.3`](https://renovatebot.com/diffs/npm/typescript/5.3.2/5.3.3) | [![age](https://developer.mend.io/api/mc/badges/age/npm/typescript/5.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript/5.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript/5.3.2/5.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript/5.3.2/5.3.3?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
Microsoft/TypeScript (typescript) ### [`v5.3.3`](https://togithub.com/microsoft/TypeScript/releases/tag/v5.3.3): TypeScript 5.3.3 [Compare Source](https://togithub.com/Microsoft/TypeScript/compare/v5.3.2...v5.3.3) For release notes, check out the [release announcement](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/). For the complete list of fixed issues, check out the - [fixed issues query for Typescript 5.3.0 (Beta)](https://togithub.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.0%22+is%3Aclosed+). - [fixed issues query for Typescript 5.3.1 (RC)](https://togithub.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.1%22+is%3Aclosed+). - [fixed issues query for Typescript 5.3.2 (Stable)](https://togithub.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.2%22+is%3Aclosed+). - [fixed issues query for Typescript 5.3.3 (Stable)](https://togithub.com/Microsoft/TypeScript/issues?utf8=%E2%9C%93\&q=milestone%3A%22TypeScript+5.3.3%22+is%3Aclosed+). Downloads are available on: - [NuGet package](https://www.nuget.org/packages/Microsoft.TypeScript.MSBuild)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9a7fa0a74..729222a14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.2", - "typescript": "5.3.2" + "typescript": "5.3.3" } }, "node_modules/@babel/runtime": { @@ -1936,9 +1936,9 @@ } }, "node_modules/typescript": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", - "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 464d12ecc..683635f01 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,6 @@ "quicktype-core": "23.0.80", "rimraf": "5.0.5", "ts-node": "10.9.2", - "typescript": "5.3.2" + "typescript": "5.3.3" } } From 9c65e0775497cd43c4fb27896844580a1ed62db4 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:38:22 -0500 Subject: [PATCH 127/378] Add token to checkout step (#428) --- .github/workflows/version-bump.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index fd9c9bef7..19af72c1d 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -35,12 +35,6 @@ jobs: name: "Bump ${{ inputs.project }} Version to v${{ inputs.version_number }}" runs-on: ubuntu-22.04 steps: - - name: Checkout Branch - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - with: - repository: bitwarden/sdk - ref: master - - name: Install rust uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: @@ -66,6 +60,13 @@ jobs: github-gpg-private-key-passphrase, github-pat-bitwarden-devops-bot-repo-scope" + - name: Checkout Branch + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + repository: bitwarden/sdk + ref: master + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + - name: Import GPG key uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 with: @@ -173,8 +174,8 @@ jobs: if: ${{ steps.version-changed.outputs.changes_to_commit == 'TRUE' }} id: create-pr env: - PR_BRANCH: ${{ steps.create-branch.outputs.name }} GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + PR_BRANCH: ${{ steps.create-branch.outputs.name }} TITLE: "Bump version to ${{ inputs.version_number }}" run: | PR_URL=$(gh pr create --title "$TITLE" \ From 6a190a19a3bd765f61e1189c83859c85be2b731f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 12 Dec 2023 19:08:56 +0100 Subject: [PATCH 128/378] Change login_method to have the access token directly (#427) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Now that set_login_method is split from set_tokens, we can just change this to directly contain the token without adding the Clone bound to it. This way we avoid duplicating 2/3rds of the AccessToken. This should help with #388 --- crates/bitwarden/src/auth/login/access_token.rs | 3 +-- crates/bitwarden/src/auth/renew.rs | 15 +++++++-------- crates/bitwarden/src/client/access_token.rs | 11 ++++++++++- crates/bitwarden/src/client/client.rs | 5 +++-- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 147480576..ed664437d 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -61,8 +61,7 @@ pub(crate) async fn login_access_token( ); client.set_login_method(LoginMethod::ServiceAccount( ServiceAccountLoginMethod::AccessToken { - access_token_id: access_token.access_token_id, - client_secret: access_token.client_secret, + access_token, organization_id, }, )); diff --git a/crates/bitwarden/src/auth/renew.rs b/crates/bitwarden/src/auth/renew.rs index f215024d2..fe1920e62 100644 --- a/crates/bitwarden/src/auth/renew.rs +++ b/crates/bitwarden/src/auth/renew.rs @@ -43,14 +43,13 @@ pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { } }, LoginMethod::ServiceAccount(s) => match s { - ServiceAccountLoginMethod::AccessToken { - access_token_id, - client_secret, - .. - } => { - AccessTokenRequest::new(*access_token_id, client_secret) - .send(&client.__api_configurations) - .await? + ServiceAccountLoginMethod::AccessToken { access_token, .. } => { + AccessTokenRequest::new( + access_token.access_token_id, + &access_token.client_secret, + ) + .send(&client.__api_configurations) + .await? } }, }; diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index db6b78f20..c3d6f2fea 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -1,4 +1,4 @@ -use std::str::FromStr; +use std::{fmt::Debug, str::FromStr}; use base64::Engine; use uuid::Uuid; @@ -15,6 +15,15 @@ pub struct AccessToken { pub encryption_key: SymmetricCryptoKey, } +// We don't want to log the more sensitive fields from an AccessToken +impl Debug for AccessToken { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AccessToken") + .field("access_token_id", &self.access_token_id) + .finish() + } +} + impl FromStr for AccessToken { type Err = crate::error::Error; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index fbbfb8798..0c69ba917 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -22,6 +22,8 @@ use crate::{ error::{Error, Result}, }; +use super::AccessToken; + #[derive(Debug)] pub(crate) struct ApiConfigurations { pub identity: bitwarden_api_identity::apis::configuration::Configuration, @@ -58,8 +60,7 @@ pub(crate) enum UserLoginMethod { #[derive(Debug)] pub(crate) enum ServiceAccountLoginMethod { AccessToken { - access_token_id: Uuid, - client_secret: String, + access_token: AccessToken, organization_id: Uuid, }, } From c362462efb8edf9c9187a8e61e8907eb98e24002 Mon Sep 17 00:00:00 2001 From: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com> Date: Tue, 12 Dec 2023 12:05:00 -0800 Subject: [PATCH 129/378] Point workflows at `main` (#423) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update workflows to point to `main` ## Code changes - **.github/workflows/*:** Change all relevant references of internal `master` branches to `main` ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) - If this change requires a **documentation update** - notify the documentation team - If this change has particular **deployment requirements** - notify the DevOps team - Ensure that all UI additions follow [WCAG AA requirements](https://contributing.bitwarden.com/contributing/accessibility/) --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-cli.yml | 2 +- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-java.yml | 2 +- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-rust-crates.yml | 4 ++-- .github/workflows/cloc.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-php.yml | 2 +- .github/workflows/publish-ruby.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/release-napi.yml | 4 ++-- .github/workflows/rust-test.yml | 2 +- .github/workflows/version-bump.yml | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 22eda7f88..424d048e9 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -5,7 +5,7 @@ on: pull_request: push: branches: - - "master" + - "main" workflow_dispatch: defaults: diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 4239a9a0a..c8b1e97dd 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -5,7 +5,7 @@ on: pull_request: push: branches: - - "master" + - "main" - "rc" - "hotfix-rc" workflow_dispatch: diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 7ebb03526..91f21210b 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -3,7 +3,7 @@ name: Build .NET SDK on: push: branches: - - master + - main jobs: generate_schemas: diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 002164647..663f0d493 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -3,7 +3,7 @@ name: Build Java SDK on: push: branches: - - master + - main jobs: generate_schemas: diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index d5bd935e9..96d96fb8c 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -5,7 +5,7 @@ on: pull_request: push: branches: - - "master" + - "main" - "rc" - "hotfix-rc" workflow_dispatch: diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 7504887f0..b008540fb 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -6,7 +6,7 @@ on: pull_request: push: branches: - - "master" + - "main" - "rc" - "hotfix-rc" @@ -59,7 +59,7 @@ jobs: release-dry-run: name: Release dry-run runs-on: ubuntu-latest - if: ${{ github.ref == 'refs/head/master' || github.ref == 'refs/head/rc' || github.ref == 'refs/head/hotfix-rc' }} + if: ${{ github.ref == 'refs/head/main' || github.ref == 'refs/head/rc' || github.ref == 'refs/head/hotfix-rc' }} needs: - build steps: diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index a3afad257..f87ba6aa8 100644 --- a/.github/workflows/cloc.yml +++ b/.github/workflows/cloc.yml @@ -3,7 +3,7 @@ name: CLOC on: workflow_dispatch: push: - branches: ["master"] + branches: ["main"] pull_request: jobs: diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index f164a2433..eb911072f 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -5,7 +5,7 @@ on: pull_request: push: branches: - - "master" + - "main" - "rc" - "hotfix-rc" workflow_dispatch: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d6e57740e..0d2dbed91 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -3,7 +3,7 @@ name: Lint on: workflow_dispatch: push: - branches: ["master"] + branches: ["main"] pull_request: env: diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index b033319ec..ef03eca4a 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -3,7 +3,7 @@ name: Publish PHP SDK on: push: branches: - - master + - main jobs: build_rust: diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index fa46af292..c7d5ded20 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -3,7 +3,7 @@ name: Publish Ruby SDK on: push: branches: - - master + - main jobs: generate_schemas: diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 04863f34e..ee08c2be8 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -72,7 +72,7 @@ jobs: workflow: build-cli.yml path: packages workflow_conclusion: success - branch: master + branch: main - name: Get checksum files uses: bitwarden/gh-actions/get-checksum@main diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 3171cfb33..19595832a 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -117,7 +117,7 @@ jobs: artifacts: schemas.ts path: ${{ github.workspace }}/crates/bitwarden-napi/src-ts/bitwarden_client/ workflow_conclusion: success - branch: master + branch: main - name: Install dependencies run: npm ci @@ -153,7 +153,7 @@ jobs: workflow: build-napi.yml path: ${{ github.workspace }}/crates/bitwarden-napi/artifacts workflow_conclusion: success - branch: master + branch: main - name: Move artifacts run: npm run artifacts diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 2ea0ad5eb..49775481b 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: push: branches: - - "master" + - "main" - "rc" - "hotfix-rc" pull_request: diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 19af72c1d..31e8b4a3a 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -179,7 +179,7 @@ jobs: TITLE: "Bump version to ${{ inputs.version_number }}" run: | PR_URL=$(gh pr create --title "$TITLE" \ - --base "master" \ + --base "main" \ --head "$PR_BRANCH" \ --label "version update" \ --label "automated pr" \ From 92f19dc401964e3acea6c35e3118d44d75b71007 Mon Sep 17 00:00:00 2001 From: Joseph Flinn <58369717+joseph-flinn@users.noreply.github.com> Date: Wed, 13 Dec 2023 02:56:42 -0800 Subject: [PATCH 130/378] Fix branch (#430) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Fix changed branch ## Code changes * **.github/workflow/version-bump.yml:** Switch from `master` to `main` ## Before you submit - Please check for formatting errors (`dotnet format --verify-no-changes`) (required) - If making database changes - make sure you also update Entity Framework queries and/or migrations - Please add **unit tests** where it makes sense to do so (encouraged but not required) - If this change requires a **documentation update** - notify the documentation team - If this change has particular **deployment requirements** - notify the DevOps team --- .github/workflows/version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 31e8b4a3a..4fb83ae8c 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -64,7 +64,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: repository: bitwarden/sdk - ref: master + ref: main token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} - name: Import GPG key From f8114ab16ca7fc19ef04f68f36077d094e2f6dc6 Mon Sep 17 00:00:00 2001 From: Robyn MacCallum Date: Wed, 13 Dec 2023 10:24:31 -0500 Subject: [PATCH 131/378] Update Changelog with env output item (#429) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ``` ## Objective Add env output item in the changelog ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bws/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 2dc71f152..3ae1d9009 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,6 +7,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Ability to output secrets in an `env` format with `bws` (#320) + ## [0.3.1] - 2023-10-13 ### Added From a8ebf5acef922ddc642b8ab4566b78711981ed50 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 14 Dec 2023 13:19:49 +0100 Subject: [PATCH 132/378] Tweak ruby to not emit null in settings (#432) --- languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb b/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb index c2ce7e576..b023402da 100644 --- a/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb +++ b/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb @@ -37,7 +37,7 @@ def initialize(bitwarden_settings) ) @bitwarden = BitwardenLib - @handle = @bitwarden.init(client_settings.to_json) + @handle = @bitwarden.init(client_settings.to_dynamic.compact.to_json) @command_runner = CommandRunner.new(@bitwarden, @handle) @project_client = ProjectsClient.new(@command_runner) @secrets_client = SecretsClient.new(@command_runner) From 7ec2183ab8194a05c994c9c67909dec538da1096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 14 Dec 2023 15:11:08 +0100 Subject: [PATCH 133/378] Improve SDK bindings examples (#377) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Updated all the samples to load access token, organization id and urls from env variables. This made it much easier to quickly test all the bindings. Also added one Java example. --- languages/cpp/examples/Wrapper.cpp | 15 +++---- languages/go/example/example.go | 1 + languages/java/Example.java | 33 +++++++++++++++ .../com/bitwarden/sdk/ExampleProgram.java | 42 ------------------- languages/php/example.php | 10 +++-- languages/ruby/examples/example.rb | 13 +++--- 6 files changed, 56 insertions(+), 58 deletions(-) create mode 100644 languages/java/Example.java delete mode 100644 languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java diff --git a/languages/cpp/examples/Wrapper.cpp b/languages/cpp/examples/Wrapper.cpp index df4aa164c..e94980698 100644 --- a/languages/cpp/examples/Wrapper.cpp +++ b/languages/cpp/examples/Wrapper.cpp @@ -7,6 +7,9 @@ int main() { const char* accessTokenEnv = std::getenv("ACCESS_TOKEN"); const char* organizationIdEnv = std::getenv("ORGANIZATION_ID"); + const char* apiUrl = std::getenv("API_URL"); + const char* identityUrl = std::getenv("IDENTITY_URL"); + if (!accessTokenEnv || !organizationIdEnv) { std::cerr << "Error: Environment variables ACCESS_TOKEN or ORGANIZATION_ID not set." << std::endl; return 1; @@ -15,15 +18,13 @@ int main() { std::string accessToken = accessTokenEnv; std::string organizationId = organizationIdEnv; - - - // Optional - commented to use default values - // BitwardenSettings bitwardenSettings; - // bitwardenSettings.set_api_url(""); - // bitwardenSettings.set_identity_url(""); + // Configuring the URLS is optional, remove them to use the default values + BitwardenSettings bitwardenSettings; + bitwardenSettings.set_api_url(apiUrl); + bitwardenSettings.set_identity_url(identityUrl); // Create a Bitwarden client instance - BitwardenClient bitwardenClient = BitwardenClient(); + BitwardenClient bitwardenClient = BitwardenClient(bitwardenSettings); // // Access token login bitwardenClient.accessTokenLogin(accessToken); // Organization ID diff --git a/languages/go/example/example.go b/languages/go/example/example.go index 5935d8002..154c14618 100644 --- a/languages/go/example/example.go +++ b/languages/go/example/example.go @@ -9,6 +9,7 @@ import ( ) func main() { + // Configuring the URLS is optional, set them to nil to use the default values apiURL := os.Getenv("API_URL") identityURL := os.Getenv("IDENTITY_URL") diff --git a/languages/java/Example.java b/languages/java/Example.java new file mode 100644 index 000000000..eacf23f8a --- /dev/null +++ b/languages/java/Example.java @@ -0,0 +1,33 @@ +import java.lang.System; +import java.util.UUID; + +import com.bitwarden.sdk.*; +import com.bitwarden.sdk.schema.*; + +class Example { + public static void main(String[] args) { + + String accessToken = System.getenv("ACCESS_TOKEN"); + UUID organizationId = UUID.fromString(System.getenv("ORGANIZATION_ID")); + String apiUrl = System.getenv("API_URL"); + String identityUrl = System.getenv("IDENTITY_URL"); + + // Configuring the URLS is optional, remove them to use the default values + BitwardenSettings bitwardenSettings = new BitwardenSettings(); + bitwardenSettings.setApiUrl(apiUrl); + bitwardenSettings.setIdentityUrl(identityUrl); + BitwardenClient client = new BitwardenClient(bitwardenSettings); + client.accessTokenLogin(accessToken); + + + ProjectResponse project = client.projects().create(organizationId, "Test Project"); + ProjectsResponse list = client.projects().list(organizationId); + + SecretResponse secret = client.secrets().create("Secret Key", "Secret Value", "Secret Note", organizationId, new UUID[] { project.getID() }); + + System.out.println("Secret: " + secret.getValue()); + + client.secrets().delete(new UUID[] { secret.getID() }); + client.projects().delete(new UUID[] { project.getID() }); + } +} diff --git a/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java b/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java deleted file mode 100644 index f3ad53036..000000000 --- a/languages/java/src/main/java/com/bitwarden/sdk/ExampleProgram.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.bitwarden.sdk; - -import com.bitwarden.sdk.schema.*; - -import java.util.UUID; - -public class ExampleProgram { - - public static void main(String[] args) { - BitwardenSettings bitwardenSettings = new BitwardenSettings(); - bitwardenSettings.setApiUrl("https://api.bitwarden.com"); - bitwardenSettings.setIdentityUrl("https://identity.bitwarden.com"); - - try (BitwardenClient bitwardenClient = new BitwardenClient(bitwardenSettings)) { - APIKeyLoginResponse apiKeyLoginResponse = bitwardenClient.accessTokenLogin(""); - - UUID organizationId = UUID.fromString(""); - ProjectResponse projectResponse = bitwardenClient.projects().create(organizationId, "NewTestProject"); - UUID projectId = projectResponse.getID(); - ProjectsResponse projectsResponse = bitwardenClient.projects().list(organizationId); - projectResponse = bitwardenClient.projects().get(projectId); - projectResponse = bitwardenClient.projects().update(projectId, organizationId, "NewTestProject2"); - - String key = "key"; - String value = "value"; - String note = "note"; - SecretResponse secretResponse = bitwardenClient.secrets().create(key, value, note, organizationId, - new UUID[]{projectId}); - UUID secretId = secretResponse.getID(); - SecretIdentifiersResponse secretIdentifiersResponse = bitwardenClient.secrets().list(organizationId); - secretResponse = bitwardenClient.secrets().get(secretId); - key = "key2"; - value = "value2"; - note = "note2"; - secretResponse = bitwardenClient.secrets().update(secretId, key, value, note, organizationId, - new UUID[]{projectId}); - - SecretsDeleteResponse secretsDeleteResponse = bitwardenClient.secrets().delete(new UUID[]{secretId}); - ProjectsDeleteResponse projectsDeleteResponse = bitwardenClient.projects().delete(new UUID[]{projectId}); - } - } -} diff --git a/languages/php/example.php b/languages/php/example.php index 0fdb6930a..7eafcb96a 100644 --- a/languages/php/example.php +++ b/languages/php/example.php @@ -2,10 +2,14 @@ require_once 'vendor/autoload.php'; -$access_token = ''; -$organization_id = ""; +$access_token = getenv('ACCESS_TOKEN'); +$organization_id = getenv('ORGANIZATION_ID'); -$client_settings = new \Bitwarden\Sdk\BitwardenSettings(); +// Configuring the URLS is optional, set them to null to use the default values +$api_url = getenv('API_URL'); +$identity_url = getenv('IDENTITY_URL'); + +$client_settings = new \Bitwarden\Sdk\BitwardenSettings($api_url, $identity_url); $bitwarden_client = new \Bitwarden\Sdk\BitwardenClient($client_settings); $bitwarden_client->access_token_login($access_token); diff --git a/languages/ruby/examples/example.rb b/languages/ruby/examples/example.rb index c0deeb437..09192aa5d 100644 --- a/languages/ruby/examples/example.rb +++ b/languages/ruby/examples/example.rb @@ -1,13 +1,14 @@ # NOTE - for example purpose only - import gem instead require 'bitwarden-sdk' -token = '' -organization_id = '' +token = ENV['ACCESS_TOKEN'] +organization_id = ENV['ORGANIZATION_ID'] -bitwarden_settings = BitwardenSDK::BitwardenSettings.new( - 'https://api.bitwarden.com', - 'https://identity.bitwarden.com/connect/token' -) +# Configuring the URLS is optional, set them to nil to use the default values +api_url = ENV['API_URL'] +identity_url = ENV['IDENTITY_URL'] + +bitwarden_settings = BitwardenSDK::BitwardenSettings.new(api_url, identity_url) bw_client = BitwardenSDK::BitwardenClient.new(bitwarden_settings) response = bw_client.access_token_login(token) From e6d0759541d3c65b9338d809bf6876d396d475c6 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 15 Dec 2023 11:11:33 +0100 Subject: [PATCH 134/378] Add support for Hmac org keys (#435) --- .../src/client/encryption_settings.rs | 11 +-- crates/bitwarden/src/crypto/enc_string.rs | 73 ++++++++++++++++++- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 7c16725e7..f56932700 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -9,7 +9,7 @@ use { crypto::{EncString, KeyDecryptable}, error::{CryptoError, Result}, }, - rsa::{pkcs8::DecodePrivateKey, Oaep}, + rsa::pkcs8::DecodePrivateKey, }; use crate::crypto::SymmetricCryptoKey; @@ -96,14 +96,7 @@ impl EncryptionSettings { // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { - let data = match org_enc_key { - EncString::Rsa2048_OaepSha1_B64 { data } => data, - _ => return Err(CryptoError::InvalidKey.into()), - }; - - let dec = private_key - .decrypt(Oaep::new::(), &data) - .map_err(|_| CryptoError::KeyDecrypt)?; + let dec = org_enc_key.decrypt_with_private_key(private_key)?; let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?; diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index 3004d2dea..34ec359ab 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -2,6 +2,8 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; +#[cfg(feature = "internal")] +use rsa::{Oaep, RsaPrivateKey}; use serde::{de::Visitor, Deserialize}; use super::{KeyDecryptable, KeyEncryptable, LocateKey}; @@ -144,12 +146,12 @@ impl FromStr for EncString { Ok(EncString::Rsa2048_OaepSha1_B64 { data }) } #[allow(deprecated)] - ("5", 1) => { + ("5", 2) => { let data = from_b64_vec(parts[0])?; Ok(EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data }) } #[allow(deprecated)] - ("6", 1) => { + ("6", 2) => { let data = from_b64_vec(parts[0])?; Ok(EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data }) } @@ -170,6 +172,29 @@ impl EncString { s.map(|s| s.parse()).transpose() } + /// TODO: Convert this to a trait method + #[cfg(feature = "internal")] + pub(crate) fn decrypt_with_private_key(&self, key: &RsaPrivateKey) -> Result> { + Ok(match self { + EncString::Rsa2048_OaepSha256_B64 { data } => { + key.decrypt(Oaep::new::(), data) + } + EncString::Rsa2048_OaepSha1_B64 { data } => { + key.decrypt(Oaep::new::(), data) + } + #[allow(deprecated)] + EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data } => { + key.decrypt(Oaep::new::(), data) + } + #[allow(deprecated)] + EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data } => { + key.decrypt(Oaep::new::(), data) + } + _ => return Err(CryptoError::InvalidKey.into()), + } + .map_err(|_| CryptoError::KeyDecrypt)?) + } + #[cfg(feature = "mobile")] pub(crate) fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { @@ -430,6 +455,50 @@ mod tests { assert_eq!(decrypted_str, test_string); } + #[cfg(feature = "internal")] + #[test] + fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { + use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; + + let rsa_private_key: &str = "-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS +8HzYUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2 +e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86LnhD56A9FDUfuI0dVnPcrwNv0YJIo9 +4LwxtbqBULNvXl6wJ7WAbODrCQy5ZgMVg+iH+gGpwiqsZqHt+KuoHWcN53MSPDfa +F4/YMB99U3TziJMOOJask1TEEnakMPln11PczNDazT17DXIxYrbPfutPdh6sLs6A +QOajdZijfEvepgnOe7cQ7aeatiOJFrjTApKPGxOVRzEMX4XS4xbyhH0QxQeB6l16 +l8C0uxIBAgMBAAECggEASaWfeVDA3cVzOPFSpvJm20OTE+R6uGOU+7vh36TX/POq +92qBuwbd0h0oMD32FxsXywd2IxtBDUSiFM9699qufTVuM0Q3tZw6lHDTOVG08+tP +dr8qSbMtw7PGFxN79fHLBxejjO4IrM9lapjWpxEF+11x7r+wM+0xRZQ8sNFYG46a +PfIaty4BGbL0I2DQ2y8I57iBCAy69eht59NLMm27fRWGJIWCuBIjlpfzET1j2HLX +UIh5bTBNzqaN039WH49HczGE3mQKVEJZc/efk3HaVd0a1Sjzyn0QY+N1jtZN3jTR +buDWA1AknkX1LX/0tUhuS3/7C3ejHxjw4Dk1ZLo5/QKBgQDIWvqFn0+IKRSu6Ua2 +hDsufIHHUNLelbfLUMmFthxabcUn4zlvIscJO00Tq/ezopSRRvbGiqnxjv/mYxuc +vOUBeZtlus0Q9RTACBtw9TGoNTmQbEunJ2FOSlqbQxkBBAjgGEppRPt30iGj/VjA +hCATq2MYOa/X4dVR51BqQAFIEwKBgQDBSIfTFKC/hDk6FKZlgwvupWYJyU9Rkyfs +tPErZFmzoKhPkQ3YORo2oeAYmVUbS9I2iIYpYpYQJHX8jMuCbCz4ONxTCuSIXYQY +UcUq4PglCKp31xBAE6TN8SvhfME9/MvuDssnQinAHuF0GDAhF646T3LLS1not6Vs +zv7brwSoGwKBgQC88v/8cGfi80ssQZeMnVvq1UTXIeQcQnoY5lGHJl3K8mbS3TnX +E6c9j417Fdz+rj8KWzBzwWXQB5pSPflWcdZO886Xu/mVGmy9RWgLuVFhXwCwsVEP +jNX5ramRb0/vY0yzenUCninBsIxFSbIfrPtLUYCc4hpxr+sr2Mg/y6jpvQKBgBez +MRRs3xkcuXepuI2R+BCXL1/b02IJTUf1F+1eLLGd7YV0H+J3fgNc7gGWK51hOrF9 +JBZHBGeOUPlaukmPwiPdtQZpu4QNE3l37VlIpKTF30E6mb+BqR+nht3rUjarnMXg +AoEZ18y6/KIjpSMpqC92Nnk/EBM9EYe6Cf4eA9ApAoGAeqEUg46UTlJySkBKURGp +Is3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8+tPVgppLcG0+tMdLjigFQiDUQk2y3 +WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz +XKZBokBGnjFnTnKcs7nv/O8= +-----END PRIVATE KEY-----"; + let private_key = RsaPrivateKey::from_pkcs8_pem(rsa_private_key).unwrap(); + let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; + let enc_string: EncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 6); + + let res = enc_string.decrypt_with_private_key(&private_key).unwrap(); + + assert_eq!(std::str::from_utf8(&res).unwrap(), "EncryptMe!"); + } + #[test] fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] From 2a163b7bf6bbd006e8ba070a843246d17224141c Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 15 Dec 2023 16:39:14 +0100 Subject: [PATCH 135/378] Wire up code coverage (#433) --- .github/workflows/rust-test.yml | 40 ++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 49775481b..ee8c55a22 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -15,7 +15,7 @@ env: jobs: ci-pass: name: CI is green - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: - test - wasm @@ -25,14 +25,14 @@ jobs: test: name: ${{ matrix.os }} / ${{matrix.target || 'default' }} - runs-on: ${{ matrix.os || 'ubuntu-latest' }} + runs-on: ${{ matrix.os || 'ubuntu-22.04' }} strategy: matrix: os: - - ubuntu-latest - - macOS-latest - - windows-latest + - ubuntu-22.04 + - macOS-12 + - windows-2022 steps: - name: Checkout @@ -49,10 +49,38 @@ jobs: - name: Test run: cargo test --all-features + coverage: + name: Coverage + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + toolchain: stable + components: llvm-tools + + - name: Cache cargo registry + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + + - name: Install cargo-llvm-cov + run: cargo install cargo-llvm-cov --version 0.5.38 + + - name: Generate coverage + run: cargo llvm-cov --all-features --lcov --output-path lcov.info --ignore-filename-regex "crates/bitwarden-api-" + + - name: Upload to codecov.io + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + wasm: name: WASM - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - name: Checkout From e32e2ff80f907081729427405da6aa9b5727997b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:56:15 +0100 Subject: [PATCH 136/378] [deps]: Update Rust crate thiserror to 1.0.51 (#437) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bws/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73609e295..e181f8e76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3190,18 +3190,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index ba59ece0e..d9f008043 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -35,7 +35,7 @@ serde = "^1.0.193" serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" -thiserror = "1.0.50" +thiserror = "1.0.51" tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.6.1", features = ["serde"] } From c071d476e0441d74abecc41e0d1a1babff496c70 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:57:15 +0100 Subject: [PATCH 137/378] [deps]: Lock file maintenance (#445) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 158 +++---- crates/bitwarden-napi/package-lock.json | 12 +- languages/js/sdk-client/package-lock.json | 485 +++++++++------------- package-lock.json | 24 +- 4 files changed, 299 insertions(+), 380 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e181f8e76..fcc4155e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -83,30 +83,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -156,7 +156,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -227,7 +227,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -704,7 +704,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -815,9 +815,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "content_inspector" @@ -873,9 +873,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ "cfg-if", ] @@ -930,12 +930,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1101,9 +1101,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.9" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" +checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" dependencies = [ "indenter", "once_cell", @@ -1244,7 +1244,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1411,9 +1411,9 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hkdf" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" dependencies = [ "hmac", ] @@ -1429,11 +1429,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1449,9 +1449,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1675,9 +1675,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" @@ -1699,9 +1699,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" @@ -1832,9 +1832,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", @@ -1864,23 +1864,23 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.14.2" +version = "2.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0cca5738c6e81eb5ffd2c8ff2b4f05ece9c4c60c7e2b36cec6524492cf7f330" +checksum = "9b5af262f1d8e660742eb722abc7113a5b3c3de4144d0ef23ede2518672ceff1" dependencies = [ "cfg-if", "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.41", ] [[package]] name = "napi-derive-backend" -version = "1.0.55" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35960e5f33228192a9b661447d0dfe8f5a3790ff5b4058c4d67680ded4f65b91" +checksum = "4ea236321b521d6926213a2021e407b0562e28a257c037a45919e414d2cdb4f8" dependencies = [ "convert_case", "once_cell", @@ -1888,7 +1888,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 1.0.109", + "syn 2.0.41", ] [[package]] @@ -2036,9 +2036,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oneshot" @@ -2073,9 +2073,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -2094,7 +2094,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2105,18 +2105,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.6+3.1.4" +version = "300.2.1+3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" +checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" dependencies = [ "cc", "libc", @@ -2384,7 +2384,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2396,7 +2396,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2640,9 +2640,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", @@ -2659,9 +2659,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "safemem" @@ -2743,7 +2743,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2808,7 +2808,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2863,7 +2863,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3068,7 +3068,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3100,9 +3100,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -3205,7 +3205,7 @@ checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3287,7 +3287,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3382,7 +3382,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3436,9 +3436,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -3457,9 +3457,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-ident" @@ -3555,7 +3555,7 @@ version = "0.25.2" source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3586,7 +3586,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.39", + "syn 2.0.41", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3635,9 +3635,9 @@ checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "unsafe-libyaml" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" [[package]] name = "url" @@ -3744,7 +3744,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", "wasm-bindgen-shared", ] @@ -3778,7 +3778,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3811,7 +3811,7 @@ checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -4081,9 +4081,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" dependencies = [ "memchr", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 7a1281560..e10a23742 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dev": true, "peer": true, "dependencies": { @@ -117,9 +117,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index ff252e970..12a2bb7c7 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -1,6 +1,6 @@ { "name": "@bitwarden/sdk-client", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -11,6 +11,23 @@ "typescript": "^5.0.3" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -22,30 +39,33 @@ } }, "node_modules/@types/node": { - "version": "18.16.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", - "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", - "dev": true + "version": "18.19.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", + "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" @@ -66,17 +86,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -109,10 +118,16 @@ "node": ">= 8" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/foreground-child": { @@ -132,19 +147,19 @@ } }, "node_modules/glob": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", - "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.7.0" + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -169,12 +184,12 @@ "dev": true }, "node_modules/jackspeak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.0.tgz", - "integrity": "sha512-DiEwVPqsieUzZBNxQ2cxznmFzfg/AMgJUjYw5xl6rSmCxAQXECcbSdwcLM6Ds6T09+SBfSNCGPhYUoQ96P4h7A==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { - "cliui": "^7.0.4" + "@isaacs/cliui": "^8.0.2" }, "engines": { "node": ">=14" @@ -187,18 +202,18 @@ } }, "node_modules/lru-cache": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", - "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", "dev": true, "engines": { "node": "14 || >=16.14" } }, "node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -211,12 +226,12 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/path-key": { @@ -229,13 +244,13 @@ } }, "node_modules/path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", "dev": true, "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -245,15 +260,15 @@ } }, "node_modules/rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", + "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", "dev": true, "dependencies": { - "glob": "^10.0.0" + "glob": "^10.3.7" }, "bin": { - "rimraf": "dist/cjs/src/bin.js" + "rimraf": "dist/esm/bin.mjs" }, "engines": { "node": ">=14" @@ -284,9 +299,9 @@ } }, "node_modules/signal-exit": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", - "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { "node": ">=14" @@ -296,6 +311,24 @@ } }, "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -309,7 +342,50 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", @@ -321,19 +397,34 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=12.20" + "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -350,6 +441,24 @@ } }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -365,251 +474,61 @@ "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } - } - }, - "dependencies": { - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true }, - "@types/node": { - "version": "18.16.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.1.tgz", - "integrity": "sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==", - "dev": true - }, - "ansi-regex": { + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "ansi-styles": { + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "requires": { + "dependencies": { "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "emoji-regex": { + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "glob": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", - "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", - "path-scurry": "^1.7.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "jackspeak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.0.tgz", - "integrity": "sha512-DiEwVPqsieUzZBNxQ2cxznmFzfg/AMgJUjYw5xl6rSmCxAQXECcbSdwcLM6Ds6T09+SBfSNCGPhYUoQ96P4h7A==", - "dev": true, - "requires": { - "@pkgjs/parseargs": "^0.11.0", - "cliui": "^7.0.4" - } - }, - "lru-cache": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", - "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", - "dev": true - }, - "minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", - "dev": true, - "requires": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" - } - }, - "rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", - "dev": true, - "requires": { - "glob": "^10.0.0" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", - "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", - "dev": true - }, - "string-width": { + "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, - "requires": { + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "strip-ansi": { + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "requires": { + "dependencies": { "ansi-regex": "^5.0.1" - } - }, - "typescript": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", - "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } } } diff --git a/package-lock.json b/package-lock.json index 729222a14..3aa3c5092 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", - "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", + "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -363,9 +363,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.3.tgz", - "integrity": "sha512-XJavIpZqiXID5Yxnxv3RUDKTN5b81ddNC3ecsA0SoFXz/QU8OGBwZGMomiq0zw+uuqbL/krztv/DINAQ/EV4gg==", + "version": "20.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", + "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", "dev": true, "peer": true, "dependencies": { @@ -403,9 +403,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1577,9 +1577,9 @@ "dev": true }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true }, "node_modules/require-directory": { From dda075cabe5b48339f7a65604cd1ac63cdcf150f Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 18 Dec 2023 11:02:37 +0100 Subject: [PATCH 138/378] Update old references to master branch (#446) --- languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj | 2 +- languages/java/build.gradle | 4 ++-- languages/kotlin/sdk/build.gradle | 4 ++-- languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj index 951b893ab..183ea8db9 100644 --- a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj +++ b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj @@ -12,7 +12,7 @@ Bitwarden Inc. SDK - https://github.com/bitwarden/sdk/tree/master/languages/csharp + https://github.com/bitwarden/sdk/tree/main/languages/csharp Git https://bitwarden.com/products/secrets-manager/ diff --git a/languages/java/build.gradle b/languages/java/build.gradle index dc17386c4..f044ea485 100644 --- a/languages/java/build.gradle +++ b/languages/java/build.gradle @@ -31,11 +31,11 @@ repositories { // Determine the version from the git history. // // PRs: use the branch name. - // Master: Grab it from `crates/bitwarden/Cargo.toml` + // Main: Grab it from `crates/bitwarden/Cargo.toml` def branchName = "git branch --show-current".execute().text.trim() - if (branchName == "master") { + if (branchName == "main") { def content = ['grep', '-o', '^version = ".*"', '../../crates/bitwarden/Cargo.toml'].execute().text.trim() def match = ~/version = "(.*)"/ def matcher = match.matcher(content) diff --git a/languages/kotlin/sdk/build.gradle b/languages/kotlin/sdk/build.gradle index 3fb6956e2..a4ee06814 100644 --- a/languages/kotlin/sdk/build.gradle +++ b/languages/kotlin/sdk/build.gradle @@ -46,11 +46,11 @@ publishing { // Determine the version from the git history. // // PRs: use the branch name. - // Master: Grab it from `crates/bitwarden/Cargo.toml` + // Main: Grab it from `crates/bitwarden/Cargo.toml` def branchName = "git branch --show-current".execute().text.trim() - if (branchName == "master") { + if (branchName == "main") { def content = ['grep', '-o', '^version = ".*"', '../../crates/bitwarden/Cargo.toml'].execute().text.trim() def match = ~/version = "(.*)"/ def matcher = match.matcher(content) diff --git a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec index 12a4f5fdc..596531035 100644 --- a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec +++ b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec @@ -15,7 +15,7 @@ Gem::Specification.new do |spec| spec.metadata['homepage_uri'] = spec.homepage spec.metadata['source_code_uri'] = 'https://github.com/bitwarden/sdk' - spec.metadata['changelog_uri'] = 'https://github.com/bitwarden/sdk/blob/master/languages/ruby/CHANGELOG.md' + spec.metadata['changelog_uri'] = 'https://github.com/bitwarden/sdk/blob/main/languages/ruby/CHANGELOG.md' # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. From c8a1d77c7dc4559247608c94ecf973bb6498e912 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 18 Dec 2023 12:46:27 +0100 Subject: [PATCH 139/378] Improve internal error (#436) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Allow using dynamic strings on the Internal error variant, tested on the passphrase length error. The Internal variant is using a `Cow<'static, str>`, to avoid unnecessary allocations on all the cases where a `&'static str` would suffice. I've implemented `From<&'static str>` and `From` for Error. It feels a bit magic, but it avoids repeating `Error::Internal` all over the place. --- crates/bitwarden/src/auth/jwt_token.rs | 4 +--- crates/bitwarden/src/auth/login/api_key.rs | 4 ++-- crates/bitwarden/src/client/kdf.rs | 2 +- crates/bitwarden/src/crypto/fingerprint.rs | 15 +++++---------- crates/bitwarden/src/crypto/mod.rs | 8 +++----- crates/bitwarden/src/crypto/rsa.rs | 6 +++--- crates/bitwarden/src/error.rs | 16 ++++++++++++++-- .../bitwarden/src/platform/get_user_api_key.rs | 2 +- .../bitwarden/src/tool/generators/passphrase.rs | 9 +++------ crates/bitwarden/src/tool/generators/password.rs | 14 ++++---------- crates/bitwarden/src/uniffi_support.rs | 2 +- crates/bitwarden/src/vault/totp.rs | 6 +++--- 12 files changed, 41 insertions(+), 47 deletions(-) diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs index 9097b84f2..17e0e13e9 100644 --- a/crates/bitwarden/src/auth/jwt_token.rs +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -29,9 +29,7 @@ impl FromStr for JWTToken { fn from_str(s: &str) -> Result { let split = s.split('.').collect::>(); if split.len() != 3 { - return Err(crate::error::Error::Internal( - "JWT token has an invalid number of parts", - )); + return Err("JWT token has an invalid number of parts".into()); } let decoded = BASE64_ENGINE.decode(split[1])?; Ok(serde_json::from_slice(&decoded)?) diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index 6f75b0033..9370559b4 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -9,7 +9,7 @@ use crate::{ }, client::{LoginMethod, UserLoginMethod}, crypto::EncString, - error::{Error, Result}, + error::Result, Client, }; @@ -28,7 +28,7 @@ pub(crate) async fn login_api_key( // This should always be Some() when logging in with an api key let email = access_token_obj .email - .ok_or(Error::Internal("Access token doesn't contain email"))?; + .ok_or("Access token doesn't contain email")?; let kdf = client.auth().prelogin(email.clone()).await?; diff --git a/crates/bitwarden/src/client/kdf.rs b/crates/bitwarden/src/client/kdf.rs index 4f1edfdb0..2f6787d8d 100644 --- a/crates/bitwarden/src/client/kdf.rs +++ b/crates/bitwarden/src/client/kdf.rs @@ -32,7 +32,7 @@ impl TryFrom for Kdf { default_pbkdf2_iterations, }; - let kdf = response.kdf.ok_or(Error::Internal("KDF not found"))?; + let kdf = response.kdf.ok_or("KDF not found")?; Ok(match kdf { KdfType::Variant0 => Kdf::PBKDF2 { diff --git a/crates/bitwarden/src/crypto/fingerprint.rs b/crates/bitwarden/src/crypto/fingerprint.rs index ddcf89d40..707a07ca6 100644 --- a/crates/bitwarden/src/crypto/fingerprint.rs +++ b/crates/bitwarden/src/crypto/fingerprint.rs @@ -2,10 +2,7 @@ use num_bigint::BigUint; use num_traits::cast::ToPrimitive; use sha2::Digest; -use crate::{ - error::{Error, Result}, - wordlist::EFF_LONG_WORD_LIST, -}; +use crate::{error::Result, wordlist::EFF_LONG_WORD_LIST}; /// Computes a fingerprint of the given `fingerprint_material` using the given `public_key`. /// @@ -17,12 +14,12 @@ pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Resu h.update(public_key); h.finalize(); - let hkdf = hkdf::Hkdf::::from_prk(public_key) - .map_err(|_| Error::Internal("hkdf::InvalidLength"))?; + let hkdf = + hkdf::Hkdf::::from_prk(public_key).map_err(|_| "hkdf::InvalidLength")?; let mut user_fingerprint = [0u8; 32]; hkdf.expand(fingerprint_material.as_bytes(), &mut user_fingerprint) - .map_err(|_| Error::Internal("hkdf::expand"))?; + .map_err(|_| "hkdf::expand")?; Ok(hash_word(user_fingerprint).unwrap()) } @@ -37,9 +34,7 @@ fn hash_word(hash: [u8; 32]) -> Result { let hash_arr: Vec = hash.to_vec(); let entropy_available = hash_arr.len() * 4; if num_words as f64 * entropy_per_word > entropy_available as f64 { - return Err(Error::Internal( - "Output entropy of hash function is too small", - )); + return Err("Output entropy of hash function is too small".into()); } let mut phrase = Vec::new(); diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index fc79ad8f5..3d8f7b0ce 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -24,7 +24,7 @@ use aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; use hmac::digest::OutputSizeUser; -use crate::error::{Error, Result}; +use crate::error::Result; mod enc_string; pub use enc_string::EncString; @@ -65,13 +65,11 @@ pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = /// RFC5869 HKDF-Expand operation fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result> { - let hkdf = hkdf::Hkdf::::from_prk(prk) - .map_err(|_| Error::Internal("invalid prk length"))?; + let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| "invalid prk length")?; let mut key = GenericArray::::default(); let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); - hkdf.expand(i, &mut key) - .map_err(|_| Error::Internal("invalid length"))?; + hkdf.expand(i, &mut key).map_err(|_| "invalid length")?; Ok(key) } diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden/src/crypto/rsa.rs index f105dbfe2..6feb6ef47 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden/src/crypto/rsa.rs @@ -6,7 +6,7 @@ use rsa::{ use crate::{ crypto::{EncString, SymmetricCryptoKey}, - error::{Error, Result}, + error::Result, util::BASE64_ENGINE, }; @@ -26,12 +26,12 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let spki = pub_key .to_public_key_der() - .map_err(|_| Error::Internal("unable to create public key"))?; + .map_err(|_| "unable to create public key")?; let b64 = BASE64_ENGINE.encode(spki.as_bytes()); let pkcs = priv_key .to_pkcs8_der() - .map_err(|_| Error::Internal("unable to create private key"))?; + .map_err(|_| "unable to create private key")?; let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 6a9b0d8aa..e5560b479 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -1,6 +1,6 @@ //! Errors that can occur when using this SDK -use std::fmt::Debug; +use std::{borrow::Cow, fmt::Debug}; use bitwarden_api_api::apis::Error as ApiError; use bitwarden_api_identity::apis::Error as IdentityError; @@ -47,7 +47,19 @@ pub enum Error { ResponseContent { status: StatusCode, message: String }, #[error("Internal error: {0}")] - Internal(&'static str), + Internal(Cow<'static, str>), +} + +impl From for Error { + fn from(s: String) -> Self { + Self::Internal(s.into()) + } +} + +impl From<&'static str> for Error { + fn from(s: &'static str) -> Self { + Self::Internal(s.into()) + } } #[derive(Debug, Error)] diff --git a/crates/bitwarden/src/platform/get_user_api_key.rs b/crates/bitwarden/src/platform/get_user_api_key.rs index a1cfc389d..994a7a7ab 100644 --- a/crates/bitwarden/src/platform/get_user_api_key.rs +++ b/crates/bitwarden/src/platform/get_user_api_key.rs @@ -62,7 +62,7 @@ fn get_secret_verification_request( auth_request_access_code: None, }) } else { - Err(Error::Internal("Unsupported login method")) + Err("Unsupported login method".into()) } } diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden/src/tool/generators/passphrase.rs index e62fa8f9a..5abad368b 100644 --- a/crates/bitwarden/src/tool/generators/passphrase.rs +++ b/crates/bitwarden/src/tool/generators/passphrase.rs @@ -1,7 +1,4 @@ -use crate::{ - error::{Error, Result}, - wordlist::EFF_LONG_WORD_LIST, -}; +use crate::{error::Result, wordlist::EFF_LONG_WORD_LIST}; use rand::{seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -52,11 +49,11 @@ impl PassphraseGeneratorRequest { if !(MINIMUM_PASSPHRASE_NUM_WORDS..=MAXIMUM_PASSPHRASE_NUM_WORDS).contains(&self.num_words) { - return Err(Error::Internal("'num_words' must be between 3 and 20")); + return Err(format!("'num_words' must be between {MINIMUM_PASSPHRASE_NUM_WORDS} and {MAXIMUM_PASSPHRASE_NUM_WORDS}").into()); } if self.word_separator.chars().next().is_none() { - return Err(Error::Internal("'word_separator' cannot be empty")); + return Err("'word_separator' cannot be empty".into()); }; Ok(ValidPassphraseGeneratorOptions { diff --git a/crates/bitwarden/src/tool/generators/password.rs b/crates/bitwarden/src/tool/generators/password.rs index cf986495c..d091d1a45 100644 --- a/crates/bitwarden/src/tool/generators/password.rs +++ b/crates/bitwarden/src/tool/generators/password.rs @@ -4,7 +4,7 @@ use rand::{distributions::Distribution, seq::SliceRandom, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::error::{Error, Result}; +use crate::error::Result; /// Password generator request options. #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -133,15 +133,11 @@ impl PasswordGeneratorRequest { // We always have to have at least one character set enabled if !self.lowercase && !self.uppercase && !self.numbers && !self.special { - return Err(Error::Internal( - "At least one character set must be enabled", - )); + return Err("At least one character set must be enabled".into()); } if self.length < 4 { - return Err(Error::Internal( - "A password must be at least 4 characters long", - )); + return Err("A password must be at least 4 characters long".into()); } // Make sure the minimum values are zero when the character @@ -163,9 +159,7 @@ impl PasswordGeneratorRequest { // Check that the minimum lengths aren't larger than the password length let minimum_length = min_lowercase + min_uppercase + min_number + min_special; if minimum_length > length { - return Err(Error::Internal( - "Password length can't be less than the sum of the minimums", - )); + return Err("Password length can't be less than the sum of the minimums".into()); } let lower = ( diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 701f142b9..5e25d764e 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -10,7 +10,7 @@ impl UniffiCustomTypeConverter for NonZeroU32 { type Builtin = u32; fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::new(val).ok_or(Error::Internal("Number is zero").into()) + Self::new(val).ok_or(Error::from("Number is zero").into()) } fn from_custom(obj: Self) -> Self::Builtin { diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index e080a85a9..4adbe4dac 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -130,11 +130,11 @@ impl FromStr for Totp { fn decode_secret(secret: &str) -> Result> { BASE32 .decode(secret.as_bytes()) - .map_err(|_| Error::Internal("Unable to decode secret")) + .map_err(|_| "Unable to decode secret".into()) } let params = if key.starts_with("otpauth://") { - let url = Url::parse(key).map_err(|_| Error::Internal("Unable to parse URL"))?; + let url = Url::parse(key).map_err(|_| "Unable to parse URL")?; let parts: HashMap<_, _> = url.query_pairs().collect(); Totp { @@ -161,7 +161,7 @@ impl FromStr for Totp { &parts .get("secret") .map(|v| v.to_string()) - .ok_or(Error::Internal("Missing secret in otpauth URI"))?, + .ok_or("Missing secret in otpauth URI")?, )?, } } else if let Some(secret) = key.strip_prefix("steam://") { From 4c079e85a94320d5b42c88291671acd2cbc7dccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 18 Dec 2023 18:08:41 +0100 Subject: [PATCH 140/378] [PM-3436] Username generator (#285) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement username generation. Some of the methods are shared with password and passphrase generation (like `capitalize_first_letter`, `random_lowercase_string` and the username word generation). To avoid dependencies between the PRs, I included them here again, once we're done with all the generators I'll unify them. --- crates/bitwarden-uniffi/src/tool/mod.rs | 17 +- crates/bitwarden/src/client/client.rs | 5 + .../src/tool/generators/client_generator.rs | 33 ++- crates/bitwarden/src/tool/generators/mod.rs | 3 + .../src/tool/generators/passphrase.rs | 13 +- .../bitwarden/src/tool/generators/username.rs | 244 ++++++++++++++++++ .../generators/username_forwarders/addyio.rs | 143 ++++++++++ .../username_forwarders/duckduckgo.rs | 86 ++++++ .../username_forwarders/fastmail.rs | 188 ++++++++++++++ .../generators/username_forwarders/firefox.rs | 120 +++++++++ .../username_forwarders/forwardemail.rs | 193 ++++++++++++++ .../generators/username_forwarders/mod.rs | 22 ++ .../username_forwarders/simplelogin.rs | 114 ++++++++ crates/bitwarden/src/tool/mod.rs | 5 +- crates/bitwarden/src/util.rs | 12 + 15 files changed, 1180 insertions(+), 18 deletions(-) create mode 100644 crates/bitwarden/src/tool/generators/username.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/mod.rs create mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs diff --git a/crates/bitwarden-uniffi/src/tool/mod.rs b/crates/bitwarden-uniffi/src/tool/mod.rs index 6622a1b2d..6b443618c 100644 --- a/crates/bitwarden-uniffi/src/tool/mod.rs +++ b/crates/bitwarden-uniffi/src/tool/mod.rs @@ -1,7 +1,10 @@ use std::sync::Arc; use bitwarden::{ - tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, + tool::{ + ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest, + UsernameGeneratorRequest, + }, vault::{Cipher, Collection, Folder}, }; @@ -35,6 +38,18 @@ impl ClientGenerators { .passphrase(settings) .await?) } + + /// **API Draft:** Generate Username + pub async fn username(&self, settings: UsernameGeneratorRequest) -> Result { + Ok(self + .0 + .0 + .read() + .await + .generator() + .username(settings) + .await?) + } } #[derive(uniffi::Object)] diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 0c69ba917..bb0f65c09 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -132,6 +132,11 @@ impl Client { &self.__api_configurations } + #[cfg(feature = "mobile")] + pub(crate) fn get_http_client(&self) -> &reqwest::Client { + &self.__api_configurations.api.client + } + #[cfg(feature = "secrets")] #[deprecated(note = "Use auth().login_access_token() instead")] pub async fn access_token_login( diff --git a/crates/bitwarden/src/tool/generators/client_generator.rs b/crates/bitwarden/src/tool/generators/client_generator.rs index 4675ad99d..301383635 100644 --- a/crates/bitwarden/src/tool/generators/client_generator.rs +++ b/crates/bitwarden/src/tool/generators/client_generator.rs @@ -1,12 +1,15 @@ use crate::{ error::Result, - tool::generators::passphrase::{passphrase, PassphraseGeneratorRequest}, - tool::generators::password::{password, PasswordGeneratorRequest}, + tool::generators::{ + passphrase::{passphrase, PassphraseGeneratorRequest}, + password::{password, PasswordGeneratorRequest}, + username::{username, UsernameGeneratorRequest}, + }, Client, }; pub struct ClientGenerator<'a> { - pub(crate) _client: &'a crate::Client, + pub(crate) client: &'a crate::Client, } impl<'a> ClientGenerator<'a> { @@ -59,10 +62,32 @@ impl<'a> ClientGenerator<'a> { pub async fn passphrase(&self, input: PassphraseGeneratorRequest) -> Result { passphrase(input) } + + /// Generates a random username. + /// There are different username generation strategies, which can be customized using the `input` parameter. + /// + /// Note that most generation strategies will be executed on the client side, but `Forwarded` will use third-party + /// services, which may require a specific setup or API key. + /// + /// ``` + /// use bitwarden::{Client, tool::{UsernameGeneratorRequest}, error::Result}; + /// async fn test() -> Result<()> { + /// let input = UsernameGeneratorRequest::Word { + /// capitalize: true, + /// include_number: true, + /// }; + /// let username = Client::new(None).generator().username(input).await.unwrap(); + /// println!("{}", username); + /// Ok(()) + /// } + /// ``` + pub async fn username(&self, input: UsernameGeneratorRequest) -> Result { + username(input, self.client.get_http_client()).await + } } impl<'a> Client { pub fn generator(&'a self) -> ClientGenerator<'a> { - ClientGenerator { _client: self } + ClientGenerator { client: self } } } diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs index 12c526930..7966c58a9 100644 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ b/crates/bitwarden/src/tool/generators/mod.rs @@ -1,7 +1,10 @@ mod client_generator; mod passphrase; mod password; +mod username; +mod username_forwarders; pub use client_generator::ClientGenerator; pub use passphrase::PassphraseGeneratorRequest; pub use password::PasswordGeneratorRequest; +pub use username::{AppendType, ForwarderServiceType, UsernameGeneratorRequest}; diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden/src/tool/generators/passphrase.rs index 5abad368b..7c5c8e434 100644 --- a/crates/bitwarden/src/tool/generators/passphrase.rs +++ b/crates/bitwarden/src/tool/generators/passphrase.rs @@ -1,4 +1,4 @@ -use crate::{error::Result, wordlist::EFF_LONG_WORD_LIST}; +use crate::{error::Result, util::capitalize_first_letter, wordlist::EFF_LONG_WORD_LIST}; use rand::{seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -109,17 +109,6 @@ fn capitalize_words(words: &mut [String]) { .for_each(|w| *w = capitalize_first_letter(w)); } -fn capitalize_first_letter(s: &str) -> String { - // Unicode case conversion can change the length of the string, so we can't capitalize in place. - // Instead we extract the first character and convert it to uppercase. This returns - // an iterator which we collect into a string, and then append the rest of the input. - let mut c = s.chars(); - match c.next() { - None => String::new(), - Some(f) => f.to_uppercase().collect::() + c.as_str(), - } -} - #[cfg(test)] mod tests { use rand::SeedableRng; diff --git a/crates/bitwarden/src/tool/generators/username.rs b/crates/bitwarden/src/tool/generators/username.rs new file mode 100644 index 000000000..666772714 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username.rs @@ -0,0 +1,244 @@ +use crate::{error::Result, util::capitalize_first_letter, wordlist::EFF_LONG_WORD_LIST}; +use rand::{distributions::Distribution, seq::SliceRandom, Rng, RngCore}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum AppendType { + /// Generates a random string of 8 lowercase characters as part of your username + Random, + /// Uses the websitename as part of your username + WebsiteName { website: String }, +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +/// Configures the email forwarding service to use. +/// For instructions on how to configure each service, see the documentation: +/// +pub enum ForwarderServiceType { + /// Previously known as "AnonAddy" + AddyIo { + api_token: String, + domain: String, + base_url: String, + }, + DuckDuckGo { + token: String, + }, + Firefox { + api_token: String, + }, + Fastmail { + api_token: String, + }, + ForwardEmail { + api_token: String, + domain: String, + }, + SimpleLogin { + api_key: String, + }, +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum UsernameGeneratorRequest { + /// Generates a single word username + Word { + /// Capitalize the first letter of the word + capitalize: bool, + /// Include a 4 digit number at the end of the word + include_number: bool, + }, + /// Generates an email using your provider's subaddressing capabilities. + /// Note that not all providers support this functionality. + /// This will generate an address of the format `youremail+generated@domain.tld` + Subaddress { + /// The type of subaddress to add to the base email + r#type: AppendType, + /// The full email address to use as the base for the subaddress + email: String, + }, + Catchall { + /// The type of username to use with the catchall email domain + r#type: AppendType, + /// The domain to use for the catchall email address + domain: String, + }, + Forwarded { + /// The email forwarding service to use, see [ForwarderServiceType] + /// for instructions on how to configure each + service: ForwarderServiceType, + /// The website for which the email address is being generated + /// This is not used in all services, and is only used for display purposes + website: Option, + }, +} + +impl ForwarderServiceType { + // Generate a username using the specified email forwarding service + // This requires an HTTP client to be passed in, as the service will need to make API calls + pub async fn generate(self, http: &reqwest::Client, website: Option) -> Result { + use crate::tool::generators::username_forwarders::*; + use ForwarderServiceType::*; + + match self { + AddyIo { + api_token, + domain, + base_url, + } => addyio::generate(http, api_token, domain, base_url, website).await, + DuckDuckGo { token } => duckduckgo::generate(http, token).await, + Firefox { api_token } => firefox::generate(http, api_token, website).await, + Fastmail { api_token } => fastmail::generate(http, api_token, website).await, + ForwardEmail { api_token, domain } => { + forwardemail::generate(http, api_token, domain, website).await + } + SimpleLogin { api_key } => simplelogin::generate(http, api_key, website).await, + } + } +} + +/// Implementation of the username generator. This is not accessible to the public API. +/// See [`ClientGenerator::username`](crate::ClientGenerator::username) for the API function. +/// Note: The HTTP client is passed in as a required parameter for convenience, +/// as some username generators require making API calls. +pub(super) async fn username( + input: UsernameGeneratorRequest, + http: &reqwest::Client, +) -> Result { + use rand::thread_rng; + use UsernameGeneratorRequest::*; + match input { + Word { + capitalize, + include_number, + } => Ok(username_word(&mut thread_rng(), capitalize, include_number)), + Subaddress { r#type, email } => Ok(username_subaddress(&mut thread_rng(), r#type, email)), + Catchall { r#type, domain } => Ok(username_catchall(&mut thread_rng(), r#type, domain)), + Forwarded { service, website } => service.generate(http, website).await, + } +} + +fn username_word(mut rng: impl RngCore, capitalize: bool, include_number: bool) -> String { + let word = EFF_LONG_WORD_LIST + .choose(&mut rng) + .expect("slice is not empty"); + + let mut word = if capitalize { + capitalize_first_letter(word) + } else { + word.to_string() + }; + + if include_number { + word.push_str(&random_number(&mut rng)); + } + + word +} + +/// Generate a random 4 digit number, including leading zeros +fn random_number(mut rng: impl RngCore) -> String { + let num = rng.gen_range(0..=9999); + format!("{num:0>4}") +} + +/// Generate a username using a plus addressed email address +/// The format is +@ +fn username_subaddress(mut rng: impl RngCore, r#type: AppendType, email: String) -> String { + if email.len() < 3 { + return email; + } + + let (email_begin, email_end) = match email.find('@') { + Some(pos) if pos > 0 && pos < email.len() - 1 => { + email.split_once('@').expect("The email contains @") + } + _ => return email, + }; + + let email_middle = match r#type { + AppendType::Random => random_lowercase_string(&mut rng, 8), + AppendType::WebsiteName { website } => website, + }; + + format!("{}+{}@{}", email_begin, email_middle, email_end) +} + +/// Generate a username using a catchall email address +/// The format is @ +fn username_catchall(mut rng: impl RngCore, r#type: AppendType, domain: String) -> String { + if domain.is_empty() { + return domain; + } + + let email_start = match r#type { + AppendType::Random => random_lowercase_string(&mut rng, 8), + AppendType::WebsiteName { website } => website, + }; + + format!("{}@{}", email_start, domain) +} + +fn random_lowercase_string(mut rng: impl RngCore, length: usize) -> String { + const LOWERCASE_ALPHANUMERICAL: &[u8] = b"abcdefghijklmnopqrstuvwxyz1234567890"; + let dist = rand::distributions::Slice::new(LOWERCASE_ALPHANUMERICAL).expect("Non-empty slice"); + + dist.sample_iter(&mut rng) + .take(length) + .map(|&b| b as char) + .collect() +} + +#[cfg(test)] +mod tests { + use rand::SeedableRng; + + pub use super::*; + + #[test] + fn test_username_word() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + assert_eq!(username_word(&mut rng, true, true), "Subsystem6314"); + assert_eq!(username_word(&mut rng, true, false), "Silenced"); + assert_eq!(username_word(&mut rng, false, true), "dinginess4487"); + } + + #[test] + fn test_username_subaddress() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); + let user = username_subaddress(&mut rng, AppendType::Random, "demo@test.com".into()); + assert_eq!(user, "demo+5wiejdaj@test.com"); + + let user = username_subaddress( + &mut rng, + AppendType::WebsiteName { + website: "bitwarden.com".into(), + }, + "demo@test.com".into(), + ); + assert_eq!(user, "demo+bitwarden.com@test.com"); + } + + #[test] + fn test_username_catchall() { + let mut rng = rand_chacha::ChaCha8Rng::from_seed([1u8; 32]); + let user = username_catchall(&mut rng, AppendType::Random, "test.com".into()); + assert_eq!(user, "k9y6yw7j@test.com"); + + let user = username_catchall( + &mut rng, + AppendType::WebsiteName { + website: "bitwarden.com".into(), + }, + "test.com".into(), + ); + assert_eq!(user, "bitwarden.com@test.com"); + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs b/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs new file mode 100644 index 000000000..0fc5937f6 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs @@ -0,0 +1,143 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::error::Result; +pub async fn generate( + http: &reqwest::Client, + api_token: String, + domain: String, + base_url: String, + website: Option, +) -> Result { + let description = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + domain: String, + description: String, + } + + let response = http + .post(format!("{base_url}/api/v1/aliases")) + .header(CONTENT_TYPE, "application/json") + .bearer_auth(api_token) + .header("X-Requested-With", "XMLHttpRequest") + .json(&Request { + domain, + description, + }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid addy.io API token.".into()); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct ResponseData { + email: String, + } + #[derive(serde::Deserialize)] + struct Response { + data: ResponseData, + } + let response: Response = response.json().await?; + + Ok(response.data.email) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock the request to the addy.io API, and verify that the correct request is made + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "myemail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "data": { + "id": "50c9e585-e7f5-41c4-9016-9014c15454bc", + "user_id": "ca0a4e09-c266-4f6f-845c-958db5090f09", + "local_part": "50c9e585-e7f5-41c4-9016-9014c15454bc", + "domain": "myemail.com", + "email": "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com", + "active": true + } + }))) + .expect(1), + // Mock an invalid API token request + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "myemail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + // Mock an invalid domain + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "gmail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(403)) + .expect(1), + ]) + .await; + + let address = super::generate( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "myemail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap(); + + let fake_token_error = super::generate( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + "myemail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap_err(); + + assert!(fake_token_error + .to_string() + .contains("Invalid addy.io API token.")); + + let fake_domain_error = super::generate( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "gmail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap_err(); + + assert!(fake_domain_error.to_string().contains("403 Forbidden")); + + server.verify().await; + assert_eq!(address, "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com"); + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs b/crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs new file mode 100644 index 000000000..512db7812 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs @@ -0,0 +1,86 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::error::Result; +pub async fn generate(http: &reqwest::Client, token: String) -> Result { + generate_with_api_url(http, token, "https://quack.duckduckgo.com".into()).await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + token: String, + api_url: String, +) -> Result { + let response = http + .post(format!("{api_url}/api/email/addresses")) + .header(CONTENT_TYPE, "application/json") + .bearer_auth(token) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid DuckDuckGo API token".into()); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct Response { + address: String, + } + let response: Response = response.json().await?; + + Ok(format!("{}@duck.com", response.address)) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock the request to the DDG API, and verify that the correct request is made + Mock::given(matchers::path("/api/email/addresses")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "address": "bw7prt" + }))) + .expect(1), + // Mock an invalid token request + Mock::given(matchers::path("/api/email/addresses")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "bw7prt@duck.com"); + + let fake_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(fake_token_error + .to_string() + .contains("Invalid DuckDuckGo API token")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs b/crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs new file mode 100644 index 000000000..d2a7554e2 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs @@ -0,0 +1,188 @@ +use std::collections::HashMap; + +use reqwest::{header::CONTENT_TYPE, StatusCode}; +use serde_json::json; + +use crate::error::Result; +pub async fn generate( + http: &reqwest::Client, + api_token: String, + website: Option, +) -> Result { + generate_with_api_url(http, api_token, website, "https://api.fastmail.com".into()).await +} + +pub async fn generate_with_api_url( + http: &reqwest::Client, + api_token: String, + website: Option, + api_url: String, +) -> Result { + let account_id = get_account_id(http, &api_token, &api_url).await?; + + let response = http + .post(format!("{api_url}/jmap/api/")) + .header(CONTENT_TYPE, "application/json") + .bearer_auth(api_token) + .json(&json!({ + "using": ["https://www.fastmail.com/dev/maskedemail", "urn:ietf:params:jmap:core"], + "methodCalls": [[ + "MaskedEmail/set", { + "accountId": account_id, + "create": { + "new-masked-email": { + "state": "enabled", + "description": "", + "url": website, + "emailPrefix": null, + }, + }, + }, + "0", + ]], + })) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid Fastmail API token".into()); + } + + let response: serde_json::Value = response.json().await?; + let Some(r) = response.get("methodResponses").and_then(|r| r.get(0)) else { + return Err("Unknown Fastmail error occurred.".into()); + }; + let method_response = r.get(0).and_then(|r| r.as_str()); + let response_value = r.get(1); + + if method_response == Some("MaskedEmail/set") { + if let Some(email) = response_value + .and_then(|r| r.get("created")) + .and_then(|r| r.get("new-masked-email")) + .and_then(|r| r.get("email")) + .and_then(|r| r.as_str()) + { + return Ok(email.to_owned()); + }; + + let error_description = response_value + .and_then(|r| r.get("notCreated")) + .and_then(|r| r.get("new-masked-email")) + .and_then(|r| r.get("description")) + .and_then(|r| r.as_str()) + .unwrap_or("Unknown error"); + + return Err(format!("Fastmail error: {error_description}").into()); + } else if method_response == Some("error") { + let error_description = response_value + .and_then(|r| r.get("description")) + .and_then(|r| r.as_str()) + .unwrap_or("Unknown error"); + + return Err(format!("Fastmail error: {error_description}").into()); + } + + Err("Unknown Fastmail error occurred.".into()) +} + +async fn get_account_id( + client: &reqwest::Client, + api_token: &str, + api_url: &str, +) -> Result { + #[derive(serde::Deserialize)] + struct Response { + #[serde(rename = "primaryAccounts")] + primary_accounts: HashMap, + } + let response = client + .get(format!("{api_url}/.well-known/jmap")) + .bearer_auth(api_token) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid Fastmail API token".into()); + } + + response.error_for_status_ref()?; + let mut response: Response = response.json().await?; + + Ok(response + .primary_accounts + .remove("https://www.fastmail.com/dev/maskedemail") + .unwrap_or_default()) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock a valid request to FastMail API + Mock::given(matchers::path("/.well-known/jmap")) + .and(matchers::method("GET")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "primaryAccounts": { + "https://www.fastmail.com/dev/maskedemail": "ca0a4e09-c266-4f6f-845c-958db5090f09" + } + }))) + .expect(1), + + Mock::given(matchers::path("/jmap/api/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "methodResponses": [ + ["MaskedEmail/set", {"created": {"new-masked-email": {"email": "9f823dq23d123ds@mydomain.com"}}}] + ] + }))) + .expect(1), + + // Mock an invalid token request + Mock::given(matchers::path("/.well-known/jmap")) + .and(matchers::method("GET")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + + Mock::given(matchers::path("/jmap/api/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(201)) + .expect(0), + ]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "9f823dq23d123ds@mydomain.com"); + + let fake_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(fake_token_error + .to_string() + .contains("Invalid Fastmail API token")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs b/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs new file mode 100644 index 000000000..2c45803a5 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs @@ -0,0 +1,120 @@ +use reqwest::{ + header::{self}, + StatusCode, +}; + +use crate::error::Result; + +pub async fn generate( + http: &reqwest::Client, + api_token: String, + website: Option, +) -> Result { + generate_with_api_url(http, api_token, website, "https://relay.firefox.com".into()).await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + api_token: String, + website: Option, + api_url: String, +) -> Result { + #[derive(serde::Serialize)] + struct Request { + enabled: bool, + generated_for: Option, + description: String, + } + + let description = super::format_description_ff(&website); + + let response = http + .post(format!("{api_url}/api/v1/relayaddresses/")) + .header(header::AUTHORIZATION, format!("Token {api_token}")) + .json(&Request { + enabled: true, + generated_for: website, + description, + }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid Firefox Relay API key".into()); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct Response { + full_address: String, + } + let response: Response = response.json().await?; + + Ok(response.full_address) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock the request to the Firefox API, and verify that the correct request is made + Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "generated_for": "example.com", + "description": "example.com - Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "full_address": "ofuj4d4qw@mozmail.com" + }))) + .expect(1), + // Mock an invalid API key + Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "generated_for": "example.com", + "description": "example.com - Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "ofuj4d4qw@mozmail.com"); + + let fake_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(fake_token_error + .to_string() + .contains("Invalid Firefox Relay API key")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs b/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs new file mode 100644 index 000000000..f4ba6ced6 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs @@ -0,0 +1,193 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::error::{Error, Result}; + +pub async fn generate( + http: &reqwest::Client, + api_token: String, + domain: String, + website: Option, +) -> Result { + generate_with_api_url( + http, + api_token, + domain, + website, + "https://api.forwardemail.net".into(), + ) + .await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + api_token: String, + domain: String, + website: Option, + api_url: String, +) -> Result { + let description = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + labels: Option, + description: String, + } + + let response = http + .post(format!("{api_url}/v1/domains/{domain}/aliases")) + .header(CONTENT_TYPE, "application/json") + .basic_auth(api_token, None::) + .json(&Request { + description, + labels: website, + }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid Forward Email API key.".into()); + } + + #[derive(serde::Deserialize)] + struct ResponseDomain { + name: Option, + } + #[derive(serde::Deserialize)] + struct Response { + name: Option, + domain: Option, + + message: Option, + error: Option, + } + let status = response.status(); + let response: Response = response.json().await?; + + if status.is_success() { + if let Some(name) = response.name { + if let Some(response_domain) = response.domain { + return Ok(format!( + "{}@{}", + name, + response_domain.name.unwrap_or(domain) + )); + } + } + } + + if let Some(message) = response.message { + return Err(Error::ResponseContent { status, message }); + } + if let Some(message) = response.error { + return Err(Error::ResponseContent { status, message }); + } + + Err("Unknown ForwardEmail error.".into()) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock the request to the ForwardEmail API, and verify that the correct request is made + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Basic TVlfVE9LRU46")) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "name": "wertg8ad", + "domain": { + "name": "mydomain.com" + } + }))) + .expect(1), + // Mock an invalid API token request + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header( + "Authorization", + "Basic TVlfRkFLRV9UT0tFTjo=", + )) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401).set_body_json(json!({ + "statusCode": 401, + "error": "Unauthorized", + "message": "Invalid API token." + }))) + .expect(1), + // Mock a free API token request + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header( + "Authorization", + "Basic TVlfRlJFRV9UT0tFTjo=", + )) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(402).set_body_json(json!({ + "statusCode": 402, + "error": "Payment required", + "message": "Please upgrade to a paid plan to unlock this feature." + }))) + .expect(1), + ]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "wertg8ad@mydomain.com"); + + let invalid_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(invalid_token_error + .to_string() + .contains("Invalid Forward Email API key.")); + + let free_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FREE_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(free_token_error + .to_string() + .contains("Please upgrade to a paid plan")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/mod.rs b/crates/bitwarden/src/tool/generators/username_forwarders/mod.rs new file mode 100644 index 000000000..8d445bc04 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/mod.rs @@ -0,0 +1,22 @@ +pub(super) mod addyio; +pub(super) mod duckduckgo; +pub(super) mod fastmail; +pub(super) mod firefox; +pub(super) mod forwardemail; +pub(super) mod simplelogin; + +fn format_description(website: &Option) -> String { + let description = website + .as_ref() + .map(|w| format!("Website: {w}. ")) + .unwrap_or_default(); + format!("{description}Generated by Bitwarden.") +} + +fn format_description_ff(website: &Option) -> String { + let description = website + .as_ref() + .map(|w| format!("{w} - ")) + .unwrap_or_default(); + format!("{description}Generated by Bitwarden.") +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs b/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs new file mode 100644 index 000000000..3c09fc691 --- /dev/null +++ b/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs @@ -0,0 +1,114 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::error::Result; + +pub async fn generate( + http: &reqwest::Client, + api_key: String, + website: Option, +) -> Result { + generate_with_api_url(http, api_key, website, "https://app.simplelogin.io".into()).await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + api_key: String, + website: Option, + api_url: String, +) -> Result { + let query = website + .as_ref() + .map(|w| format!("?hostname={}", w)) + .unwrap_or_default(); + + let note = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + note: String, + } + + let response = http + .post(format!("{api_url}/api/alias/random/new{query}")) + .header(CONTENT_TYPE, "application/json") + .bearer_auth(api_key) + .json(&Request { note }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err("Invalid SimpleLogin API key.".into()); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct Response { + alias: String, + } + let response: Response = response.json().await?; + + Ok(response.alias) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = crate::util::start_mock(vec![ + // Mock the request to the SimpleLogin API, and verify that the correct request is made + Mock::given(matchers::path("/api/alias/random/new")) + .and(matchers::method("POST")) + .and(matchers::query_param("hostname", "example.com")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::body_json(json!({ + "note": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "alias": "simplelogin.yut3g8@aleeas.com", + }))) + .expect(1), + // Mock an invalid token request + Mock::given(matchers::path("/api/alias/random/new")) + .and(matchers::method("POST")) + .and(matchers::query_param("hostname", "example.com")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "note": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "simplelogin.yut3g8@aleeas.com"); + + let fake_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + assert!(fake_token_error + .to_string() + .contains("Invalid SimpleLogin API key.")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/mod.rs b/crates/bitwarden/src/tool/mod.rs index 212ce4bf7..fe41b68db 100644 --- a/crates/bitwarden/src/tool/mod.rs +++ b/crates/bitwarden/src/tool/mod.rs @@ -2,4 +2,7 @@ mod exporters; mod generators; pub use exporters::{ClientExporters, ExportFormat}; -pub use generators::{ClientGenerator, PassphraseGeneratorRequest, PasswordGeneratorRequest}; +pub use generators::{ + AppendType, ClientGenerator, ForwarderServiceType, PassphraseGeneratorRequest, + PasswordGeneratorRequest, UsernameGeneratorRequest, +}; diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index b6c8465ec..4dbe21ca6 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -28,6 +28,18 @@ const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() pub const BASE64_ENGINE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); +#[cfg(feature = "mobile")] +pub(crate) fn capitalize_first_letter(s: &str) -> String { + // Unicode case conversion can change the length of the string, so we can't capitalize in place. + // Instead we extract the first character and convert it to uppercase. This returns + // an iterator which we collect into a string, and then append the rest of the input. + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + #[cfg(test)] pub async fn start_mock(mocks: Vec) -> (wiremock::MockServer, crate::Client) { let server = wiremock::MockServer::start().await; From a5328e5f86fa5fc5c225f539b850bd758bf3a366 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Mon, 18 Dec 2023 12:59:52 -0500 Subject: [PATCH 141/378] Update version bump workflow (#434) --- .github/workflows/version-bump.yml | 42 +++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 4fb83ae8c..fae8b0bc5 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -3,16 +3,6 @@ name: Version Bump run-name: Version Bump - v${{ inputs.version_number }} on: - workflow_call: - inputs: - project: - description: "Project" - required: true - type: string - version_number: - description: "New version (example: '2024.1.0')" - required: true - type: string workflow_dispatch: inputs: project: @@ -29,6 +19,10 @@ on: version_number: description: "New version (example: '2024.1.0')" required: true + cut_rc_branch: + description: "Cut RC branch?" + default: true + type: boolean jobs: bump_version: @@ -63,9 +57,8 @@ jobs: - name: Checkout Branch uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - repository: bitwarden/sdk ref: main - token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + repository: bitwarden/sdk - name: Import GPG key uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 @@ -206,3 +199,28 @@ jobs: GH_TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} run: gh pr merge $PR_NUMBER --squash --auto --delete-branch + + cut_rc: + name: Cut RC branch + needs: bump_version + if: ${{ inputs.cut_rc_branch == true }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout Branch + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: main + + - name: Check if RC branch exists + run: | + remote_rc_branch_check=$(git ls-remote --heads origin rc | wc -l) + if [[ "${remote_rc_branch_check}" -gt 0 ]]; then + echo "Remote RC branch exists." + echo "Please delete current RC branch before running again." + exit 1 + fi + + - name: Cut RC branch + run: | + git switch --quiet --create rc + git push --quiet --set-upstream origin rc From fd0659ebba00169655b7ce265fcf8eb418b083f7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:06:03 -0500 Subject: [PATCH 142/378] [deps]: Update actions/upload-artifact action to v4 (#444) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-cli.yml | 6 +++--- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/generate_schemas.yml | 14 +++++++------- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 424d048e9..7ac229535 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -46,7 +46,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index c8b1e97dd..408015860 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -99,7 +99,7 @@ jobs: run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip @@ -142,7 +142,7 @@ jobs: run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws - name: Upload artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip path: ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip @@ -177,7 +177,7 @@ jobs: sed -i.bak 's/\$NAME\$/Bitwarden Secrets Manager CLI/g' THIRDPARTY.html - name: Upload artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: THIRDPARTY.html path: ./crates/bws/THIRDPARTY.html diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 91f21210b..8794a50a8 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -71,7 +71,7 @@ jobs: working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: Bitwarden.Sdk.0.0.1.nupkg path: | diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 96d96fb8c..1c009f8da 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -84,7 +84,7 @@ jobs: run: ${{ matrix.settings.build }} - name: Upload artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: sdk-bitwarden-napi-${{ matrix.settings.target }} path: ${{ github.workspace }}/crates/bitwarden-napi/sdk-napi.*.node diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 39039359f..8999295a2 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -41,7 +41,7 @@ jobs: run: cargo build --target ${{ matrix.settings.target }} --release - name: Upload Artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: libbitwarden_c_files-${{ matrix.settings.target }} path: | diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 807da7520..93904b2a6 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -37,48 +37,48 @@ jobs: run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: schemas.ts path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: schemas.cs path: ${{ github.workspace }}/languages/csharp/Bitwarden.Sdk/schemas.cs if-no-files-found: error - name: Upload python schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* From 214142206cdee259f4c1c0305f0d0274aac71746 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:06:27 -0500 Subject: [PATCH 143/378] [deps]: Update actions/download-artifact action to v4 (#443) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-cli.yml | 4 ++-- .github/workflows/build-dotnet.yml | 10 +++++----- .github/workflows/build-java.yml | 10 +++++----- .github/workflows/build-napi.yml | 2 +- .github/workflows/publish-dotnet.yml | 10 +++++----- .github/workflows/publish-php.yml | 8 ++++---- .github/workflows/publish-ruby.yml | 10 +++++----- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 7ac229535..f1c956944 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -86,7 +86,7 @@ jobs: java-version: 17 - name: Download Artifacts - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 - name: Move artifacts working-directory: languages/kotlin/sdk/src/main/jniLibs diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 408015860..eef2d84b5 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -118,12 +118,12 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: bws-x86_64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip - name: Download aarch64-apple-darwin artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: bws-aarch64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 8794a50a8..a7cad42c0 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -35,25 +35,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 663f0d493..9534b51ac 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download Java schemas artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: sdk-schemas-java path: languages/java/src/main/java/bit/sdk/schema/ @@ -36,25 +36,25 @@ jobs: java-version: 17 - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/java/src/main/resources/darwin-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/java/src/main/resources/darwin-aarch64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/java/src/main/resources/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/java/src/main/resources/windows-x64 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 1c009f8da..a08bb8b04 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -72,7 +72,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: schemas.ts path: ${{ github.workspace }}/crates/bitwarden-napi/src-ts/bitwarden_client/ diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index b52656de2..e9b1076fe 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -37,25 +37,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index ef03eca4a..c9d88a29e 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -33,25 +33,25 @@ jobs: working-directory: languages/php/ - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index c7d5ded20..3ed03fadc 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -28,31 +28,31 @@ jobs: ruby-version: 3.2 - name: Download Ruby schemas artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: schemas.rb path: languages/ruby/bitwarden_sdk/lib - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 From 65df2ede079117e4bc2f5e18999b6a3fc9838ba6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 13:11:58 -0500 Subject: [PATCH 144/378] [deps]: Update gh minor (#440) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-java.yml | 2 +- .github/workflows/build-napi.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-ruby.yml | 2 +- .github/workflows/release-napi.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index f1c956944..2171fb515 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -102,7 +102,7 @@ jobs: run: ./build-schemas.sh - name: Publish - uses: gradle/gradle-build-action@87a9a15658c426a54dd469d4fc7dc1a73ca9d4a6 # v2.10.0 + uses: gradle/gradle-build-action@8cbcb9948b5892387aed077daf6f90e1f0ba5b27 # v2.11.0 with: arguments: sdk:publish build-root-directory: languages/kotlin diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 9534b51ac..a2c0938ec 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -60,7 +60,7 @@ jobs: path: languages/java/src/main/resources/windows-x64 - name: Publish Maven - uses: gradle/gradle-build-action@87a9a15658c426a54dd469d4fc7dc1a73ca9d4a6 # v2.10.0 + uses: gradle/gradle-build-action@8cbcb9948b5892387aed077daf6f90e1f0ba5b27 # v2.11.0 with: arguments: publish build-root-directory: languages/java diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index a08bb8b04..39674c2ea 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -54,7 +54,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version: 18 cache: "npm" diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 93904b2a6..53bbf34e3 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -21,7 +21,7 @@ jobs: toolchain: stable - name: Set up Node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0d2dbed91..f11ff4ced 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -31,7 +31,7 @@ jobs: run: cargo fmt --check - name: Set up Node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 3ed03fadc..01f6be58d 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@8575951200e472d5f2d95c625da0c7bec8217c42 # v1.161.0 + uses: ruby/setup-ruby@af848b40be8bb463a751551a1180d74782ba8a72 # v1.162.0 with: ruby-version: 3.2 diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 19595832a..57498c681 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -93,7 +93,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version: 18 cache: "npm" From 9d4ec76d2811bf4d2e52b7a0d0cba029f3ba42c6 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Mon, 18 Dec 2023 13:27:40 -0500 Subject: [PATCH 145/378] SM-866: Add state to the SDK & BWS CLI (#388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective This PR adds the ability to manage basic state via the SDK. It also updates the `bws` crate to use this SDK change, implementing basic state management for auth tokens. The core benefit is that reauthentication per command will no longer be needed, so that server auth requests will be mitigated. ## Code changes _(to be added)_ - **file.ext:** Description of what was changed and why ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --------- Co-authored-by: Oscar Hinton Co-authored-by: Daniel García --- crates/bitwarden/CHANGELOG.md | 5 ++ crates/bitwarden/README.md | 2 +- crates/bitwarden/src/auth/client_auth.rs | 3 +- .../bitwarden/src/auth/login/access_token.rs | 63 ++++++++++++++++++- crates/bitwarden/src/auth/renew.rs | 28 +++++++-- crates/bitwarden/src/client/client.rs | 9 ++- crates/bitwarden/src/error.rs | 6 ++ crates/bitwarden/src/lib.rs | 2 +- crates/bitwarden/src/secrets_manager/mod.rs | 1 + crates/bitwarden/src/secrets_manager/state.rs | 52 +++++++++++++++ crates/bws/CHANGELOG.md | 2 + crates/bws/src/config.rs | 6 +- crates/bws/src/main.rs | 13 +++- crates/bws/src/state.rs | 18 ++++++ 14 files changed, 195 insertions(+), 15 deletions(-) create mode 100644 crates/bitwarden/src/secrets_manager/state.rs create mode 100644 crates/bws/src/state.rs diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index 8bb18ff72..1341eef68 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,6 +7,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Support for basic state to avoid reauthenticating when creating a new `Client`. This is a breaking + change because of adding `state_file` to the `AccessTokenLoginRequest` struct. (#388) + ### Deprecated - `client.access_token_login()` is now deprecated and will be removed in a future release. Please diff --git a/crates/bitwarden/README.md b/crates/bitwarden/README.md index 67c347583..abb2b5dd4 100644 --- a/crates/bitwarden/README.md +++ b/crates/bitwarden/README.md @@ -41,7 +41,7 @@ async fn test() -> Result<()> { let mut client = Client::new(Some(settings)); // Before we operate, we need to authenticate with a token - let token = AccessTokenLoginRequest { access_token: String::from("") }; + let token = AccessTokenLoginRequest { access_token: String::from(""), state_file: None }; client.auth().login_access_token(&token).await.unwrap(); let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 3c096835a..6c9ddbd4d 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -170,7 +170,8 @@ mod tests { .auth() .login_access_token(&AccessTokenLoginRequest { access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), - }) + state_file: None, + },) .await .unwrap(); assert!(res.authenticated); diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index ed664437d..2e11035c6 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,6 +1,10 @@ +use std::path::{Path, PathBuf}; + use base64::Engine; +use chrono::Utc; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use uuid::Uuid; use crate::{ auth::{ @@ -11,6 +15,7 @@ use crate::{ client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, + secrets_manager::state::{self, ClientState}, util::BASE64_ENGINE, Client, }; @@ -24,6 +29,25 @@ pub(crate) async fn login_access_token( let access_token: AccessToken = input.access_token.parse()?; + if let Some(state_file) = &input.state_file { + if let Ok(organization_id) = load_tokens_from_state(client, state_file, &access_token) { + client.set_login_method(LoginMethod::ServiceAccount( + ServiceAccountLoginMethod::AccessToken { + access_token, + organization_id, + state_file: Some(state_file.to_path_buf()), + }, + )); + + return Ok(AccessTokenLoginResponse { + authenticated: true, + reset_master_password: false, + force_password_reset: false, + two_factor: None, + }); + } + } + let response = request_access_token(client, &access_token).await?; if let IdentityTokenResponse::Payload(r) = &response { @@ -40,9 +64,7 @@ pub(crate) async fn login_access_token( } let payload: Payload = serde_json::from_slice(&decrypted_payload)?; - - let encryption_key = BASE64_ENGINE.decode(payload.encryption_key)?; - + let encryption_key = BASE64_ENGINE.decode(payload.encryption_key.clone())?; let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; let access_token_obj: JWTToken = r.access_token.parse()?; @@ -54,6 +76,11 @@ pub(crate) async fn login_access_token( .parse() .map_err(|_| Error::InvalidResponse)?; + if let Some(state_file) = &input.state_file { + let state = ClientState::new(r.access_token.clone(), payload.encryption_key); + _ = state::set(state_file, &access_token, state); + } + client.set_tokens( r.access_token.clone(), r.refresh_token.clone(), @@ -63,6 +90,7 @@ pub(crate) async fn login_access_token( ServiceAccountLoginMethod::AccessToken { access_token, organization_id, + state_file: input.state_file.clone(), }, )); @@ -82,12 +110,41 @@ async fn request_access_token( .await } +fn load_tokens_from_state( + client: &mut Client, + state_file: &Path, + access_token: &AccessToken, +) -> Result { + let client_state = state::get(state_file, access_token)?; + + let token: JWTToken = client_state.token.parse()?; + + if let Some(organization_id) = token.organization { + let time_till_expiration = (token.exp as i64) - Utc::now().timestamp(); + + if time_till_expiration > 0 { + let organization_id: Uuid = organization_id + .parse() + .map_err(|_| "Bad organization id.")?; + let encryption_key: SymmetricCryptoKey = client_state.encryption_key.parse()?; + + client.set_tokens(client_state.token, None, time_till_expiration as u64); + client.initialize_crypto_single_key(encryption_key); + + return Ok(organization_id); + } + } + + Err(Error::InvalidStateFile) +} + /// Login to Bitwarden with access token #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct AccessTokenLoginRequest { /// Bitwarden service API access token pub access_token: String, + pub state_file: Option, } #[derive(Serialize, Deserialize, Debug, JsonSchema)] diff --git a/crates/bitwarden/src/auth/renew.rs b/crates/bitwarden/src/auth/renew.rs index fe1920e62..6f93f7482 100644 --- a/crates/bitwarden/src/auth/renew.rs +++ b/crates/bitwarden/src/auth/renew.rs @@ -6,12 +6,13 @@ use crate::{ auth::api::{request::AccessTokenRequest, response::IdentityTokenResponse}, client::{Client, LoginMethod, ServiceAccountLoginMethod}, error::{Error, Result}, + secrets_manager::state::{self, ClientState}, }; pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { const TOKEN_RENEW_MARGIN_SECONDS: i64 = 5 * 60; - if let (Some(expires), Some(login_method)) = (&client.token_expires_in, &client.login_method) { + if let (Some(expires), Some(login_method)) = (&client.token_expires_on, &client.login_method) { if Utc::now().timestamp() < expires - TOKEN_RENEW_MARGIN_SECONDS { return Ok(()); } @@ -43,13 +44,32 @@ pub(crate) async fn renew_token(client: &mut Client) -> Result<()> { } }, LoginMethod::ServiceAccount(s) => match s { - ServiceAccountLoginMethod::AccessToken { access_token, .. } => { - AccessTokenRequest::new( + ServiceAccountLoginMethod::AccessToken { + access_token, + state_file, + .. + } => { + let result = AccessTokenRequest::new( access_token.access_token_id, &access_token.client_secret, ) .send(&client.__api_configurations) - .await? + .await?; + + if let ( + IdentityTokenResponse::Authenticated(r), + Some(state_file), + Ok(enc_settings), + ) = (&result, state_file, client.get_encryption_settings()) + { + if let Some(enc_key) = enc_settings.get_key(&None) { + let state = + ClientState::new(r.access_token.clone(), enc_key.to_base64()); + _ = state::set(state_file, access_token, state); + } + } + + result } }, }; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index bb0f65c09..1057532a6 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -62,6 +64,7 @@ pub(crate) enum ServiceAccountLoginMethod { AccessToken { access_token: AccessToken, organization_id: Uuid, + state_file: Option, }, } @@ -69,7 +72,7 @@ pub(crate) enum ServiceAccountLoginMethod { pub struct Client { token: Option, pub(crate) refresh_token: Option, - pub(crate) token_expires_in: Option, + pub(crate) token_expires_on: Option, pub(crate) login_method: Option, /// Use Client::get_api_configurations() to access this. @@ -114,7 +117,7 @@ impl Client { Self { token: None, refresh_token: None, - token_expires_in: None, + token_expires_on: None, login_method: None, __api_configurations: ApiConfigurations { identity, @@ -193,7 +196,7 @@ impl Client { ) { self.token = Some(token.clone()); self.refresh_token = refresh_token; - self.token_expires_in = Some(Utc::now().timestamp() + expires_in as i64); + self.token_expires_on = Some(Utc::now().timestamp() + expires_in as i64); self.__api_configurations.identity.oauth_access_token = Some(token.clone()); self.__api_configurations.api.oauth_access_token = Some(token); } diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index e5560b479..ede8ef806 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -46,6 +46,12 @@ pub enum Error { #[error("Received error message from server: [{}] {}", .status, .message)] ResponseContent { status: StatusCode, message: String }, + #[error("The state file version is invalid")] + InvalidStateFileVersion, + + #[error("The state file could not be read")] + InvalidStateFile, + #[error("Internal error: {0}")] Internal(Cow<'static, str>), } diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index 0017ecff9..a8dd60399 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -38,7 +38,7 @@ //! let mut client = Client::new(Some(settings)); //! //! // Before we operate, we need to authenticate with a token -//! let token = AccessTokenLoginRequest { access_token: String::from("") }; +//! let token = AccessTokenLoginRequest { access_token: String::from(""), state_file: None }; //! client.auth().login_access_token(&token).await.unwrap(); //! //! let org_id = SecretIdentifiersRequest { organization_id: Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() }; diff --git a/crates/bitwarden/src/secrets_manager/mod.rs b/crates/bitwarden/src/secrets_manager/mod.rs index 27b84121e..181edf6b6 100644 --- a/crates/bitwarden/src/secrets_manager/mod.rs +++ b/crates/bitwarden/src/secrets_manager/mod.rs @@ -1,5 +1,6 @@ pub mod projects; pub mod secrets; +pub mod state; mod client_projects; mod client_secrets; diff --git a/crates/bitwarden/src/secrets_manager/state.rs b/crates/bitwarden/src/secrets_manager/state.rs new file mode 100644 index 000000000..d39603d34 --- /dev/null +++ b/crates/bitwarden/src/secrets_manager/state.rs @@ -0,0 +1,52 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + client::AccessToken, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, + error::{Error, Result}, +}; +use std::{fmt::Debug, path::Path}; + +const STATE_VERSION: u32 = 1; + +#[cfg(feature = "secrets")] +#[derive(Serialize, Deserialize, Debug)] +pub struct ClientState { + pub(crate) version: u32, + pub(crate) token: String, + pub(crate) encryption_key: String, +} + +impl ClientState { + pub fn new(token: String, encryption_key: String) -> Self { + Self { + version: STATE_VERSION, + token, + encryption_key, + } + } +} + +pub fn get(state_file: &Path, access_token: &AccessToken) -> Result { + let file_content = std::fs::read_to_string(state_file)?; + + let encrypted_state: EncString = file_content.parse()?; + let decrypted_state: String = encrypted_state.decrypt_with_key(&access_token.encryption_key)?; + let client_state: ClientState = serde_json::from_str(&decrypted_state)?; + + if client_state.version != STATE_VERSION { + return Err(Error::InvalidStateFileVersion); + } + + Ok(client_state) +} + +pub fn set(state_file: &Path, access_token: &AccessToken, state: ClientState) -> Result<()> { + let serialized_state: String = serde_json::to_string(&state)?; + let encrypted_state: EncString = + serialized_state.encrypt_with_key(&access_token.encryption_key)?; + let state_string: String = encrypted_state.to_string(); + + std::fs::write(state_file, state_string) + .map_err(|_| "Failure writing to the state file.".into()) +} diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 3ae1d9009..30db20a04 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -10,6 +10,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - Ability to output secrets in an `env` format with `bws` (#320) +- Basic state to avoid reauthenticating every run, used when setting the `state_file_dir` key in the + config (#388) ## [0.3.1] - 2023-10-13 diff --git a/crates/bws/src/config.rs b/crates/bws/src/config.rs index ecad2f6a5..0ea1259f9 100644 --- a/crates/bws/src/config.rs +++ b/crates/bws/src/config.rs @@ -19,6 +19,7 @@ pub(crate) struct Profile { pub server_base: Option, pub server_api: Option, pub server_identity: Option, + pub state_file_dir: Option, } // TODO: This could probably be derived with a macro if we start adding more fields @@ -28,6 +29,7 @@ pub(crate) enum ProfileKey { server_base, server_api, server_identity, + state_file_dir, } impl ProfileKey { @@ -36,6 +38,7 @@ impl ProfileKey { ProfileKey::server_base => p.server_base = Some(value), ProfileKey::server_api => p.server_api = Some(value), ProfileKey::server_identity => p.server_identity = Some(value), + ProfileKey::state_file_dir => p.state_file_dir = Some(value), } } } @@ -43,7 +46,7 @@ impl ProfileKey { pub(crate) const FILENAME: &str = "config"; pub(crate) const DIRECTORY: &str = ".bws"; -fn get_config_path(config_file: Option<&Path>, ensure_folder_exists: bool) -> PathBuf { +pub(crate) fn get_config_path(config_file: Option<&Path>, ensure_folder_exists: bool) -> PathBuf { let config_file = config_file.map(ToOwned::to_owned).unwrap_or_else(|| { let base_dirs = BaseDirs::new().unwrap(); base_dirs.home_dir().join(DIRECTORY).join(FILENAME) @@ -118,6 +121,7 @@ impl Profile { server_base: Some(url.to_string()), server_api: None, server_identity: None, + state_file_dir: None, }) } pub(crate) fn api_url(&self) -> Result { diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 22e3b5dcd..117186663 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -21,6 +21,7 @@ use log::error; mod config; mod render; +mod state; use config::ProfileKey; use render::{serialize_response, Color, Output}; @@ -302,6 +303,7 @@ async fn process_commands() -> Result<()> { Some(key) => key, None => bail!("Missing access token"), }; + let access_token_obj: AccessToken = access_token.parse()?; let profile = get_config_profile( &cli.server_url, @@ -311,6 +313,7 @@ async fn process_commands() -> Result<()> { )?; let settings = profile + .clone() .map(|p| -> Result<_> { Ok(ClientSettings { identity_url: p.identity_url()?, @@ -320,12 +323,20 @@ async fn process_commands() -> Result<()> { }) .transpose()?; + let state_file_path = state::get_state_file_path( + profile.and_then(|p| p.state_file_dir).map(Into::into), + access_token_obj.access_token_id.to_string(), + ); + let mut client = bitwarden::Client::new(settings); // Load session or return if no session exists let _ = client .auth() - .login_access_token(&AccessTokenLoginRequest { access_token }) + .login_access_token(&AccessTokenLoginRequest { + access_token, + state_file: state_file_path, + }) .await?; let organization_id = match client.get_access_token_organization() { diff --git a/crates/bws/src/state.rs b/crates/bws/src/state.rs new file mode 100644 index 000000000..ef0ef07e2 --- /dev/null +++ b/crates/bws/src/state.rs @@ -0,0 +1,18 @@ +use std::path::PathBuf; + +pub(crate) fn get_state_file_path( + state_file_dir: Option, + access_token_id: String, +) -> Option { + if let Some(mut state_file_path) = state_file_dir { + state_file_path.push(access_token_id); + + if let Some(parent_folder) = state_file_path.parent() { + std::fs::create_dir_all(parent_folder).unwrap(); + } + + return Some(state_file_path); + } + + None +} From f3d200f3428341f703b52a28fa79eabe1d3b465d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 19 Dec 2023 10:52:58 +0100 Subject: [PATCH 146/378] Change attachment key to EncString (#449) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Change `AttachmentView` key to be an `EncString`, and skip decrypting it. This is to avoid a uniffi issue with the representation of Vec on Android. Note that this is very similar to what we're doing with Sends, where we don't decrypt the key on the model either until we're ready to decrypt the file. --- crates/bitwarden/src/vault/cipher/attachment.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index ace4937da..e2d11f592 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -28,7 +28,7 @@ pub struct AttachmentView { pub size: Option, pub size_name: Option, pub file_name: Option, - pub key: Option>, // TODO: Should be made into SymmetricCryptoKey + pub key: Option, } impl KeyEncryptable for AttachmentView { @@ -39,7 +39,7 @@ impl KeyEncryptable for AttachmentView { size: self.size, size_name: self.size_name, file_name: self.file_name.encrypt_with_key(key)?, - key: self.key.as_deref().encrypt_with_key(key)?, + key: self.key, }) } } @@ -52,7 +52,7 @@ impl KeyDecryptable for Attachment { size: self.size.clone(), size_name: self.size_name.clone(), file_name: self.file_name.decrypt_with_key(key)?, - key: self.key.decrypt_with_key(key)?, + key: self.key.clone(), }) } } From 1067d35508852f2dc92a26545659f563a53ac422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 19 Dec 2023 16:04:47 +0100 Subject: [PATCH 147/378] Split EncString for asymmetric support (#448) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Split `EncString` into an asymmetric variant. I've left the symmetric variant with the name `EncString` as it's the most common variant to avoid major changes. This is somewhat related to #447 and should be merged first so that PR can take advantage of the symm/asymm separation. I've moved the `EncString` files into their own folder to organize the crypto directory a bit better too. --- crates/bitwarden/src/client/client.rs | 4 +- .../src/client/encryption_settings.rs | 6 +- .../src/crypto/enc_string/asymmetric.rs | 256 ++++++++++++++++++ crates/bitwarden/src/crypto/enc_string/mod.rs | 80 ++++++ .../symmetric.rs} | 232 +--------------- crates/bitwarden/src/crypto/mod.rs | 2 +- crates/bitwarden/src/error.rs | 6 +- crates/bitwarden/src/mobile/crypto.rs | 4 +- crates/bitwarden/src/uniffi_support.rs | 20 +- 9 files changed, 379 insertions(+), 231 deletions(-) create mode 100644 crates/bitwarden/src/crypto/enc_string/asymmetric.rs create mode 100644 crates/bitwarden/src/crypto/enc_string/mod.rs rename crates/bitwarden/src/crypto/{enc_string.rs => enc_string/symmetric.rs} (52%) diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 1057532a6..272d4210a 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -9,7 +9,7 @@ use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ client::kdf::Kdf, - crypto::EncString, + crypto::{AsymmEncString, EncString}, platform::{ generate_fingerprint, get_user_api_key, sync, FingerprintRequest, FingerprintResponse, SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, @@ -275,7 +275,7 @@ impl Client { #[cfg(feature = "internal")] pub(crate) fn initialize_org_crypto( &mut self, - org_keys: Vec<(Uuid, EncString)>, + org_keys: Vec<(Uuid, AsymmEncString)>, ) -> Result<&EncryptionSettings> { let enc = self .encryption_settings diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index f56932700..d7321aeb4 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -6,7 +6,7 @@ use uuid::Uuid; use { crate::{ client::UserLoginMethod, - crypto::{EncString, KeyDecryptable}, + crypto::{AsymmEncString, EncString, KeyDecryptable}, error::{CryptoError, Result}, }, rsa::pkcs8::DecodePrivateKey, @@ -84,7 +84,7 @@ impl EncryptionSettings { #[cfg(feature = "internal")] pub(crate) fn set_org_keys( &mut self, - org_enc_keys: Vec<(Uuid, EncString)>, + org_enc_keys: Vec<(Uuid, AsymmEncString)>, ) -> Result<&mut Self> { use crate::error::Error; @@ -96,7 +96,7 @@ impl EncryptionSettings { // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { - let dec = org_enc_key.decrypt_with_private_key(private_key)?; + let dec = org_enc_key.decrypt(private_key)?; let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?; diff --git a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs new file mode 100644 index 000000000..f90315afa --- /dev/null +++ b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs @@ -0,0 +1,256 @@ +use std::{fmt::Display, str::FromStr}; + +use base64::Engine; +#[cfg(feature = "internal")] +use rsa::{Oaep, RsaPrivateKey}; +use serde::Deserialize; + +use crate::{ + error::{EncStringParseError, Error, Result}, + util::BASE64_ENGINE, +}; + +#[cfg(feature = "internal")] +use crate::error::CryptoError; + +use super::{from_b64_vec, split_enc_string}; + +/// # Encrypted string primitive +/// +/// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are +/// are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt +/// data using AsymmetricCryptoKeys. +/// +/// The flexibility of the [AsymmEncString] type allows for different encryption algorithms to be used +/// which is represented by the different variants of the enum. +/// +/// ## Note +/// +/// For backwards compatibility we will rarely if ever be able to remove support for decrypting old +/// variants, but we should be opinionated in which variants are used for encrypting. +/// +/// ## Variants +/// - [Rsa2048_OaepSha256_B64](AsymmEncString::Rsa2048_OaepSha256_B64) +/// - [Rsa2048_OaepSha1_B64](AsymmEncString::Rsa2048_OaepSha1_B64) +/// +/// ## Serialization +/// +/// [AsymmEncString] implements [Display] and [FromStr] to allow for easy serialization and uses a +/// custom scheme to represent the different variants. +/// +/// The scheme is one of the following schemes: +/// - `[type].[data]` +/// +/// Where: +/// - `[type]`: is a digit number representing the variant. +/// - `[data]`: is the encrypted data. +#[derive(Clone)] +#[allow(unused, non_camel_case_types)] +pub enum AsymmEncString { + /// 3 + Rsa2048_OaepSha256_B64 { data: Vec }, + /// 4 + Rsa2048_OaepSha1_B64 { data: Vec }, + /// 5 + #[deprecated] + Rsa2048_OaepSha256_HmacSha256_B64 { data: Vec, mac: Vec }, + /// 6 + #[deprecated] + Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec, mac: Vec }, +} + +/// To avoid printing sensitive information, [AsymmEncString] debug prints to `AsymmEncString`. +impl std::fmt::Debug for AsymmEncString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AsymmEncString").finish() + } +} + +/// Deserializes an [AsymmEncString] from a string. +impl FromStr for AsymmEncString { + type Err = Error; + + fn from_str(s: &str) -> Result { + let (enc_type, parts) = split_enc_string(s); + match (enc_type, parts.len()) { + ("3", 1) => { + let data = from_b64_vec(parts[0])?; + Ok(AsymmEncString::Rsa2048_OaepSha256_B64 { data }) + } + ("4", 1) => { + let data = from_b64_vec(parts[0])?; + Ok(AsymmEncString::Rsa2048_OaepSha1_B64 { data }) + } + #[allow(deprecated)] + ("5", 2) => { + let data = from_b64_vec(parts[0])?; + let mac: Vec = from_b64_vec(parts[1])?; + Ok(AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac }) + } + #[allow(deprecated)] + ("6", 2) => { + let data = from_b64_vec(parts[0])?; + let mac: Vec = from_b64_vec(parts[1])?; + Ok(AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac }) + } + + (enc_type, parts) => Err(EncStringParseError::InvalidTypeAsymm { + enc_type: enc_type.to_string(), + parts, + } + .into()), + } + } +} + +#[allow(unused)] +impl AsymmEncString { + /// TODO: Convert this to a trait method + #[cfg(feature = "internal")] + pub(crate) fn decrypt(&self, key: &RsaPrivateKey) -> Result> { + Ok(match self { + Self::Rsa2048_OaepSha256_B64 { data } => key.decrypt(Oaep::new::(), data), + Self::Rsa2048_OaepSha1_B64 { data } => key.decrypt(Oaep::new::(), data), + #[allow(deprecated)] + Self::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac: _ } => { + key.decrypt(Oaep::new::(), data) + } + #[allow(deprecated)] + Self::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac: _ } => { + key.decrypt(Oaep::new::(), data) + } + } + .map_err(|_| CryptoError::KeyDecrypt)?) + } +} + +impl Display for AsymmEncString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let parts: Vec<&[u8]> = match self { + AsymmEncString::Rsa2048_OaepSha256_B64 { data } => vec![data], + AsymmEncString::Rsa2048_OaepSha1_B64 { data } => vec![data], + #[allow(deprecated)] + AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac } => vec![data, mac], + #[allow(deprecated)] + AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac } => vec![data, mac], + }; + + let encoded_parts: Vec = parts + .iter() + .map(|part| BASE64_ENGINE.encode(part)) + .collect(); + + write!(f, "{}.{}", self.enc_type(), encoded_parts.join("|"))?; + + Ok(()) + } +} + +impl<'de> Deserialize<'de> for AsymmEncString { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_str(super::FromStrVisitor::new()) + } +} + +impl serde::Serialize for AsymmEncString { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl AsymmEncString { + /// The numerical representation of the encryption type of the [AsymmEncString]. + const fn enc_type(&self) -> u8 { + match self { + AsymmEncString::Rsa2048_OaepSha256_B64 { .. } => 3, + AsymmEncString::Rsa2048_OaepSha1_B64 { .. } => 4, + #[allow(deprecated)] + AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { .. } => 5, + #[allow(deprecated)] + AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, + } + } +} + +/// Usually we wouldn't want to expose AsymmEncStrings in the API or the schemas. +/// But during the transition phase we will expose endpoints using the AsymmEncString type. +impl schemars::JsonSchema for AsymmEncString { + fn schema_name() -> String { + "AsymmEncString".to_string() + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + gen.subschema_for::() + } +} + +#[cfg(test)] +mod tests { + use super::AsymmEncString; + + #[cfg(feature = "internal")] + #[test] + fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { + use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; + + let rsa_private_key: &str = "-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS +8HzYUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2 +e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86LnhD56A9FDUfuI0dVnPcrwNv0YJIo9 +4LwxtbqBULNvXl6wJ7WAbODrCQy5ZgMVg+iH+gGpwiqsZqHt+KuoHWcN53MSPDfa +F4/YMB99U3TziJMOOJask1TEEnakMPln11PczNDazT17DXIxYrbPfutPdh6sLs6A +QOajdZijfEvepgnOe7cQ7aeatiOJFrjTApKPGxOVRzEMX4XS4xbyhH0QxQeB6l16 +l8C0uxIBAgMBAAECggEASaWfeVDA3cVzOPFSpvJm20OTE+R6uGOU+7vh36TX/POq +92qBuwbd0h0oMD32FxsXywd2IxtBDUSiFM9699qufTVuM0Q3tZw6lHDTOVG08+tP +dr8qSbMtw7PGFxN79fHLBxejjO4IrM9lapjWpxEF+11x7r+wM+0xRZQ8sNFYG46a +PfIaty4BGbL0I2DQ2y8I57iBCAy69eht59NLMm27fRWGJIWCuBIjlpfzET1j2HLX +UIh5bTBNzqaN039WH49HczGE3mQKVEJZc/efk3HaVd0a1Sjzyn0QY+N1jtZN3jTR +buDWA1AknkX1LX/0tUhuS3/7C3ejHxjw4Dk1ZLo5/QKBgQDIWvqFn0+IKRSu6Ua2 +hDsufIHHUNLelbfLUMmFthxabcUn4zlvIscJO00Tq/ezopSRRvbGiqnxjv/mYxuc +vOUBeZtlus0Q9RTACBtw9TGoNTmQbEunJ2FOSlqbQxkBBAjgGEppRPt30iGj/VjA +hCATq2MYOa/X4dVR51BqQAFIEwKBgQDBSIfTFKC/hDk6FKZlgwvupWYJyU9Rkyfs +tPErZFmzoKhPkQ3YORo2oeAYmVUbS9I2iIYpYpYQJHX8jMuCbCz4ONxTCuSIXYQY +UcUq4PglCKp31xBAE6TN8SvhfME9/MvuDssnQinAHuF0GDAhF646T3LLS1not6Vs +zv7brwSoGwKBgQC88v/8cGfi80ssQZeMnVvq1UTXIeQcQnoY5lGHJl3K8mbS3TnX +E6c9j417Fdz+rj8KWzBzwWXQB5pSPflWcdZO886Xu/mVGmy9RWgLuVFhXwCwsVEP +jNX5ramRb0/vY0yzenUCninBsIxFSbIfrPtLUYCc4hpxr+sr2Mg/y6jpvQKBgBez +MRRs3xkcuXepuI2R+BCXL1/b02IJTUf1F+1eLLGd7YV0H+J3fgNc7gGWK51hOrF9 +JBZHBGeOUPlaukmPwiPdtQZpu4QNE3l37VlIpKTF30E6mb+BqR+nht3rUjarnMXg +AoEZ18y6/KIjpSMpqC92Nnk/EBM9EYe6Cf4eA9ApAoGAeqEUg46UTlJySkBKURGp +Is3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8+tPVgppLcG0+tMdLjigFQiDUQk2y3 +WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz +XKZBokBGnjFnTnKcs7nv/O8= +-----END PRIVATE KEY-----"; + let private_key = RsaPrivateKey::from_pkcs8_pem(rsa_private_key).unwrap(); + let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; + let enc_string: AsymmEncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 6); + + let res = enc_string.decrypt(&private_key).unwrap(); + + assert_eq!(std::str::from_utf8(&res).unwrap(), "EncryptMe!"); + } + + #[test] + fn test_enc_string_serialization() { + #[derive(serde::Serialize, serde::Deserialize)] + struct Test { + key: AsymmEncString, + } + + let cipher = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; + let serialized = format!("{{\"key\":\"{cipher}\"}}"); + + let t = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(t.key.enc_type(), 6); + assert_eq!(t.key.to_string(), cipher); + assert_eq!(serde_json::to_string(&t).unwrap(), serialized); + } +} diff --git a/crates/bitwarden/src/crypto/enc_string/mod.rs b/crates/bitwarden/src/crypto/enc_string/mod.rs new file mode 100644 index 000000000..f8608638a --- /dev/null +++ b/crates/bitwarden/src/crypto/enc_string/mod.rs @@ -0,0 +1,80 @@ +mod asymmetric; +mod symmetric; + +use std::str::FromStr; + +pub use asymmetric::AsymmEncString; +use base64::Engine; +pub use symmetric::EncString; + +use crate::{ + error::{EncStringParseError, Result}, + util::BASE64_ENGINE, +}; + +#[cfg(feature = "mobile")] +fn check_length(buf: &[u8], expected: usize) -> Result<()> { + if buf.len() < expected { + return Err(EncStringParseError::InvalidLength { + expected, + got: buf.len(), + } + .into()); + } + Ok(()) +} + +fn from_b64_vec(s: &str) -> Result> { + Ok(BASE64_ENGINE + .decode(s) + .map_err(EncStringParseError::InvalidBase64)?) +} + +fn from_b64(s: &str) -> Result<[u8; N]> { + Ok(from_b64_vec(s)? + .try_into() + .map_err(|e: Vec<_>| EncStringParseError::InvalidLength { + expected: N, + got: e.len(), + })?) +} + +fn split_enc_string(s: &str) -> (&str, Vec<&str>) { + let header_parts: Vec<_> = s.split('.').collect(); + + if header_parts.len() == 2 { + (header_parts[0], header_parts[1].split('|').collect()) + } else { + // Support legacy format with no header + let parts: Vec<_> = s.split('|').collect(); + if parts.len() == 3 { + ("1", parts) // AesCbc128_HmacSha256_B64 + } else { + ("0", parts) // AesCbc256_B64 + } + } +} + +struct FromStrVisitor(std::marker::PhantomData); +impl FromStrVisitor { + fn new() -> Self { + Self(Default::default()) + } +} +impl serde::de::Visitor<'_> for FromStrVisitor +where + T::Err: std::fmt::Debug, +{ + type Value = T; + + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "a valid string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + T::from_str(v).map_err(|e| E::custom(format!("{:?}", e))) + } +} diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string/symmetric.rs similarity index 52% rename from crates/bitwarden/src/crypto/enc_string.rs rename to crates/bitwarden/src/crypto/enc_string/symmetric.rs index 34ec359ab..eed7c09ad 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string/symmetric.rs @@ -2,20 +2,20 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; -#[cfg(feature = "internal")] -use rsa::{Oaep, RsaPrivateKey}; -use serde::{de::Visitor, Deserialize}; +use serde::Deserialize; -use super::{KeyDecryptable, KeyEncryptable, LocateKey}; +#[cfg(feature = "mobile")] +use super::check_length; +use super::{from_b64, from_b64_vec, split_enc_string}; use crate::{ - crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, + crypto::{decrypt_aes256_hmac, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; /// # Encrypted string primitive /// -/// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are +/// [EncString] is a Bitwarden specific primitive that represents a symmetrically encrypted string. They are /// are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and decrypt /// data using [SymmetricCryptoKey]s. /// @@ -24,9 +24,6 @@ use crate::{ /// /// ## Note /// -/// We are currently in the progress of splitting the [EncString] into distinct AES and RSA -/// variants. To provide better control of which encryption algorithm is expected. -/// /// For backwards compatibility we will rarely if ever be able to remove support for decrypting old /// variants, but we should be opinionated in which variants are used for encrypting. /// @@ -34,8 +31,6 @@ use crate::{ /// - [AesCbc256_B64](EncString::AesCbc256_B64) /// - [AesCbc128_HmacSha256_B64](EncString::AesCbc128_HmacSha256_B64) /// - [AesCbc256_HmacSha256_B64](EncString::AesCbc256_HmacSha256_B64) -/// - [Rsa2048_OaepSha256_B64](EncString::Rsa2048_OaepSha256_B64) -/// - [Rsa2048_OaepSha1_B64](EncString::Rsa2048_OaepSha1_B64) /// /// ## Serialization /// @@ -45,7 +40,6 @@ use crate::{ /// The scheme is one of the following schemes: /// - `[type].[iv]|[data]` /// - `[type].[iv]|[data]|[mac]` -/// - `[type].[data]` /// /// Where: /// - `[type]`: is a digit number representing the variant. @@ -69,16 +63,6 @@ pub enum EncString { mac: [u8; 32], data: Vec, }, - /// 3 - Rsa2048_OaepSha256_B64 { data: Vec }, - /// 4 - Rsa2048_OaepSha1_B64 { data: Vec }, - /// 5 - #[deprecated] - Rsa2048_OaepSha256_HmacSha256_B64 { data: Vec }, - /// 6 - #[deprecated] - Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec }, } /// To avoid printing sensitive information, [EncString] debug prints to `EncString`. @@ -93,32 +77,7 @@ impl FromStr for EncString { type Err = Error; fn from_str(s: &str) -> Result { - let (enc_type, parts): (&str, Vec<_>) = { - let header_parts: Vec<_> = s.split('.').collect(); - - if header_parts.len() == 2 { - (header_parts[0], header_parts[1].split('|').collect()) - } else { - // Support legacy format with no header - let parts: Vec<_> = s.split('|').collect(); - if parts.len() == 3 { - ("1", parts) // AesCbc128_HmacSha256_B64 - } else { - ("0", parts) // AesCbc256_B64 - } - } - }; - - fn from_b64_vec(s: &str) -> Result> { - Ok(BASE64_ENGINE - .decode(s) - .map_err(EncStringParseError::InvalidBase64)?) - } - - fn from_b64(s: &str) -> Result<[u8; N]> { - Ok(from_b64_vec(s)?.try_into().map_err(invalid_len_error(N))?) - } - + let (enc_type, parts) = split_enc_string(s); match (enc_type, parts.len()) { ("0", 2) => { let iv = from_b64(parts[0])?; @@ -137,26 +96,8 @@ impl FromStr for EncString { Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } } - ("3", 1) => { - let data = from_b64_vec(parts[0])?; - Ok(EncString::Rsa2048_OaepSha256_B64 { data }) - } - ("4", 1) => { - let data = from_b64_vec(parts[0])?; - Ok(EncString::Rsa2048_OaepSha1_B64 { data }) - } - #[allow(deprecated)] - ("5", 2) => { - let data = from_b64_vec(parts[0])?; - Ok(EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data }) - } - #[allow(deprecated)] - ("6", 2) => { - let data = from_b64_vec(parts[0])?; - Ok(EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data }) - } - (enc_type, parts) => Err(EncStringParseError::InvalidType { + (enc_type, parts) => Err(EncStringParseError::InvalidTypeSymm { enc_type: enc_type.to_string(), parts, } @@ -172,29 +113,6 @@ impl EncString { s.map(|s| s.parse()).transpose() } - /// TODO: Convert this to a trait method - #[cfg(feature = "internal")] - pub(crate) fn decrypt_with_private_key(&self, key: &RsaPrivateKey) -> Result> { - Ok(match self { - EncString::Rsa2048_OaepSha256_B64 { data } => { - key.decrypt(Oaep::new::(), data) - } - EncString::Rsa2048_OaepSha1_B64 { data } => { - key.decrypt(Oaep::new::(), data) - } - #[allow(deprecated)] - EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data } => { - key.decrypt(Oaep::new::(), data) - } - #[allow(deprecated)] - EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data } => { - key.decrypt(Oaep::new::(), data) - } - _ => return Err(CryptoError::InvalidKey.into()), - } - .map_err(|_| CryptoError::KeyDecrypt)?) - } - #[cfg(feature = "mobile")] pub(crate) fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { @@ -202,17 +120,6 @@ impl EncString { } let enc_type = buf[0]; - fn check_length(buf: &[u8], expected: usize) -> Result<()> { - if buf.len() < expected { - return Err(EncStringParseError::InvalidLength { - expected, - got: buf.len(), - } - .into()); - } - Ok(()) - } - match enc_type { 0 => { check_length(buf, 18)?; @@ -233,29 +140,7 @@ impl EncString { Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } } - 3 => { - check_length(buf, 2)?; - let data = buf[1..].to_vec(); - Ok(EncString::Rsa2048_OaepSha256_B64 { data }) - } - 4 => { - check_length(buf, 2)?; - let data = buf[1..].to_vec(); - Ok(EncString::Rsa2048_OaepSha1_B64 { data }) - } - #[allow(deprecated)] - 5 => { - check_length(buf, 2)?; - let data = buf[1..].to_vec(); - Ok(EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data }) - } - #[allow(deprecated)] - 6 => { - check_length(buf, 2)?; - let data = buf[1..].to_vec(); - Ok(EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data }) - } - _ => Err(EncStringParseError::InvalidType { + _ => Err(EncStringParseError::InvalidTypeSymm { enc_type: enc_type.to_string(), parts: 1, } @@ -282,20 +167,6 @@ impl EncString { buf.extend_from_slice(mac); buf.extend_from_slice(data); } - - EncString::Rsa2048_OaepSha256_B64 { data } - | EncString::Rsa2048_OaepSha1_B64 { data } => { - buf = Vec::with_capacity(1 + data.len()); - buf.push(self.enc_type()); - buf.extend_from_slice(data); - } - #[allow(deprecated)] - EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data } - | EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data } => { - buf = Vec::with_capacity(1 + data.len()); - buf.push(self.enc_type()); - buf.extend_from_slice(data); - } } Ok(buf) @@ -308,12 +179,6 @@ impl Display for EncString { EncString::AesCbc256_B64 { iv, data } => vec![iv, data], EncString::AesCbc128_HmacSha256_B64 { iv, mac, data } => vec![iv, data, mac], EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => vec![iv, data, mac], - EncString::Rsa2048_OaepSha256_B64 { data } => vec![data], - EncString::Rsa2048_OaepSha1_B64 { data } => vec![data], - #[allow(deprecated)] - EncString::Rsa2048_OaepSha256_HmacSha256_B64 { data } => vec![data], - #[allow(deprecated)] - EncString::Rsa2048_OaepSha1_HmacSha256_B64 { data } => vec![data], }; let encoded_parts: Vec = parts @@ -332,23 +197,7 @@ impl<'de> Deserialize<'de> for EncString { where D: serde::Deserializer<'de>, { - struct CSVisitor; - impl Visitor<'_> for CSVisitor { - type Value = EncString; - - fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!(f, "a valid string") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - EncString::from_str(v).map_err(|e| E::custom(format!("{:?}", e))) - } - } - - deserializer.deserialize_str(CSVisitor) + deserializer.deserialize_str(super::FromStrVisitor::new()) } } @@ -367,7 +216,7 @@ impl EncString { mac_key: GenericArray, key: GenericArray, ) -> Result { - let (iv, mac, data) = super::encrypt_aes256_hmac(data_dec, mac_key, key)?; + let (iv, mac, data) = crate::crypto::encrypt_aes256_hmac(data_dec, mac_key, key)?; Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } @@ -377,23 +226,10 @@ impl EncString { EncString::AesCbc256_B64 { .. } => 0, EncString::AesCbc128_HmacSha256_B64 { .. } => 1, EncString::AesCbc256_HmacSha256_B64 { .. } => 2, - EncString::Rsa2048_OaepSha256_B64 { .. } => 3, - EncString::Rsa2048_OaepSha1_B64 { .. } => 4, - #[allow(deprecated)] - EncString::Rsa2048_OaepSha256_HmacSha256_B64 { .. } => 5, - #[allow(deprecated)] - EncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, } } } -fn invalid_len_error(expected: usize) -> impl Fn(Vec) -> EncStringParseError { - move |e: Vec<_>| EncStringParseError::InvalidLength { - expected, - got: e.len(), - } -} - impl LocateKey for EncString {} impl KeyEncryptable for &[u8] { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { @@ -429,7 +265,7 @@ impl KeyDecryptable for EncString { /// Usually we wouldn't want to expose EncStrings in the API or the schemas. /// But during the transition phase we will expose endpoints using the EncString type. -impl schemars::JsonSchema for crate::crypto::EncString { +impl schemars::JsonSchema for EncString { fn schema_name() -> String { "EncString".to_string() } @@ -455,50 +291,6 @@ mod tests { assert_eq!(decrypted_str, test_string); } - #[cfg(feature = "internal")] - #[test] - fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { - use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; - - let rsa_private_key: &str = "-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS -8HzYUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2 -e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86LnhD56A9FDUfuI0dVnPcrwNv0YJIo9 -4LwxtbqBULNvXl6wJ7WAbODrCQy5ZgMVg+iH+gGpwiqsZqHt+KuoHWcN53MSPDfa -F4/YMB99U3TziJMOOJask1TEEnakMPln11PczNDazT17DXIxYrbPfutPdh6sLs6A -QOajdZijfEvepgnOe7cQ7aeatiOJFrjTApKPGxOVRzEMX4XS4xbyhH0QxQeB6l16 -l8C0uxIBAgMBAAECggEASaWfeVDA3cVzOPFSpvJm20OTE+R6uGOU+7vh36TX/POq -92qBuwbd0h0oMD32FxsXywd2IxtBDUSiFM9699qufTVuM0Q3tZw6lHDTOVG08+tP -dr8qSbMtw7PGFxN79fHLBxejjO4IrM9lapjWpxEF+11x7r+wM+0xRZQ8sNFYG46a -PfIaty4BGbL0I2DQ2y8I57iBCAy69eht59NLMm27fRWGJIWCuBIjlpfzET1j2HLX -UIh5bTBNzqaN039WH49HczGE3mQKVEJZc/efk3HaVd0a1Sjzyn0QY+N1jtZN3jTR -buDWA1AknkX1LX/0tUhuS3/7C3ejHxjw4Dk1ZLo5/QKBgQDIWvqFn0+IKRSu6Ua2 -hDsufIHHUNLelbfLUMmFthxabcUn4zlvIscJO00Tq/ezopSRRvbGiqnxjv/mYxuc -vOUBeZtlus0Q9RTACBtw9TGoNTmQbEunJ2FOSlqbQxkBBAjgGEppRPt30iGj/VjA -hCATq2MYOa/X4dVR51BqQAFIEwKBgQDBSIfTFKC/hDk6FKZlgwvupWYJyU9Rkyfs -tPErZFmzoKhPkQ3YORo2oeAYmVUbS9I2iIYpYpYQJHX8jMuCbCz4ONxTCuSIXYQY -UcUq4PglCKp31xBAE6TN8SvhfME9/MvuDssnQinAHuF0GDAhF646T3LLS1not6Vs -zv7brwSoGwKBgQC88v/8cGfi80ssQZeMnVvq1UTXIeQcQnoY5lGHJl3K8mbS3TnX -E6c9j417Fdz+rj8KWzBzwWXQB5pSPflWcdZO886Xu/mVGmy9RWgLuVFhXwCwsVEP -jNX5ramRb0/vY0yzenUCninBsIxFSbIfrPtLUYCc4hpxr+sr2Mg/y6jpvQKBgBez -MRRs3xkcuXepuI2R+BCXL1/b02IJTUf1F+1eLLGd7YV0H+J3fgNc7gGWK51hOrF9 -JBZHBGeOUPlaukmPwiPdtQZpu4QNE3l37VlIpKTF30E6mb+BqR+nht3rUjarnMXg -AoEZ18y6/KIjpSMpqC92Nnk/EBM9EYe6Cf4eA9ApAoGAeqEUg46UTlJySkBKURGp -Is3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8+tPVgppLcG0+tMdLjigFQiDUQk2y3 -WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz -XKZBokBGnjFnTnKcs7nv/O8= ------END PRIVATE KEY-----"; - let private_key = RsaPrivateKey::from_pkcs8_pem(rsa_private_key).unwrap(); - let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; - let enc_string: EncString = enc_str.parse().unwrap(); - - assert_eq!(enc_string.enc_type(), 6); - - let res = enc_string.decrypt_with_private_key(&private_key).unwrap(); - - assert_eq!(std::str::from_utf8(&res).unwrap(), "EncryptMe!"); - } - #[test] fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index 3d8f7b0ce..84697e8a5 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -27,7 +27,7 @@ use hmac::digest::OutputSizeUser; use crate::error::Result; mod enc_string; -pub use enc_string::EncString; +pub use enc_string::{AsymmEncString, EncString}; mod encryptable; pub use encryptable::{Decryptable, Encryptable, LocateKey}; mod key_encryptable; diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index ede8ef806..bb70adebf 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -106,8 +106,10 @@ pub enum CryptoError { pub enum EncStringParseError { #[error("No type detected, missing '.' separator")] NoType, - #[error("Invalid type, got {enc_type} with {parts} parts")] - InvalidType { enc_type: String, parts: usize }, + #[error("Invalid symmetric type, got type {enc_type} with {parts} parts")] + InvalidTypeSymm { enc_type: String, parts: usize }, + #[error("Invalid asymmetric type, got type {enc_type} with {parts} parts")] + InvalidTypeAsymm { enc_type: String, parts: usize }, #[error("Error decoding base64: {0}")] InvalidBase64(#[from] base64::DecodeError), #[error("Invalid length: expected {expected}, got {got}")] diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index edb44fadc..ca5dea703 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ client::kdf::Kdf, - crypto::EncString, + crypto::{AsymmEncString, EncString}, error::{Error, Result}, Client, }; @@ -87,7 +87,7 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct InitOrgCryptoRequest { /// The encryption keys for all the organizations the user is a part of - pub organization_keys: HashMap, + pub organization_keys: HashMap, } #[cfg(feature = "internal")] diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 5e25d764e..795aa9f50 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -2,7 +2,11 @@ use std::{num::NonZeroU32, str::FromStr}; use uuid::Uuid; -use crate::{crypto::EncString, error::Error, UniffiCustomTypeConverter}; +use crate::{ + crypto::{AsymmEncString, EncString}, + error::Error, + UniffiCustomTypeConverter, +}; uniffi::custom_type!(NonZeroU32, u32); @@ -32,6 +36,20 @@ impl UniffiCustomTypeConverter for EncString { } } +uniffi::custom_type!(AsymmEncString, String); + +impl UniffiCustomTypeConverter for AsymmEncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::from_str(&val).map_err(|e| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} + type DateTime = chrono::DateTime; uniffi::custom_type!(DateTime, std::time::SystemTime); From 0360a9a860526a40ad96bf7cb02830b31d0cce8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Wed, 20 Dec 2023 15:39:02 +0100 Subject: [PATCH 148/378] Make model IDs optional (#453) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Previously some of the model structs had non-optional IDs, this won't work when trying to encrypt a new item, as you won't have an ID until you POST it to the server. This PR changes the id fields to be optional, matching what we already do on Cipher. --- crates/bitwarden/src/vault/collection.rs | 6 +++--- crates/bitwarden/src/vault/folder.rs | 6 +++--- crates/bitwarden/src/vault/send.rs | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 11983dca5..3ff5d1350 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -13,7 +13,7 @@ use crate::{ #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct Collection { - id: Uuid, + id: Option, organization_id: Uuid, name: EncString, @@ -27,7 +27,7 @@ pub struct Collection { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct CollectionView { - id: Uuid, + id: Option, organization_id: Uuid, name: String, @@ -66,7 +66,7 @@ impl TryFrom for Collection { fn try_from(collection: CollectionDetailsResponseModel) -> Result { Ok(Collection { - id: collection.id.ok_or(Error::MissingFields)?, + id: collection.id, organization_id: collection.organization_id.ok_or(Error::MissingFields)?, name: collection.name.ok_or(Error::MissingFields)?.parse()?, external_id: collection.external_id, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index d04bf3110..04a4bebf7 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -13,7 +13,7 @@ use crate::{ #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct Folder { - id: Uuid, + id: Option, name: EncString, revision_date: DateTime, } @@ -22,7 +22,7 @@ pub struct Folder { #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct FolderView { - id: Uuid, + id: Option, name: String, revision_date: DateTime, } @@ -54,7 +54,7 @@ impl TryFrom for Folder { fn try_from(folder: FolderResponseModel) -> Result { Ok(Folder { - id: folder.id.ok_or(Error::MissingFields)?, + id: folder.id, name: EncString::try_from_optional(folder.name)?.ok_or(Error::MissingFields)?, revision_date: folder.revision_date.ok_or(Error::MissingFields)?.parse()?, }) diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 255f6b9fd..e732170c5 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -63,8 +63,8 @@ pub enum SendType { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct Send { - pub id: Uuid, - pub access_id: String, + pub id: Option, + pub access_id: Option, pub name: EncString, pub notes: Option, @@ -89,8 +89,8 @@ pub struct Send { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendView { - pub id: Uuid, - pub access_id: String, + pub id: Option, + pub access_id: Option, pub name: String, pub notes: Option, @@ -115,8 +115,8 @@ pub struct SendView { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendListView { - pub id: Uuid, - pub access_id: String, + pub id: Option, + pub access_id: Option, pub name: String, @@ -270,8 +270,8 @@ impl TryFrom for Send { fn try_from(send: SendResponseModel) -> Result { Ok(Send { - id: send.id.ok_or(Error::MissingFields)?, - access_id: send.access_id.ok_or(Error::MissingFields)?, + id: send.id, + access_id: send.access_id, name: send.name.ok_or(Error::MissingFields)?.parse()?, notes: EncString::try_from_optional(send.notes)?, key: send.key.ok_or(Error::MissingFields)?.parse()?, @@ -348,8 +348,8 @@ mod tests { // Create a send object, the only value we really care about here is the key let send = Send { - id: "d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap(), - access_id: "fx7711OQwEOgLLBpAJhoWg".into(), + id: Some("d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap()), + access_id: Some("fx7711OQwEOgLLBpAJhoWg".into()), name: "2.u5vXPAepUZ+4lI2vGGKiGg==|hEouC4SvCCb/ifzZzLcfSw==|E2VZUVffehczfIuRSlX2vnPRfflBtXef5tzsWvRrtfM=" .parse() .unwrap(), From ac3e93ef65cd7ff2d04bed6b31b6bf8740104d1e Mon Sep 17 00:00:00 2001 From: Jake Fink Date: Wed, 20 Dec 2023 14:41:34 -0500 Subject: [PATCH 149/378] [PM-3437] add validation for master password policy (#452) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implements the validation for master password policy ## Code changes - **file.ext:** Description of what was changed and why ## Screenshots ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bitwarden-uniffi/src/auth/mod.rs | 2 +- crates/bitwarden/src/auth/password.rs | 154 +++++++++++++++++++++++- 2 files changed, 151 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index ded3f776a..1dc102b3e 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -29,7 +29,7 @@ impl ClientAuth { .await } - /// **API Draft:** Evaluate if the provided password satisfies the provided policy + /// Evaluate if the provided password satisfies the provided policy pub async fn satisfies_policy( &self, password: String, diff --git a/crates/bitwarden/src/auth/password.rs b/crates/bitwarden/src/auth/password.rs index eec68861a..94fe0faa0 100644 --- a/crates/bitwarden/src/auth/password.rs +++ b/crates/bitwarden/src/auth/password.rs @@ -16,11 +16,36 @@ pub(super) fn password_strength( 2 } +/// Validate the provided password passes the provided Master Password Requirements Policy. pub(super) fn satisfies_policy( - _password: String, - _strength: u8, - _policy: &MasterPasswordPolicyOptions, + password: String, + strength: u8, + policy: &MasterPasswordPolicyOptions, ) -> bool { + if policy.min_complexity > 0 && policy.min_complexity > strength { + return false; + } + + if policy.min_length > 0 && usize::from(policy.min_length) > password.len() { + return false; + } + + if policy.require_upper && password.to_lowercase() == password { + return false; + } + + if policy.require_lower && password.to_uppercase() == password { + return false; + } + + if policy.require_numbers && !password.chars().any(|c| c.is_numeric()) { + return false; + } + + if policy.require_special && !password.chars().any(|c| "!@#$%^&*".contains(c)) { + return false; + } + true } @@ -69,8 +94,129 @@ pub struct MasterPasswordPolicyOptions { } #[cfg(test)] - mod tests { + mod satisfies_policy { + use crate::auth::password::{satisfies_policy, MasterPasswordPolicyOptions}; + + #[test] + fn satisfies_policy_gives_success() { + let password = "lkasfo!icbb$2323ALKJCO22".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 3, + min_length: 5, + require_upper: true, + require_lower: true, + require_numbers: true, + require_special: true, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 4, &options); + assert!(result); + } + + #[test] + fn satisfies_policy_evaluates_strength() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 3, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_length() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 20, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_upper() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: true, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_lower() { + let password = "ABCDEFG123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: true, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_numbers() { + let password = "password".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: true, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_special() { + let password = "Password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: true, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + } #[cfg(feature = "mobile")] #[tokio::test] From f191c662ee5f7e86c8d945d2cd9936e4bd3842e1 Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:27:22 -0500 Subject: [PATCH 150/378] Bump version to 0.2.3 (#455) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden-api-api version bump to 0.2.3 --- Cargo.lock | 2 +- crates/bitwarden-api-api/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fcc4155e9..527f496a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -368,7 +368,7 @@ dependencies = [ [[package]] name = "bitwarden-api-api" -version = "0.2.2" +version = "0.2.3" dependencies = [ "reqwest", "serde", diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index 2e05088e0..e4ec902b1 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-api" -version = "0.2.2" +version = "0.2.3" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index a9cafc4da..f67fa2ea5 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -27,7 +27,7 @@ argon2 = { version = ">=0.5.0, <0.6", features = [ "alloc", ], default-features = false } base64 = ">=0.21.2, <0.22" -bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } +bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } chrono = { version = ">=0.4.26, <0.5", features = [ From 0b306e3cf7967ba1ba379b4943e5415b5b41ff87 Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:33:26 -0500 Subject: [PATCH 151/378] Bump version to 0.2.3 (#457) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden-api-identity version bump to 0.2.3 --- Cargo.lock | 2 +- crates/bitwarden-api-identity/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 527f496a2..ca2b03c78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -381,7 +381,7 @@ dependencies = [ [[package]] name = "bitwarden-api-identity" -version = "0.2.2" +version = "0.2.3" dependencies = [ "reqwest", "serde", diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 7207c5f8e..929bbc6fa 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden-api-identity" -version = "0.2.2" +version = "0.2.3" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index f67fa2ea5..bd94fb00b 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -28,7 +28,7 @@ argon2 = { version = ">=0.5.0, <0.6", features = [ ], default-features = false } base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } -bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } +bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", From 3746415ac546a1aadc102e5b63d5daf871fdf4e0 Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:36:28 -0500 Subject: [PATCH 152/378] Bump version to 0.4.0 (#458) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated bitwarden version bump to 0.4.0 --- Cargo.lock | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca2b03c78..6aa395e57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,7 +329,7 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "bitwarden" -version = "0.3.1" +version = "0.4.0" dependencies = [ "aes", "argon2", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index bd94fb00b..224ef1096 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitwarden" -version = "0.3.1" +version = "0.4.0" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 53712100e..5183d5912 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -20,7 +20,7 @@ inquire = "0.6.2" log = "0.4.20" tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } -bitwarden = { path = "../bitwarden", version = "0.3.1", features = [ +bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ "internal", "mobile", ] } diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index d9f008043..1c7b95dc8 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -40,7 +40,7 @@ tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.6.1", features = ["serde"] } -bitwarden = { path = "../bitwarden", version = "0.3.1", features = ["secrets"] } +bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } [dev-dependencies] tempfile = "3.8.1" From cf6c2118f052c6412b66df5f1971576f03380c14 Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:39:00 -0500 Subject: [PATCH 153/378] Bump version to 0.4.0 (#459) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated cli version bump to 0.4.0 --- Cargo.lock | 2 +- crates/bws/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6aa395e57..ca4305f8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -534,7 +534,7 @@ dependencies = [ [[package]] name = "bws" -version = "0.3.1" +version = "0.4.0" dependencies = [ "bat", "bitwarden", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 1c7b95dc8..124f666cc 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bws" -version = "0.3.1" +version = "0.4.0" edition = "2021" rust-version = "1.60" authors = ["Bitwarden Inc"] From 793ff107eb8d5df7156ab4f30c0cbc78ff0d8f55 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Thu, 21 Dec 2023 15:08:44 -0500 Subject: [PATCH 154/378] SM-1058: Update the changelog (#460) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ``` ## Objective Changelog update for the release on 2023-12-21. ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bitwarden/CHANGELOG.md | 2 ++ crates/bws/CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index 1341eef68..b4a57cde1 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,6 +7,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.4.0] - 2023-12-21 + ### Added - Support for basic state to avoid reauthenticating when creating a new `Client`. This is a breaking diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 30db20a04..007639800 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,6 +7,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.4.0] - 2023-12-21 + ### Added - Ability to output secrets in an `env` format with `bws` (#320) From 52d3100931389d61971e9cbcfb867d56fdee6c4f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:09:19 +0100 Subject: [PATCH 155/378] [deps]: Update Rust crate tokio to 1.35.1 (#462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | dependencies | patch | `1.35.0` -> `1.35.1` | | [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | dev-dependencies | patch | `1.35.0` -> `1.35.1` | --- ### Release Notes
tokio-rs/tokio (tokio) ### [`v1.35.1`](https://togithub.com/tokio-rs/tokio/releases/tag/tokio-1.35.1): Tokio v1.35.1 [Compare Source](https://togithub.com/tokio-rs/tokio/compare/tokio-1.35.0...tokio-1.35.1) ### 1.35.1 (December 19, 2023) This is a forward part of a change that was backported to 1.25.3. ##### Fixed - io: add budgeting to `tokio::runtime::io::registration::async_io` ([#​6221]) [#​6221]: https://togithub.com/tokio-rs/tokio/pull/6221
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden-py/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca4305f8d..db391b7e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3264,9 +3264,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 3a7c5ca58..f867cfdc1 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -18,7 +18,7 @@ bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3-build-config = { version = "0.20.0" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] -tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 224ef1096..5677a73d9 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -62,5 +62,5 @@ uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" -tokio = { version = "1.35.0", features = ["rt", "macros"] } +tokio = { version = "1.35.1", features = ["rt", "macros"] } wiremock = "0.5.22" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 5183d5912..20e750f14 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" log = "0.4.20" -tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ "internal", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 124f666cc..3b71a7dad 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -36,7 +36,7 @@ serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.51" -tokio = { version = "1.35.0", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.6.1", features = ["serde"] } From 77cd027c14e47fb959a414b214de4a3895eb522e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 4 Jan 2024 12:59:31 +0100 Subject: [PATCH 156/378] Install cross locked (#472) --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-cli.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 2171fb515..784beb168 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -38,7 +38,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo - name: Install Cross - run: cargo install cross + run: cargo install cross --locked - name: Build env: diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index eef2d84b5..4732a1936 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -75,7 +75,7 @@ jobs: - name: Install Cross (aarch64-unknown-linux-gnu) if: ${{ matrix.settings.target == 'aarch64-unknown-linux-gnu' }} - run: cargo install cross + run: cargo install cross --locked - name: Build if: ${{ matrix.settings.target != 'aarch64-unknown-linux-gnu' }} From fa39a5263ded119f8e482a92c645321f85377653 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 4 Jan 2024 15:17:40 +0100 Subject: [PATCH 157/378] Fix clippy warning (#471) --- crates/bitwarden-c/src/macros/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/bitwarden-c/src/macros/mod.rs b/crates/bitwarden-c/src/macros/mod.rs index e524fcbf1..57ae9b9ee 100644 --- a/crates/bitwarden-c/src/macros/mod.rs +++ b/crates/bitwarden-c/src/macros/mod.rs @@ -1,3 +1 @@ -pub use ffi::*; - mod ffi; From 70abf070e0948458eb719e3fa75f99fe009709ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:28:11 +0100 Subject: [PATCH 158/378] [deps]: Update @types/node to v18.19.4 (#465) --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 12a2bb7c7..76fc3e341 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.3.tgz", - "integrity": "sha512-k5fggr14DwAytoA/t8rPrIz++lXK7/DqckthCmoZOKNsEbJkId4Z//BqgApXBUGrGddrigYa1oqheo/7YmW4rg==", + "version": "18.19.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.4.tgz", + "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 94c0d070b899d417ef3cf452b84706592e0d9b84 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:28:51 +0100 Subject: [PATCH 159/378] [deps]: Update Rust crate anyhow to 1.0.79 (#461) --- Cargo.lock | 4 ++-- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db391b7e4..9005f4909 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -111,9 +111,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arc-swap" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 2e7706200..7ae1874b4 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -12,7 +12,7 @@ internal = [ ] [dependencies] -anyhow = "1.0.75" +anyhow = "1.0.79" itertools = "0.12.0" schemars = { version = "0.8.16", features = ["preserve_order"] } serde_json = "1.0.108" From cefa072f9509e9e3de471acac2640d69c6592dfc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 14:30:13 +0000 Subject: [PATCH 160/378] [deps]: Update Rust crate thiserror to 1.0.56 (#468) --- Cargo.lock | 64 +++++++++++++++++++++---------------------- crates/bws/Cargo.toml | 2 +- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9005f4909..3a774fec7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,7 +156,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -227,7 +227,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -704,7 +704,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -935,7 +935,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -1244,7 +1244,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -1873,7 +1873,7 @@ dependencies = [ "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -1888,7 +1888,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2094,7 +2094,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2295,9 +2295,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" dependencies = [ "unicode-ident", ] @@ -2384,7 +2384,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2396,7 +2396,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2410,9 +2410,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2743,7 +2743,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2808,7 +2808,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -2863,7 +2863,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3068,7 +3068,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3100,9 +3100,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.41" +version = "2.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" +checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" dependencies = [ "proc-macro2", "quote", @@ -3190,22 +3190,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3287,7 +3287,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3382,7 +3382,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3555,7 +3555,7 @@ version = "0.25.2" source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] @@ -3586,7 +3586,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.41", + "syn 2.0.47", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3744,7 +3744,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", "wasm-bindgen-shared", ] @@ -3778,7 +3778,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3811,7 +3811,7 @@ checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" dependencies = [ "proc-macro2", "quote", - "syn 2.0.41", + "syn 2.0.47", ] [[package]] diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 3b71a7dad..648021c6f 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -35,7 +35,7 @@ serde = "^1.0.193" serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" -thiserror = "1.0.51" +thiserror = "1.0.56" tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" uuid = { version = "^1.6.1", features = ["serde"] } From f088f0c7b28c78c5f086399e5393c60eb30ff7f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:55:12 +0100 Subject: [PATCH 161/378] [deps]: Update Rust crate clap_complete to 4.4.6 (#467) --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a774fec7..3363cb5e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -688,9 +688,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.4" +version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" +checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" dependencies = [ "clap", ] diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 648021c6f..5f05d2708 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.31", features = [ "std", ], default-features = false } clap = { version = "4.4.11", features = ["derive", "env", "string"] } -clap_complete = "4.4.4" +clap_complete = "4.4.6" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" From 087dfcb77a6216ded7becef75b435ab57cabc49e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:55:29 +0100 Subject: [PATCH 162/378] [deps]: Update Rust crate tempfile to 3.9.0 (#469) --- Cargo.lock | 6 +++--- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3363cb5e0..1de208b0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3157,15 +3157,15 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 20e750f14..d3739fc7d 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -27,4 +27,4 @@ bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } [dev-dependencies] -tempfile = "3.8.1" +tempfile = "3.9.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 5f05d2708..98dfb668d 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -43,7 +43,7 @@ uuid = { version = "^1.6.1", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } [dev-dependencies] -tempfile = "3.8.1" +tempfile = "3.9.0" [target.'cfg(target_os = "linux")'.dependencies] openssl = { version = "0.10", features = ["vendored"] } From 8dd2e4581eba476d072cc8d7841b7a01e1f3211a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 15:55:50 +0100 Subject: [PATCH 163/378] [deps]: Update pyo3 non-major to 0.20.1 (#470) --- Cargo.lock | 20 ++++++++++---------- crates/bitwarden-py/Cargo.toml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1de208b0b..f4b125501 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2304,9 +2304,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" +checksum = "e82ad98ce1991c9c70c3464ba4187337b9c45fcbbb060d46dca15f0c075e14e2" dependencies = [ "cfg-if", "indoc", @@ -2346,9 +2346,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" +checksum = "5503d0b3aee2c7a8dbb389cd87cd9649f675d4c7f60ca33699a3e3859d81a891" dependencies = [ "once_cell", "target-lexicon", @@ -2356,9 +2356,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" +checksum = "18a79e8d80486a00d11c0dcb27cd2aa17c022cc95c677b461f01797226ba8f41" dependencies = [ "libc", "pyo3-build-config", @@ -2377,9 +2377,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" +checksum = "1f4b0dc7eaa578604fab11c8c7ff8934c71249c61d4def8e272c76ed879f03d4" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2389,9 +2389,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" +checksum = "816a4f709e29ddab2e3cdfe94600d554c5556cad0ddfeea95c47b580c3247fa4" dependencies = [ "heck", "proc-macro2", diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index f867cfdc1..1d52d0b2b 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -9,13 +9,13 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.20.0", features = ["extension-module"] } +pyo3 = { version = "0.20.1", features = ["extension-module"] } pyo3-log = "0.9.0" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [build-dependencies] -pyo3-build-config = { version = "0.20.0" } +pyo3-build-config = { version = "0.20.1" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } From f3cf39b1c620556950df75b9d1dc1c986825f1d1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 17:38:41 +0100 Subject: [PATCH 164/378] [deps]: Update Rust crate clap to 4.4.12 (#466) --- Cargo.lock | 8 ++++---- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4b125501..498aaf85b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" dependencies = [ "clap_builder", "clap_derive", @@ -676,9 +676,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 2591035c2..08381a47c 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.11", features = ["derive"] } +clap = { version = "4.4.12", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index d3739fc7d..059b853a5 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.11", features = ["derive", "env"] } +clap = { version = "4.4.12", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 98dfb668d..90c2cdb05 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.11", features = ["derive", "env", "string"] } +clap = { version = "4.4.12", features = ["derive", "env", "string"] } clap_complete = "4.4.6" color-eyre = "0.6" comfy-table = "^7.1.0" From 68236d314a95f612d3b0bea1aa571596a8b3705f Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 5 Jan 2024 11:51:57 +0100 Subject: [PATCH 165/378] Add support for generating the users fingerprint (#474) Add support for generating the users fingerprint using the private key from EncSettings. --- crates/bitwarden-json/src/client.rs | 2 +- crates/bitwarden-uniffi/src/platform/mod.rs | 22 ++++++- crates/bitwarden-uniffi/src/uniffi_support.rs | 3 + crates/bitwarden/src/client/client.rs | 12 +--- .../src/client/encryption_settings.rs | 2 +- .../bitwarden/src/platform/client_platform.rs | 25 +++++++ .../src/platform/generate_fingerprint.rs | 66 ++++++++++++++++++- crates/bitwarden/src/platform/mod.rs | 2 +- languages/kotlin/doc.md | 40 ++++++++--- 9 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 crates/bitwarden/src/platform/client_platform.rs diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index 416067b66..d484c7b50 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -58,7 +58,7 @@ impl Client { #[cfg(feature = "internal")] Command::Sync(req) => self.0.sync(&req).await.into_string(), #[cfg(feature = "internal")] - Command::Fingerprint(req) => self.0.fingerprint(&req).into_string(), + Command::Fingerprint(req) => self.0.platform().fingerprint(&req).into_string(), #[cfg(feature = "secrets")] Command::Secrets(cmd) => match cmd { diff --git a/crates/bitwarden-uniffi/src/platform/mod.rs b/crates/bitwarden-uniffi/src/platform/mod.rs index f03ed01e5..7200b6678 100644 --- a/crates/bitwarden-uniffi/src/platform/mod.rs +++ b/crates/bitwarden-uniffi/src/platform/mod.rs @@ -9,8 +9,26 @@ pub struct ClientPlatform(pub(crate) Arc); #[uniffi::export(async_runtime = "tokio")] impl ClientPlatform { - /// Fingerprint + /// Fingerprint (public key) pub async fn fingerprint(&self, req: FingerprintRequest) -> Result { - Ok(self.0 .0.read().await.fingerprint(&req)?.fingerprint) + Ok(self + .0 + .0 + .write() + .await + .platform() + .fingerprint(&req)? + .fingerprint) + } + + /// Fingerprint using logged in user's public key + pub async fn user_fingerprint(&self, fingerprint_material: String) -> Result { + Ok(self + .0 + .0 + .write() + .await + .platform() + .user_fingerprint(fingerprint_material)?) } } diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index 82cd343a7..72a67f698 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,3 +1,6 @@ +use bitwarden::crypto::EncString; + // Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); +uniffi::ffi_converter_forward!(EncString, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 272d4210a..302e7ed75 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -4,6 +4,7 @@ use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; +use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] @@ -11,8 +12,8 @@ use crate::{ client::kdf::Kdf, crypto::{AsymmEncString, EncString}, platform::{ - generate_fingerprint, get_user_api_key, sync, FingerprintRequest, FingerprintResponse, - SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, + get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, + UserApiKeyResponse, }, }; use crate::{ @@ -24,8 +25,6 @@ use crate::{ error::{Error, Result}, }; -use super::AccessToken; - #[derive(Debug)] pub(crate) struct ApiConfigurations { pub identity: bitwarden_api_identity::apis::configuration::Configuration, @@ -285,9 +284,4 @@ impl Client { enc.set_org_keys(org_keys)?; Ok(self.encryption_settings.as_ref().unwrap()) } - - #[cfg(feature = "internal")] - pub fn fingerprint(&self, input: &FingerprintRequest) -> Result { - generate_fingerprint(input) - } } diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index d7321aeb4..ebfbba2b4 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -16,7 +16,7 @@ use crate::crypto::SymmetricCryptoKey; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, - private_key: Option, + pub(crate) private_key: Option, org_keys: HashMap, } diff --git a/crates/bitwarden/src/platform/client_platform.rs b/crates/bitwarden/src/platform/client_platform.rs new file mode 100644 index 000000000..ada8b92b8 --- /dev/null +++ b/crates/bitwarden/src/platform/client_platform.rs @@ -0,0 +1,25 @@ +use super::{ + generate_fingerprint::{generate_fingerprint, generate_user_fingerprint}, + FingerprintRequest, FingerprintResponse, +}; +use crate::{error::Result, Client}; + +pub struct ClientPlatform<'a> { + pub(crate) client: &'a mut Client, +} + +impl<'a> ClientPlatform<'a> { + pub fn fingerprint(&self, input: &FingerprintRequest) -> Result { + generate_fingerprint(input) + } + + pub fn user_fingerprint(self, fingerprint_material: String) -> Result { + generate_user_fingerprint(self.client, fingerprint_material) + } +} + +impl<'a> Client { + pub fn platform(&'a mut self) -> ClientPlatform<'a> { + ClientPlatform { client: self } + } +} diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index e9562ab34..a8f45dd87 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -1,5 +1,6 @@ use base64::Engine; -use log::{debug, info}; +use log::info; +use rsa::pkcs8::EncodePublicKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -23,7 +24,6 @@ pub struct FingerprintResponse { pub(crate) fn generate_fingerprint(input: &FingerprintRequest) -> Result { info!("Generating fingerprint"); - debug!("{:?}", input); let key = BASE64_ENGINE.decode(&input.public_key)?; @@ -31,3 +31,65 @@ pub(crate) fn generate_fingerprint(input: &FingerprintRequest) -> Result Result { + info!("Generating fingerprint"); + + let enc_settings = client.get_encryption_settings()?; + let private_key = enc_settings + .private_key + .as_ref() + .ok_or("Missing private key")?; + + let public_key = private_key + .to_public_key() + .to_public_key_der() + .map_err(|_| "Invalid key")?; + + let fingerprint = fingerprint(&fingerprint_material, public_key.as_bytes())?; + + Ok(fingerprint) +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroU32; + + use crate::{ + client::{kdf::Kdf, LoginMethod, UserLoginMethod}, + Client, + }; + + use super::*; + + #[test] + fn test_generate_user_fingerprint() { + let user_key = "2.oZg5RYpU2HjUAKI1DUQCkg==|PyRzI9kZpt66P2OedH8CHOeU0/lgKLkhIJiKDijdyFqIemBSIBoslhfQh/P1TK9xgZp0smgD6+5+yNbZfOpBaCVrsT3WWAO78xOWizduRe4=|xfDLDZSJ+yZAdh388flVg7SMDBJuMs0+CHTjutKs4uQ="; + let private_key = "2.tY6WsWKUbBwNU8wROuipiQ==|DNFL1d19xVojUKTTy2gxT+9J1VXbMQLcbMnx1HSeA6U3yZhsLR6DPaGibb3Bp8doIHtrsxzL/JeLb4gLDZ8RnDhFfE4iLRaPakX14kbBXrKH9/uW/zc7TqIVciWhI1PaeFlu8wnVuGt3e5Ysx6Y7Uw7RS8pRT5aE3sX3aDPGZTAdTutLn1VUfkShS5OK5HJl9CdiwV2wOcrf4w/WqtaNUUqGdsJ8C4ELlpBzHxqs+lEm+8pGPYmuGQIjVc0eOR9Tza9GTk3ih1XGc1znOCoKUZbtA29RfbwfmJy/yGi/3RLWZFQGCCij4cLC5OpldiX4JWL5Dhox44p/5IVF3rfxTVz3GCyDOoHevRG/06sUBq6nhbdCQf3lJvxwcQJhoQg4rsapM3rgol+u+TbXRiwWPbfswuLkRlvGFKtKUWMa4S57gj0CFYgSBPdTyhZTB44D7JQ2bd901Ur1dYWcDe4Kn3ZawpxL0cX2ZPlE3v8FXFJf2s8DJytL8yu73GasDzVmaGHxueWWVz7EHjh+pmB4oaAHARcY8d3LActAyl/+bcFRPYQJ68ae6DJhYYJGHIBWMImf2BifGgUX8vUFfUAYjne3D82lRyZQHs3xbl+ZxEPgWiPYRWUtxGXLLP4f9mbl+LeJdehtHNjC8kOduBL0CsP4gmugzNNUXI+Izc/9svno6kFr6SU0LA3MGrOU8ao7UCQbf/Pj/RKnG1gRmBDQqf7IMm6jOyTwdde9NpfQb32iH11PkuAKBvEtUuq9BeAKWjoZku+ycsN2jZH0hzd/QrU2c+E4+yHwX3wSxxorNOXt5EZkJbEDBlpRyE1zWoyy0wIYfcChYLvFN8QFHchlw5wmHxL+OOgdgndAtV/2DCx+NB6caY31qLictME+1GPPlQ7QvicMLgmpSWq83rs4ex/My6p3hCRSrJJiLvjEDZLYWKHHLd5tsPRAjX8ADNWB1VeIeiJrj1wpOCc1PbWpbljbbTsBmVPo6iKm/UDGAHBdQ//0j3FQg8f5w/j+McsoaMpDNHNTiLvjWERR+RBmsEA0lEL00wZz/DHlzOAYHLYYqFMT7GBCQD+Wk/l1TL+X2agUy7Irlk7QbZ4ivfdNIpSW8Ct9MGE6o4wV+nIpXURojgBBTcP85RTBLXXGrIprnK1G/VE8ONag3+nkqIyChjYyk5QMsxqOqSHsbiOxhCdXypbCbY4g9yKJtBJ/ADjxmELj0X7pqsTFqC0eRT7rk9qTBcYBBu6rwlAfq8AKjDB7WjNjzLaMi6lBoe4petBn1xcLkXD5hHra0TULxcYrq8MIb+Vk4CBZZdwwyVm/28SwSjHBIBpRysPAonDDsp3KlahwXEFvRDQR/oFww172GI7cx8SoPn93Qh0JfpTAAowsO3meR8bzUSyd7v3rmtaBPsWHE9zUXye/6nloMU5joEcD6uJaxd0kdaWWIoKLH++zHW1R776wJrS6u+TIWZgHqiIJoCd9fV25BnQcbZRKd6mnfNQkchJ6c6ozXKrFaa8DLdERdfh84+isw5mzW2zMJwHEwtKt6LUTyieC2exzPAwPxJT1+IMjuzuwiLnvGKOq+kwE/LWBSB0ZfGuCP/3jMM8OCfe7Hbpt1TfXcUxUzj6sSjkjQB6qBt+TINRdOFA=|fppguME86utsAOKrBYn6XU95q7daVbZ+3dD9OVkQlAw="; + let fingerprint_material = "a09726a0-9590-49d1-a5f5-afe300b6a515"; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "a09726a0-9590-49d1-a5f5-afe300b6a515".to_owned(), + email: "robb@stark.com".to_owned(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + })); + client + .initialize_user_crypto( + "asdfasdfasdf", + user_key.parse().unwrap(), + private_key.parse().unwrap(), + ) + .unwrap(); + + let fingerprint = + generate_user_fingerprint(&mut client, fingerprint_material.to_string()).unwrap(); + + assert_eq!(fingerprint, "turban-deftly-anime-chatroom-unselfish"); + } +} diff --git a/crates/bitwarden/src/platform/mod.rs b/crates/bitwarden/src/platform/mod.rs index 0e234f00b..b78cb27d4 100644 --- a/crates/bitwarden/src/platform/mod.rs +++ b/crates/bitwarden/src/platform/mod.rs @@ -1,10 +1,10 @@ +pub mod client_platform; mod domain; mod generate_fingerprint; mod get_user_api_key; mod secret_verification_request; mod sync; -pub(crate) use generate_fingerprint::generate_fingerprint; pub use generate_fingerprint::{FingerprintRequest, FingerprintResponse}; pub(crate) use get_user_api_key::get_user_api_key; pub use get_user_api_key::UserApiKeyResponse; diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 9249751f0..27b376051 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -84,7 +84,7 @@ Test method, echoes back the input ### `satisfies_policy` -**API Draft:** Evaluate if the provided password satisfies the provided policy +Evaluate if the provided password satisfies the provided policy **Arguments**: @@ -333,6 +333,17 @@ Decrypt folder list **Output**: std::result::Result +### `username` + +**API Draft:** Generate Username + +**Arguments**: + +- self: +- settings: UsernameGeneratorRequest + +**Output**: std::result::Result + ## ClientPasswordHistory ### `encrypt` @@ -361,7 +372,7 @@ Decrypt password history ### `fingerprint` -Fingerprint +Fingerprint (public key) **Arguments**: @@ -370,6 +381,17 @@ Fingerprint **Output**: std::result::Result +### `user_fingerprint` + +Fingerprint using logged in user's public key + +**Arguments**: + +- self: +- fingerprint_material: String + +**Output**: std::result::Result + ## ClientSends ### `encrypt` @@ -800,7 +822,7 @@ implementations. id - string + string,null @@ -891,7 +913,7 @@ implementations. id - string + string,null @@ -916,7 +938,7 @@ implementations. id - string + string,null @@ -1296,12 +1318,12 @@ implementations. id - string + string,null accessId - string + string,null @@ -1386,12 +1408,12 @@ implementations. id - string + string,null accessId - string + string,null From 816799d4e6aa14cc7748f388ea839ca0ec44952b Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 5 Jan 2024 11:52:16 +0100 Subject: [PATCH 166/378] Change jwt parsing to use URL_SAFE_NO_PAD (#450) JWT should be url encoded and never use padding. --- crates/bitwarden/src/auth/jwt_token.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden/src/auth/jwt_token.rs b/crates/bitwarden/src/auth/jwt_token.rs index 17e0e13e9..f4d4692ee 100644 --- a/crates/bitwarden/src/auth/jwt_token.rs +++ b/crates/bitwarden/src/auth/jwt_token.rs @@ -1,8 +1,8 @@ use std::str::FromStr; -use base64::Engine; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use crate::{error::Result, util::BASE64_ENGINE}; +use crate::error::Result; /// A Bitwarden secrets manager JWT Token. /// @@ -31,7 +31,7 @@ impl FromStr for JWTToken { if split.len() != 3 { return Err("JWT token has an invalid number of parts".into()); } - let decoded = BASE64_ENGINE.decode(split[1])?; + let decoded = URL_SAFE_NO_PAD.decode(split[1])?; Ok(serde_json::from_slice(&decoded)?) } } From 0f4184ce6c7bb2fbaa3bab0600c7dfdaed4bc0a6 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 5 Jan 2024 15:18:29 +0100 Subject: [PATCH 167/378] Codecov ignore tools (#476) Ignore tools since they don't need to be tested. --- .github/codecov.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/codecov.yml diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 000000000..3228d009c --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "crates/sdk-schemas" # Tool + - "crates/uniffi-bindgen" # Tool From fa09ad6932f64967cfad5fee10af592ca2be1266 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:57:35 +0100 Subject: [PATCH 168/378] [deps]: Update @types/node to v18.19.5 (#483) --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 76fc3e341..f1c72fa87 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.4.tgz", - "integrity": "sha512-xNzlUhzoHotIsnFoXmJB+yWmBvFZgKCI9TtPIEdYIMM1KWfwuY8zh7wvc1u1OAXlC7dlf6mZVx/s+Y5KfFz19A==", + "version": "18.19.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.5.tgz", + "integrity": "sha512-22MG6T02Hos2JWfa1o5jsIByn+bc5iOt1IS4xyg6OG68Bu+wMonVZzdrgCw693++rpLE9RUT/Bx15BeDzO0j+g==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From bbdd18fbbdd4987da041d5d412e10418c26ef51c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:58:21 +0100 Subject: [PATCH 169/378] [deps]: Update Rust crate clap to 4.4.13 (#478) --- Cargo.lock | 4 ++-- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 498aaf85b..b4aa123b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.12" +version = "4.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642" dependencies = [ "clap_builder", "clap_derive", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 08381a47c..217ac88c1 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.12", features = ["derive"] } +clap = { version = "4.4.13", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 059b853a5..d1298cf43 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.12", features = ["derive", "env"] } +clap = { version = "4.4.13", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 90c2cdb05..81994ad1f 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.12", features = ["derive", "env", "string"] } +clap = { version = "4.4.13", features = ["derive", "env", "string"] } clap_complete = "4.4.6" color-eyre = "0.6" comfy-table = "^7.1.0" From abaf067cfff78478ea431108e62f13cd98cf481a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:00:13 +0100 Subject: [PATCH 170/378] [deps]: Update quicktype-core to v23.0.81 (#482) --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3aa3c5092..b2bda48e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.1", - "quicktype-core": "23.0.80", + "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", "typescript": "5.3.3" @@ -1494,9 +1494,9 @@ } }, "node_modules/quicktype-core": { - "version": "23.0.80", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.80.tgz", - "integrity": "sha512-dd+aJRzAl3MzkaXJMjUu0j60y82gwX/RRr3EvW/aScQKycvkgwliNDN2tIiLB06EKBzjgC9mtlMqKyRg2rYKhQ==", + "version": "23.0.81", + "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.81.tgz", + "integrity": "sha512-iJQpCEzSQIkffJPS5NC+0w+Rq9faGgz09L+WIbseu1toFfj+M/3KTG5jhzdY/uN88fWosAom2fMoEADA403+rQ==", "dev": true, "dependencies": { "@glideapps/ts-necessities": "2.1.3", diff --git a/package.json b/package.json index 683635f01..319086900 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", "prettier": "3.1.1", - "quicktype-core": "23.0.80", + "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", "typescript": "5.3.3" From 3b220c5ef8a34bee5216e1e1e55fda2e70f309cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:01:00 +0000 Subject: [PATCH 171/378] [deps]: Update Rust crate serde to v1.0.195 (#479) --- Cargo.lock | 8 ++++---- crates/bitwarden-wasm/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4aa123b6..99c81ecb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2793,18 +2793,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 176edeaa9..4a4d7696c 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -12,7 +12,7 @@ console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.66" log = "0.4.20" -serde = { version = "1.0.193", features = ["derive"] } +serde = { version = "1.0.195", features = ["derive"] } wasm-bindgen = { version = "0.2.89", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.39" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 81994ad1f..9466398e1 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -31,7 +31,7 @@ regex = { version = "1.10.2", features = [ "std", "perf", ], default-features = false } -serde = "^1.0.193" +serde = "^1.0.195" serde_json = "^1.0.108" serde_yaml = "0.9" supports-color = "2.1.0" From 2b561306c5a2070fc3722d8f415997828ee5873d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:08:32 +0100 Subject: [PATCH 172/378] [deps]: Update Rust crate serde_json to v1.0.111 (#480) --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- crates/sdk-schemas/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c81ecb6..c53cd9086 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2824,9 +2824,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa", "ryu", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 9466398e1..821c6153c 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -32,7 +32,7 @@ regex = { version = "1.10.2", features = [ "perf", ], default-features = false } serde = "^1.0.195" -serde_json = "^1.0.108" +serde_json = "^1.0.111" serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.56" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 7ae1874b4..05c52bffa 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -15,7 +15,7 @@ internal = [ anyhow = "1.0.79" itertools = "0.12.0" schemars = { version = "0.8.16", features = ["preserve_order"] } -serde_json = "1.0.108" +serde_json = "1.0.111" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From e96a79faa628ae2e191228b584918f09c3545160 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:19:42 +0100 Subject: [PATCH 173/378] [deps]: Update pyo3 non-major to 0.20.2 (#481) --- Cargo.lock | 20 ++++++++++---------- crates/bitwarden-py/Cargo.toml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c53cd9086..ebf999c2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2304,9 +2304,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82ad98ce1991c9c70c3464ba4187337b9c45fcbbb060d46dca15f0c075e14e2" +checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0" dependencies = [ "cfg-if", "indoc", @@ -2346,9 +2346,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5503d0b3aee2c7a8dbb389cd87cd9649f675d4c7f60ca33699a3e3859d81a891" +checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be" dependencies = [ "once_cell", "target-lexicon", @@ -2356,9 +2356,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a79e8d80486a00d11c0dcb27cd2aa17c022cc95c677b461f01797226ba8f41" +checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1" dependencies = [ "libc", "pyo3-build-config", @@ -2377,9 +2377,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4b0dc7eaa578604fab11c8c7ff8934c71249c61d4def8e272c76ed879f03d4" +checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2389,9 +2389,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816a4f709e29ddab2e3cdfe94600d554c5556cad0ddfeea95c47b580c3247fa4" +checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f" dependencies = [ "heck", "proc-macro2", diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 1d52d0b2b..ed7c5df5e 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -9,13 +9,13 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.20.1", features = ["extension-module"] } +pyo3 = { version = "0.20.2", features = ["extension-module"] } pyo3-log = "0.9.0" bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [build-dependencies] -pyo3-build-config = { version = "0.20.1" } +pyo3-build-config = { version = "0.20.2" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } From f9986134a144cc55db7d2188e754d93250ea8246 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 8 Jan 2024 10:20:20 +0100 Subject: [PATCH 174/378] Update PULL_REQUEST_TEMPLATE.md (#475) Remove screenshot section. It's never used. --- .github/PULL_REQUEST_TEMPLATE.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e195cfd64..de0ba909c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -21,10 +21,6 @@ - **file.ext:** Description of what was changed and why -## Screenshots - - - ## Before you submit -- Please add **unit tests** where it makes sense to do so (encouraged but not required) +- Please add **unit tests** where it makes sense to do so From c45ad21e187ff59350ad560ba66c2b4dcbf2b093 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 8 Jan 2024 10:46:54 +0100 Subject: [PATCH 175/378] Convert totp secret to uppercase (#485) Some totp providers use lowercase secrets. This isn't valid base32 though and needs to be transformed into uppercase prior to parsing. --- crates/bitwarden/src/vault/totp.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 4adbe4dac..9bc92229b 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -129,7 +129,7 @@ impl FromStr for Totp { fn from_str(key: &str) -> Result { fn decode_secret(secret: &str) -> Result> { BASE32 - .decode(secret.as_bytes()) + .decode(secret.to_uppercase().as_bytes()) .map_err(|_| "Unable to decode secret".into()) } @@ -230,6 +230,20 @@ mod tests { assert_eq!(response.period, 30); } + #[test] + fn test_lowercase_secret() { + let key = "wqiq25brkzycjvyp".to_string(); + let time = Some( + DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") + .unwrap() + .with_timezone(&Utc), + ); + let response = generate_totp(key, time).unwrap(); + + assert_eq!(response.code, "194506".to_string()); + assert_eq!(response.period, 30); + } + #[test] fn test_generate_otpauth() { let key = "otpauth://totp/test-account?secret=WQIQ25BRKZYCJVYP".to_string(); From bd592bd7ac5f4cdbfa85196d80ff2f7fcaec9080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 8 Jan 2024 12:38:53 +0100 Subject: [PATCH 176/378] Fix simplelogin auth (#486) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Simplelogin was using the bearer Authorization header while it was supposed to use non-standard Authentication --- .../src/tool/generators/username_forwarders/simplelogin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs b/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs index 3c09fc691..6c4f9dab4 100644 --- a/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs +++ b/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs @@ -31,7 +31,7 @@ async fn generate_with_api_url( let response = http .post(format!("{api_url}/api/alias/random/new{query}")) .header(CONTENT_TYPE, "application/json") - .bearer_auth(api_key) + .header("Authentication", api_key) .json(&Request { note }) .send() .await?; @@ -65,7 +65,7 @@ mod tests { .and(matchers::method("POST")) .and(matchers::query_param("hostname", "example.com")) .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::header("Authentication", "MY_TOKEN")) .and(matchers::body_json(json!({ "note": "Website: example.com. Generated by Bitwarden." }))) @@ -78,7 +78,7 @@ mod tests { .and(matchers::method("POST")) .and(matchers::query_param("hostname", "example.com")) .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .and(matchers::header("Authentication", "MY_FAKE_TOKEN")) .and(matchers::body_json(json!({ "note": "Website: example.com. Generated by Bitwarden." }))) From fa4c2f7582a548a17a64085879c86ec3c103d592 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 8 Jan 2024 12:55:18 +0100 Subject: [PATCH 177/378] Fix SendView.key behaviour and fix types for SendFile and SendFileView (#484) --- crates/bitwarden/src/error.rs | 2 + crates/bitwarden/src/vault/send.rs | 181 ++++++++++++++++++++++++----- 2 files changed, 153 insertions(+), 30 deletions(-) diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index bb70adebf..48cb7da16 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -100,6 +100,8 @@ pub enum CryptoError { NoKeyForOrg, #[error("The value is not a valid UTF8 String")] InvalidUtf8String, + #[error("Missing key")] + MissingKey, } #[derive(Debug, Error)] diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index e732170c5..e0699ef9c 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,3 +1,4 @@ +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -10,29 +11,29 @@ use crate::{ derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, }, - error::{Error, Result}, + error::{CryptoError, Error, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendFile { - pub id: String, + pub id: Option, pub file_name: EncString, - pub size: String, + pub size: Option, /// Readable size, ex: "4.2 KB" or "1.43 GB" - pub size_name: String, + pub size_name: Option, } -#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendFileView { - pub id: String, + pub id: Option, pub file_name: String, - pub size: String, + pub size: Option, /// Readable size, ex: "4.2 KB" or "1.43 GB" - pub size_name: String, + pub size_name: Option, } #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -43,7 +44,7 @@ pub struct SendText { pub hidden: bool, } -#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendTextView { @@ -51,7 +52,7 @@ pub struct SendTextView { pub hidden: bool, } -#[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] +#[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema, PartialEq)] #[repr(u8)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] pub enum SendType { @@ -85,7 +86,7 @@ pub struct Send { pub expiration_date: Option>, } -#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SendView { @@ -94,7 +95,8 @@ pub struct SendView { pub name: String, pub notes: Option, - pub key: EncString, + /// Base64 encoded key + pub key: Option, pub password: Option, pub r#type: SendType, @@ -134,8 +136,12 @@ impl Send { enc_key: &SymmetricCryptoKey, ) -> Result { let key: Vec = send_key.decrypt_with_key(enc_key)?; - let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); - Ok(key) + Self::derive_shareable_key(&key) + } + + fn derive_shareable_key(key: &[u8]) -> Result { + let key = key.try_into().map_err(|_| CryptoError::InvalidKeyLen)?; + Ok(derive_shareable_key(key, "send", Some("send"))) } } @@ -184,7 +190,8 @@ impl KeyDecryptable for Send { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key - let key = Send::get_key(&self.key, key)?; + let k: Vec = self.key.decrypt_with_key(key)?; + let key = Send::derive_shareable_key(&k)?; Ok(SendView { id: self.id, @@ -192,7 +199,7 @@ impl KeyDecryptable for Send { name: self.name.decrypt_with_key(&key)?, notes: self.notes.decrypt_with_key(&key)?, - key: self.key.clone(), + key: Some(URL_SAFE_NO_PAD.encode(k)), password: self.password.clone(), r#type: self.r#type, @@ -238,20 +245,23 @@ impl KeyEncryptable for SendView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key - let key = Send::get_key(&self.key, key)?; + let k = URL_SAFE_NO_PAD + .decode(self.key.ok_or(CryptoError::MissingKey)?) + .map_err(|_| CryptoError::InvalidKey)?; + let send_key = Send::derive_shareable_key(&k)?; Ok(Send { id: self.id, access_id: self.access_id, - name: self.name.encrypt_with_key(&key)?, - notes: self.notes.encrypt_with_key(&key)?, - key: self.key.clone(), + name: self.name.encrypt_with_key(&send_key)?, + notes: self.notes.encrypt_with_key(&send_key)?, + key: k.encrypt_with_key(key)?, password: self.password.clone(), r#type: self.r#type, - file: self.file.encrypt_with_key(&key)?, - text: self.text.encrypt_with_key(&key)?, + file: self.file.encrypt_with_key(&send_key)?, + text: self.text.encrypt_with_key(&send_key)?, max_access_count: self.max_access_count, access_count: self.access_count, @@ -304,10 +314,10 @@ impl TryFrom for SendFile { fn try_from(file: SendFileModel) -> Result { Ok(SendFile { - id: file.id.ok_or(Error::MissingFields)?, + id: file.id, file_name: file.file_name.ok_or(Error::MissingFields)?.parse()?, - size: file.size.ok_or(Error::MissingFields)?.to_string(), - size_name: file.size_name.ok_or(Error::MissingFields)?, + size: file.size.map(|v| v.to_string()), + size_name: file.size_name, }) } } @@ -325,8 +335,12 @@ impl TryFrom for SendText { #[cfg(test)] mod tests { - use super::Send; - use crate::client::{encryption_settings::EncryptionSettings, kdf::Kdf, UserLoginMethod}; + use super::{Send, SendText, SendTextView, SendType}; + use crate::{ + client::{encryption_settings::EncryptionSettings, kdf::Kdf, UserLoginMethod}, + crypto::{KeyDecryptable, KeyEncryptable}, + vault::SendView, + }; #[test] fn test_get_send_key() { @@ -360,12 +374,12 @@ mod tests { password: None, r#type: super::SendType::File, file: Some(super::SendFile { - id: "7f129hzwu0umkmnmsghkt486w96p749c".into(), + id: Some("7f129hzwu0umkmnmsghkt486w96p749c".into()), file_name: "2.pnszM3slsCVlOIzuWrfCpA==|85zCg+X8GODvIAPf1Yt3K75YP+ub3wVAi1UvwOVXhPgUo9Gsu23FJgYSOkyKu3Vr|OvTrOugwRH7Mp2BWSuPlfxovoWt9oDRdi1Qo3xHUcdQ=" .parse() .unwrap(), - size: "1251825".into(), - size_name: "1.19 MB".into(), + size: Some("1251825".into()), + size_name: Some("1.19 MB".into()), }), text: None, max_access_count: None, @@ -382,4 +396,111 @@ mod tests { let send_key_b64 = send_key.to_base64(); assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } + + fn build_encryption_settings() -> EncryptionSettings { + EncryptionSettings::new( + &UserLoginMethod::Username { + client_id: "test".into(), + email: "test@bitwarden.com".into(), + kdf: Kdf::PBKDF2 { + iterations: 600_000.try_into().unwrap(), + }, + }, + "asdfasdfasdf", + "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(), + "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap(), + ).unwrap() + } + + #[test] + pub fn test_decrypt() { + let enc = build_encryption_settings(); + let key = enc.get_key(&None).unwrap(); + + let send = Send { + id: "3d80dd72-2d14-4f26-812c-b0f0018aa144".parse().ok(), + access_id: Some("ct2APRQtJk-BLLDwAYqhRA".to_owned()), + r#type: SendType::Text, + name: "2.STIyTrfDZN/JXNDN9zNEMw==|NDLum8BHZpPNYhJo9ggSkg==|UCsCLlBO3QzdPwvMAWs2VVwuE6xwOx/vxOooPObqnEw=".parse() + .unwrap(), + notes: None, + file: None, + text: Some(SendText { + text: "2.2VPyLzk1tMLug0X3x7RkaQ==|mrMt9vbZsCJhJIj4eebKyg==|aZ7JeyndytEMR1+uEBupEvaZuUE69D/ejhfdJL8oKq0=".parse().ok(), + hidden: false, + }), + key: "2.KLv/j0V4Ebs0dwyPdtt4vw==|jcrFuNYN1Qb3onBlwvtxUV/KpdnR1LPRL4EsCoXNAt4=|gHSywGy4Rj/RsCIZFwze4s2AACYKBtqDXTrQXjkgtIE=".parse().unwrap(), + max_access_count: None, + access_count: 0, + password: None, + disabled: false, + revision_date: "2024-01-07T23:56:48.207363Z".parse().unwrap(), + expiration_date: None, + deletion_date: "2024-01-14T23:56:48Z".parse().unwrap(), + hide_email: false, + }; + + let view: SendView = send.decrypt_with_key(key).unwrap(); + + let expected = SendView { + id: "3d80dd72-2d14-4f26-812c-b0f0018aa144".parse().ok(), + access_id: Some("ct2APRQtJk-BLLDwAYqhRA".to_owned()), + name: "Test".to_string(), + notes: None, + key: Some("Pgui0FK85cNhBGWHAlBHBw".to_owned()), + password: None, + r#type: SendType::Text, + file: None, + text: Some(SendTextView { + text: Some("This is a test".to_owned()), + hidden: false, + }), + max_access_count: None, + access_count: 0, + disabled: false, + hide_email: false, + revision_date: "2024-01-07T23:56:48.207363Z".parse().unwrap(), + deletion_date: "2024-01-14T23:56:48Z".parse().unwrap(), + expiration_date: None, + }; + + assert_eq!(view, expected); + } + + #[test] + pub fn test_encrypt() { + let enc = build_encryption_settings(); + let key = enc.get_key(&None).unwrap(); + + let view = SendView { + id: "3d80dd72-2d14-4f26-812c-b0f0018aa144".parse().ok(), + access_id: Some("ct2APRQtJk-BLLDwAYqhRA".to_owned()), + name: "Test".to_string(), + notes: None, + key: Some("Pgui0FK85cNhBGWHAlBHBw".to_owned()), + password: None, + r#type: SendType::Text, + file: None, + text: Some(SendTextView { + text: Some("This is a test".to_owned()), + hidden: false, + }), + max_access_count: None, + access_count: 0, + disabled: false, + hide_email: false, + revision_date: "2024-01-07T23:56:48.207363Z".parse().unwrap(), + deletion_date: "2024-01-14T23:56:48Z".parse().unwrap(), + expiration_date: None, + }; + + // Re-encrypt and decrypt again to ensure encrypt works + let v: SendView = view + .clone() + .encrypt_with_key(key) + .unwrap() + .decrypt_with_key(key) + .unwrap(); + assert_eq!(v, view); + } } From 332293bade95676ab7434548b872e887d080d8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 8 Jan 2024 13:13:04 +0100 Subject: [PATCH 178/378] Fix firefox forwarder when website isn't set (#487) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective When the website parameter is None, the request would include a `generated_for: null` field, while the API expects the field to not be present. --- .../generators/username_forwarders/firefox.rs | 81 ++++++++++++++----- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs b/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs index 2c45803a5..e53931358 100644 --- a/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs +++ b/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs @@ -22,6 +22,7 @@ async fn generate_with_api_url( #[derive(serde::Serialize)] struct Request { enabled: bool, + #[serde(skip_serializing_if = "Option::is_none")] generated_for: Option, description: String, } @@ -58,13 +59,13 @@ async fn generate_with_api_url( #[cfg(test)] mod tests { use serde_json::json; + #[tokio::test] - async fn test_mock_server() { + async fn test_mock_success() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = crate::util::start_mock(vec![ - // Mock the request to the Firefox API, and verify that the correct request is made - Mock::given(matchers::path("/api/v1/relayaddresses/")) + let (server, _client) = + crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) .and(matchers::method("POST")) .and(matchers::header("Content-Type", "application/json")) .and(matchers::header("Authorization", "Token MY_TOKEN")) @@ -76,33 +77,73 @@ mod tests { .respond_with(ResponseTemplate::new(201).set_body_json(json!({ "full_address": "ofuj4d4qw@mozmail.com" }))) - .expect(1), - // Mock an invalid API key - Mock::given(matchers::path("/api/v1/relayaddresses/")) + .expect(1)]) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "ofuj4d4qw@mozmail.com"); + + server.verify().await; + } + + #[tokio::test] + async fn test_mock_without_website() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = + crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) .and(matchers::method("POST")) .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Token MY_FAKE_TOKEN")) + .and(matchers::header("Authorization", "Token MY_OTHER_TOKEN")) .and(matchers::body_json(json!({ "enabled": true, - "generated_for": "example.com", - "description": "example.com - Generated by Bitwarden." + "description": "Generated by Bitwarden." }))) - .respond_with(ResponseTemplate::new(401)) - .expect(1), - ]) - .await; + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "full_address": "856f7765@mozmail.com" + }))) + .expect(1)]) + .await; let address = super::generate_with_api_url( &reqwest::Client::new(), - "MY_TOKEN".into(), - Some("example.com".into()), + "MY_OTHER_TOKEN".into(), + None, format!("http://{}", server.address()), ) .await .unwrap(); - assert_eq!(address, "ofuj4d4qw@mozmail.com"); + assert_eq!(address, "856f7765@mozmail.com"); + + server.verify().await; + } + + #[tokio::test] + async fn test_mock_invalid_token() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let (server, _client) = + crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "generated_for": "example.com", + "description": "example.com - Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1)]) + .await; - let fake_token_error = super::generate_with_api_url( + let error = super::generate_with_api_url( &reqwest::Client::new(), "MY_FAKE_TOKEN".into(), Some("example.com".into()), @@ -111,9 +152,7 @@ mod tests { .await .unwrap_err(); - assert!(fake_token_error - .to_string() - .contains("Invalid Firefox Relay API key")); + assert!(error.to_string().contains("Invalid Firefox Relay API key")); server.verify().await; } From 719f7e82a9b1ae2c90e8b1e9561c2c809f196826 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:37:20 -0500 Subject: [PATCH 179/378] [deps]: Update gh minor (#463) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 4 ++-- .github/workflows/build-dotnet.yml | 10 +++++----- .github/workflows/build-java.yml | 12 ++++++------ .github/workflows/build-napi.yml | 2 +- .github/workflows/publish-dotnet.yml | 10 +++++----- .github/workflows/publish-php.yml | 8 ++++---- .github/workflows/publish-ruby.yml | 12 ++++++------ .github/workflows/version-bump.yml | 2 +- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 784beb168..f8bee2f56 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -86,7 +86,7 @@ jobs: java-version: 17 - name: Download Artifacts - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 - name: Move artifacts working-directory: languages/kotlin/sdk/src/main/jniLibs @@ -102,7 +102,7 @@ jobs: run: ./build-schemas.sh - name: Publish - uses: gradle/gradle-build-action@8cbcb9948b5892387aed077daf6f90e1f0ba5b27 # v2.11.0 + uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1 with: arguments: sdk:publish build-root-directory: languages/kotlin diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 4732a1936..b0f3e7b63 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -118,12 +118,12 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: bws-x86_64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip - name: Download aarch64-apple-darwin artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: bws-aarch64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index a7cad42c0..904cea204 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -35,25 +35,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index a2c0938ec..d2bc049d1 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download Java schemas artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: sdk-schemas-java path: languages/java/src/main/java/bit/sdk/schema/ @@ -36,31 +36,31 @@ jobs: java-version: 17 - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/java/src/main/resources/darwin-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/java/src/main/resources/darwin-aarch64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/java/src/main/resources/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/java/src/main/resources/windows-x64 - name: Publish Maven - uses: gradle/gradle-build-action@8cbcb9948b5892387aed077daf6f90e1f0ba5b27 # v2.11.0 + uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1 with: arguments: publish build-root-directory: languages/java diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 39674c2ea..ef72e7f1e 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -72,7 +72,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: schemas.ts path: ${{ github.workspace }}/crates/bitwarden-napi/src-ts/bitwarden_client/ diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index e9b1076fe..a7a6a6e0e 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -37,25 +37,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index c9d88a29e..6ed52537a 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -33,25 +33,25 @@ jobs: working-directory: languages/php/ - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 01f6be58d..4315dea66 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,36 +23,36 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@af848b40be8bb463a751551a1180d74782ba8a72 # v1.162.0 + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 with: ruby-version: 3.2 - name: Download Ruby schemas artifact - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: schemas.rb path: languages/ruby/bitwarden_sdk/lib - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@7a1cd3216ca9260cd8022db641d960b1db4d1be4 # v4.0.0 + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index fae8b0bc5..b27a6a989 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -61,7 +61,7 @@ jobs: repository: bitwarden/sdk - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 + 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 }} From 679673096254e108fa0d71f65bf8fa28ba9679f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 8 Jan 2024 18:28:00 +0100 Subject: [PATCH 180/378] [PM-4269] Use rustls on non-wasm platforms (#374) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Updated reqwest to use rustls on all platforms. We're also using rustls-platform-verifier where possible to load the CA certificates from the operating system store instead of including them in the binary. Note that WASM doesn't need a TLS stack as reqwest just uses the browser's `fetch` | | TLS Stack | CA Validator | Accepts self signed in OS root store | |---------|-----------|--------------------------|--------------------------------------| | Windows | RusTLS | ustls-platform-verifier | Yes | | Linux | RusTLS | rustls-platform-verifier (Native+WebPKI) | Yes | | Mac | RusTLS | rustls-platform-verifier (Native) | Yes | | Android | RusTLS | WebPKI | No | | iOS | RusTLS | rustls-platform-verifier (Native) | Yes | | WASM | fetch | fetch | Maybe, use browser config | --- Cargo.lock | 270 ++++++++++++++--------- about.toml | 5 + crates/bitwarden-api-api/Cargo.toml | 1 + crates/bitwarden-api-identity/Cargo.toml | 1 + crates/bitwarden-uniffi/Cargo.toml | 3 - crates/bitwarden/CHANGELOG.md | 4 + crates/bitwarden/Cargo.toml | 21 +- crates/bitwarden/src/client/client.rs | 14 +- crates/bws/CHANGELOG.md | 4 + crates/bws/Cargo.toml | 3 - crates/bws/Cross.toml | 6 - support/openapi-template/Cargo.mustache | 1 + 12 files changed, 213 insertions(+), 120 deletions(-) delete mode 100644 crates/bws/Cross.toml diff --git a/Cargo.lock b/Cargo.lock index ebf999c2c..4849ad02c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -351,6 +351,7 @@ dependencies = [ "rand_chacha 0.3.1", "reqwest", "rsa", + "rustls-platform-verifier", "schemars", "serde", "serde_json", @@ -454,7 +455,6 @@ dependencies = [ "bitwarden", "chrono", "env_logger", - "openssl", "schemars", "uniffi", ] @@ -546,7 +546,6 @@ dependencies = [ "directories", "env_logger", "log", - "openssl", "regex", "serde", "serde_json", @@ -633,6 +632,12 @@ dependencies = [ "libc", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.0" @@ -758,6 +763,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "comfy-table" version = "7.1.0" @@ -1140,21 +1155,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1522,16 +1522,17 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "bytes", + "futures-util", + "http", "hyper", - "native-tls", + "rustls", "tokio", - "tokio-native-tls", + "tokio-rustls", ] [[package]] @@ -1679,6 +1680,26 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "js-sys" version = "0.3.66" @@ -1694,7 +1715,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] [[package]] @@ -1900,24 +1921,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "newline-converter" version = "0.2.2" @@ -2071,60 +2074,12 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "openssl" -version = "0.10.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" -dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.47", -] - [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-src" -version = "300.2.1+3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -2573,27 +2528,29 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "log", "mime", "mime_guess", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] @@ -2612,6 +2569,20 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom 0.2.11", + "libc", + "spin 0.9.8", + "untrusted", + "windows-sys 0.48.0", +] + [[package]] name = "rsa" version = "0.9.6" @@ -2651,6 +2622,76 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.5", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c573e165e19be8c9fc0264ee041d66292d4ee0439949af61d71fa747bf5df082" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e217e7fdc8466b5b35d30f8c0a30febd29173df4a3a0c2115d306b9c4117ad" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -2746,6 +2787,16 @@ dependencies = [ "syn 2.0.47", ] +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "sdk-schemas" version = "0.1.0" @@ -2769,6 +2820,7 @@ dependencies = [ "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] @@ -3024,6 +3076,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.7.3" @@ -3291,12 +3349,12 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "native-tls", + "rustls", "tokio", ] @@ -3639,6 +3697,12 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -3672,12 +3736,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" @@ -3824,6 +3882,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" + [[package]] name = "weedle2" version = "4.0.0" diff --git a/about.toml b/about.toml index 2ed67c7cc..bd56148af 100644 --- a/about.toml +++ b/about.toml @@ -8,4 +8,9 @@ accepted = [ "MPL-2.0", "LGPL-3.0", "Unicode-DFS-2016", + "OpenSSL", ] + +# Ring has all the licenses combined into a single file, which causes cargo about to +# be confused about it. Thankfully it includes a workaround for this that we can enable. +workarounds = ["ring"] diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index e4ec902b1..5b8b0c773 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -22,5 +22,6 @@ uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] version = ">=0.11.18, <0.12" features = ["json", "multipart"] +default-features = false [dev-dependencies] diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 929bbc6fa..4f4b46732 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -22,5 +22,6 @@ uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] version = ">=0.11.18, <0.12" features = ["json", "multipart"] +default-features = false [dev-dependencies] diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index ecde30a4b..4bf7b085b 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -25,6 +25,3 @@ bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } [build-dependencies] uniffi = { version = "=0.25.2", features = ["build"] } - -[target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] -openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index b4a57cde1..ff47c19d8 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -7,6 +7,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + +- Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. + ## [0.4.0] - 2023-12-21 ### Added diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 5677a73d9..2fd1f32e6 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -46,7 +46,9 @@ num-bigint = ">=0.4, <0.5" num-traits = ">=0.2.15, <0.3" pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } rand = ">=0.8.5, <0.9" -reqwest = { version = ">=0.11, <0.12", features = ["json"] } +reqwest = { version = ">=0.11, <0.12", features = [ + "json", +], default-features = false } rsa = ">=0.9.2, <0.10" schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } @@ -60,6 +62,23 @@ thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.2", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } +[target.'cfg(all(not(target_os = "android"), not(target_arch="wasm32")))'.dependencies] +# By default, we use rustls as the TLS stack and rust-platform-verifier to support user-installed root certificates +# There are a few exceptions to this: +# - WASM doesn't require a TLS stack, as it just uses the browsers/node fetch +# - Android uses webpki-roots for the moment +reqwest = { version = "*", features = [ + "rustls-tls-manual-roots", +], default-features = false } +rustls-platform-verifier = "0.1.0" + +[target.'cfg(target_os = "android")'.dependencies] +# On android, the use of rustls-platform-verifier is more complicated and going through some changes at the moment, so we fall back to using webpki-roots +# This means that for the moment android won't support self-signed certificates, even if they are included in the OS trust store +reqwest = { version = "*", features = [ + "rustls-tls-webpki-roots", +], default-features = false } + [dev-dependencies] rand_chacha = "0.3.1" tokio = { version = "1.35.1", features = ["rt", "macros"] } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 302e7ed75..2c5d9b387 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -88,10 +88,16 @@ impl Client { let headers = header::HeaderMap::new(); - let client = reqwest::Client::builder() - .default_headers(headers) - .build() - .unwrap(); + #[allow(unused_mut)] + let mut client_builder = reqwest::Client::builder().default_headers(headers); + + #[cfg(all(not(target_os = "android"), not(target_arch = "wasm32")))] + { + client_builder = + client_builder.use_preconfigured_tls(rustls_platform_verifier::tls_config()); + } + + let client = client_builder.build().unwrap(); let identity = bitwarden_api_identity::apis::configuration::Configuration { base_path: settings.identity_url, diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 007639800..d5ba27061 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,6 +7,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + +- Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. + ## [0.4.0] - 2023-12-21 ### Added diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 821c6153c..980fe684e 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -44,6 +44,3 @@ bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } [dev-dependencies] tempfile = "3.9.0" - -[target.'cfg(target_os = "linux")'.dependencies] -openssl = { version = "0.10", features = ["vendored"] } diff --git a/crates/bws/Cross.toml b/crates/bws/Cross.toml deleted file mode 100644 index 79b22e7f8..000000000 --- a/crates/bws/Cross.toml +++ /dev/null @@ -1,6 +0,0 @@ -# Install OpenSSL -[target.aarch64-unknown-linux-gnu] -pre-build = [ - "dpkg --add-architecture $CROSS_DEB_ARCH", - "apt-get update && apt-get install --assume-yes libssl-dev:$CROSS_DEB_ARCH", -] diff --git a/support/openapi-template/Cargo.mustache b/support/openapi-template/Cargo.mustache index 38885cb6f..3b89aa079 100644 --- a/support/openapi-template/Cargo.mustache +++ b/support/openapi-template/Cargo.mustache @@ -27,6 +27,7 @@ reqwest = "~0.9" [dependencies.reqwest] version = "^0.11" features = ["json", "multipart"] +default-features = false {{/supportAsync}} {{/reqwest}} {{#withAWSV4Signature}} From 37e4eaf9c66fdc2d54a88cbb4c5c25258b15ec1a Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 9 Jan 2024 11:17:51 +0100 Subject: [PATCH 181/378] Support generating a random send key if none is provided (#488) When creating a new send, we should generate a key for it. --- crates/bitwarden/src/crypto/mod.rs | 12 ++++ .../src/crypto/symmetric_crypto_key.rs | 5 +- crates/bitwarden/src/vault/send.rs | 60 +++++++++++++++++-- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index 84697e8a5..94db974d3 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -23,6 +23,10 @@ use aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; use hmac::digest::OutputSizeUser; +use rand::{ + distributions::{Distribution, Standard}, + Rng, +}; use crate::error::Result; @@ -73,3 +77,11 @@ fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result() -> T +where + Standard: Distribution, +{ + rand::thread_rng().gen() +} diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs index 5bce9e65d..741fe0559 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs @@ -4,7 +4,7 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; use crate::{ - crypto::derive_shareable_key, + crypto::{derive_shareable_key, generate_random_bytes}, error::{CryptoError, Error}, util::BASE64_ENGINE, }; @@ -20,8 +20,7 @@ impl SymmetricCryptoKey { const MAC_LEN: usize = 32; pub fn generate(name: &str) -> Self { - use rand::Rng; - let secret: [u8; 16] = rand::thread_rng().gen(); + let secret: [u8; 16] = generate_random_bytes(); derive_shareable_key(secret, name, None) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index e0699ef9c..ce100db3e 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -8,8 +8,8 @@ use uuid::Uuid; use crate::{ crypto::{ - derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, - SymmetricCryptoKey, + derive_shareable_key, generate_random_bytes, EncString, KeyDecryptable, KeyEncryptable, + LocateKey, SymmetricCryptoKey, }, error::{CryptoError, Error, Result}, }; @@ -245,9 +245,19 @@ impl KeyEncryptable for SendView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key - let k = URL_SAFE_NO_PAD - .decode(self.key.ok_or(CryptoError::MissingKey)?) - .map_err(|_| CryptoError::InvalidKey)?; + let k = match (self.key, self.id) { + // Existing send, decrypt key + (Some(k), _) => URL_SAFE_NO_PAD + .decode(k) + .map_err(|_| CryptoError::InvalidKey)?, + // New send, generate random key + (None, None) => { + let key: [u8; 16] = generate_random_bytes(); + key.to_vec() + } + // Existing send without key + _ => return Err(CryptoError::InvalidKey.into()), + }; let send_key = Send::derive_shareable_key(&k)?; Ok(Send { @@ -503,4 +513,44 @@ mod tests { .unwrap(); assert_eq!(v, view); } + + #[test] + pub fn test_encrypt_no_key() { + let enc = build_encryption_settings(); + let key = enc.get_key(&None).unwrap(); + + let view = SendView { + id: None, + access_id: Some("ct2APRQtJk-BLLDwAYqhRA".to_owned()), + name: "Test".to_string(), + notes: None, + key: None, + password: None, + r#type: SendType::Text, + file: None, + text: Some(SendTextView { + text: Some("This is a test".to_owned()), + hidden: false, + }), + max_access_count: None, + access_count: 0, + disabled: false, + hide_email: false, + revision_date: "2024-01-07T23:56:48.207363Z".parse().unwrap(), + deletion_date: "2024-01-14T23:56:48Z".parse().unwrap(), + expiration_date: None, + }; + + // Re-encrypt and decrypt again to ensure encrypt works + let v: SendView = view + .clone() + .encrypt_with_key(key) + .unwrap() + .decrypt_with_key(key) + .unwrap(); + + // Ignore key when comparing + let t = SendView { key: None, ..v }; + assert_eq!(t, view); + } } From 54b6759a2e7d53da38f64e7b025b0057aa305fc2 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 9 Jan 2024 14:47:26 +0100 Subject: [PATCH 182/378] [PM-5346] Implement password strength (#489) Break up `password.rs` into a module for clarity. Implement password strength along test cases that are replicated in the clients codebase. --- .vscode/settings.json | 3 +- Cargo.lock | 131 +++++++++- crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/auth/password.rs | 245 ------------------ crates/bitwarden/src/auth/password/mod.rs | 7 + crates/bitwarden/src/auth/password/policy.rs | 176 +++++++++++++ .../bitwarden/src/auth/password/strength.rs | 78 ++++++ .../bitwarden/src/auth/password/validate.rs | 61 +++++ 8 files changed, 455 insertions(+), 247 deletions(-) delete mode 100644 crates/bitwarden/src/auth/password.rs create mode 100644 crates/bitwarden/src/auth/password/mod.rs create mode 100644 crates/bitwarden/src/auth/password/policy.rs create mode 100644 crates/bitwarden/src/auth/password/strength.rs create mode 100644 crates/bitwarden/src/auth/password/validate.rs diff --git a/.vscode/settings.json b/.vscode/settings.json index d49fe884f..63c3dccaa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,7 @@ "reqwest", "schemars", "uniffi", - "wordlist" + "wordlist", + "zxcvbn" ] } diff --git a/Cargo.lock b/Cargo.lock index 4849ad02c..e04702e37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -315,6 +315,21 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -365,6 +380,7 @@ dependencies = [ "uniffi", "uuid", "wiremock", + "zxcvbn", ] [[package]] @@ -953,6 +969,41 @@ dependencies = [ "syn 2.0.47", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "data-encoding" version = "2.5.0" @@ -998,6 +1049,37 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.10.7" @@ -1124,6 +1206,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -1558,6 +1650,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1665,6 +1763,15 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.0" @@ -2354,6 +2461,12 @@ dependencies = [ "syn 2.0.47", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.31.0" @@ -2805,7 +2918,7 @@ dependencies = [ "bitwarden", "bitwarden-json", "bitwarden-uniffi", - "itertools", + "itertools 0.12.0", "schemars", "serde_json", ] @@ -4189,3 +4302,19 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" + +[[package]] +name = "zxcvbn" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "103fa851fff70ea29af380e87c25c48ff7faac5c530c70bd0e65366d4e0c94e4" +dependencies = [ + "derive_builder", + "fancy-regex", + "itertools 0.10.5", + "js-sys", + "lazy_static", + "quick-error", + "regex", + "time", +] diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 2fd1f32e6..79910bca4 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -61,6 +61,7 @@ subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.2", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } +zxcvbn = ">= 2.2.2, <3.0" [target.'cfg(all(not(target_os = "android"), not(target_arch="wasm32")))'.dependencies] # By default, we use rustls as the TLS stack and rust-platform-verifier to support user-installed root certificates diff --git a/crates/bitwarden/src/auth/password.rs b/crates/bitwarden/src/auth/password.rs deleted file mode 100644 index 94fe0faa0..000000000 --- a/crates/bitwarden/src/auth/password.rs +++ /dev/null @@ -1,245 +0,0 @@ -use schemars::JsonSchema; - -use super::determine_password_hash; -use crate::{ - client::{LoginMethod, UserLoginMethod}, - crypto::HashPurpose, - error::{Error, Result}, - Client, -}; - -pub(super) fn password_strength( - _password: String, - _email: String, - _additional_inputs: Vec, -) -> u8 { - 2 -} - -/// Validate the provided password passes the provided Master Password Requirements Policy. -pub(super) fn satisfies_policy( - password: String, - strength: u8, - policy: &MasterPasswordPolicyOptions, -) -> bool { - if policy.min_complexity > 0 && policy.min_complexity > strength { - return false; - } - - if policy.min_length > 0 && usize::from(policy.min_length) > password.len() { - return false; - } - - if policy.require_upper && password.to_lowercase() == password { - return false; - } - - if policy.require_lower && password.to_uppercase() == password { - return false; - } - - if policy.require_numbers && !password.chars().any(|c| c.is_numeric()) { - return false; - } - - if policy.require_special && !password.chars().any(|c| "!@#$%^&*".contains(c)) { - return false; - } - - true -} - -/// Validate if the provided password matches the password hash stored in the client. -pub(super) async fn validate_password( - client: &Client, - password: String, - password_hash: String, -) -> Result { - let login_method = client - .login_method - .as_ref() - .ok_or(Error::NotAuthenticated)?; - - if let LoginMethod::User(login_method) = login_method { - match login_method { - UserLoginMethod::Username { email, kdf, .. } - | UserLoginMethod::ApiKey { email, kdf, .. } => { - let hash = - determine_password_hash(email, kdf, &password, HashPurpose::LocalAuthorization) - .await?; - - Ok(hash == password_hash) - } - } - } else { - Err(Error::NotAuthenticated) - } -} - -#[derive(Debug, JsonSchema)] -#[cfg_attr(feature = "mobile", derive(uniffi::Record))] -#[allow(dead_code)] -pub struct MasterPasswordPolicyOptions { - min_complexity: u8, - min_length: u8, - require_upper: bool, - require_lower: bool, - require_numbers: bool, - require_special: bool, - - /// Flag to indicate if the policy should be enforced on login. - /// If true, and the user's password does not meet the policy requirements, - /// the user will be forced to update their password. - enforce_on_login: bool, -} - -#[cfg(test)] -mod tests { - mod satisfies_policy { - use crate::auth::password::{satisfies_policy, MasterPasswordPolicyOptions}; - - #[test] - fn satisfies_policy_gives_success() { - let password = "lkasfo!icbb$2323ALKJCO22".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 3, - min_length: 5, - require_upper: true, - require_lower: true, - require_numbers: true, - require_special: true, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 4, &options); - assert!(result); - } - - #[test] - fn satisfies_policy_evaluates_strength() { - let password = "password123".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 3, - min_length: 0, - require_upper: false, - require_lower: false, - require_numbers: false, - require_special: false, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - - #[test] - fn satisfies_policy_evaluates_length() { - let password = "password123".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 0, - min_length: 20, - require_upper: false, - require_lower: false, - require_numbers: false, - require_special: false, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - - #[test] - fn satisfies_policy_evaluates_upper() { - let password = "password123".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 0, - min_length: 0, - require_upper: true, - require_lower: false, - require_numbers: false, - require_special: false, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - - #[test] - fn satisfies_policy_evaluates_lower() { - let password = "ABCDEFG123".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 0, - min_length: 0, - require_upper: false, - require_lower: true, - require_numbers: false, - require_special: false, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - - #[test] - fn satisfies_policy_evaluates_numbers() { - let password = "password".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 0, - min_length: 0, - require_upper: false, - require_lower: false, - require_numbers: true, - require_special: false, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - - #[test] - fn satisfies_policy_evaluates_special() { - let password = "Password123".to_string(); - let options = MasterPasswordPolicyOptions { - min_complexity: 0, - min_length: 0, - require_upper: false, - require_lower: false, - require_numbers: false, - require_special: true, - enforce_on_login: false, - }; - - let result = satisfies_policy(password, 0, &options); - assert!(!result); - } - } - - #[cfg(feature = "mobile")] - #[tokio::test] - async fn test_validate_password() { - use std::num::NonZeroU32; - - use super::validate_password; - use crate::client::{kdf::Kdf, Client, LoginMethod, UserLoginMethod}; - - let mut client = Client::new(None); - client.set_login_method(LoginMethod::User(UserLoginMethod::Username { - email: "test@bitwarden.com".to_string(), - kdf: Kdf::PBKDF2 { - iterations: NonZeroU32::new(100_000).unwrap(), - }, - client_id: "1".to_string(), - })); - - let password = "password123".to_string(); - let password_hash = "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU=".to_string(); - - let result = validate_password(&client, password, password_hash).await; - - assert!(result.unwrap()); - } -} diff --git a/crates/bitwarden/src/auth/password/mod.rs b/crates/bitwarden/src/auth/password/mod.rs new file mode 100644 index 000000000..b7833c7f8 --- /dev/null +++ b/crates/bitwarden/src/auth/password/mod.rs @@ -0,0 +1,7 @@ +mod policy; +pub(crate) use policy::satisfies_policy; +pub use policy::MasterPasswordPolicyOptions; +mod validate; +pub(crate) use validate::validate_password; +mod strength; +pub(crate) use strength::password_strength; diff --git a/crates/bitwarden/src/auth/password/policy.rs b/crates/bitwarden/src/auth/password/policy.rs new file mode 100644 index 000000000..dfd0e770d --- /dev/null +++ b/crates/bitwarden/src/auth/password/policy.rs @@ -0,0 +1,176 @@ +use schemars::JsonSchema; + +/// Validate the provided password passes the provided Master Password Requirements Policy. +pub(crate) fn satisfies_policy( + password: String, + strength: u8, + policy: &MasterPasswordPolicyOptions, +) -> bool { + if policy.min_complexity > 0 && policy.min_complexity > strength { + return false; + } + + if policy.min_length > 0 && usize::from(policy.min_length) > password.len() { + return false; + } + + if policy.require_upper && password.to_lowercase() == password { + return false; + } + + if policy.require_lower && password.to_uppercase() == password { + return false; + } + + if policy.require_numbers && !password.chars().any(|c| c.is_numeric()) { + return false; + } + + if policy.require_special && !password.chars().any(|c| "!@#$%^&*".contains(c)) { + return false; + } + + true +} + +#[derive(Debug, JsonSchema)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +#[allow(dead_code)] +pub struct MasterPasswordPolicyOptions { + min_complexity: u8, + min_length: u8, + require_upper: bool, + require_lower: bool, + require_numbers: bool, + require_special: bool, + + /// Flag to indicate if the policy should be enforced on login. + /// If true, and the user's password does not meet the policy requirements, + /// the user will be forced to update their password. + enforce_on_login: bool, +} + +#[cfg(test)] +mod tests { + + use super::{satisfies_policy, MasterPasswordPolicyOptions}; + + #[test] + fn satisfies_policy_gives_success() { + let password = "lkasfo!icbb$2323ALKJCO22".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 3, + min_length: 5, + require_upper: true, + require_lower: true, + require_numbers: true, + require_special: true, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 4, &options); + assert!(result); + } + + #[test] + fn satisfies_policy_evaluates_strength() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 3, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_length() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 20, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_upper() { + let password = "password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: true, + require_lower: false, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_lower() { + let password = "ABCDEFG123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: true, + require_numbers: false, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_numbers() { + let password = "password".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: true, + require_special: false, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } + + #[test] + fn satisfies_policy_evaluates_special() { + let password = "Password123".to_string(); + let options = MasterPasswordPolicyOptions { + min_complexity: 0, + min_length: 0, + require_upper: false, + require_lower: false, + require_numbers: false, + require_special: true, + enforce_on_login: false, + }; + + let result = satisfies_policy(password, 0, &options); + assert!(!result); + } +} diff --git a/crates/bitwarden/src/auth/password/strength.rs b/crates/bitwarden/src/auth/password/strength.rs new file mode 100644 index 000000000..66b5b5823 --- /dev/null +++ b/crates/bitwarden/src/auth/password/strength.rs @@ -0,0 +1,78 @@ +use zxcvbn::zxcvbn; + +const GLOBAL_INPUTS: [&str; 3] = ["bitwarden", "bit", "warden"]; + +pub(crate) fn password_strength( + password: String, + email: String, + additional_inputs: Vec, +) -> u8 { + let mut inputs = email_to_user_inputs(&email); + inputs.extend(additional_inputs); + + let mut arr: Vec<_> = inputs.iter().map(String::as_str).collect(); + arr.extend(GLOBAL_INPUTS); + + zxcvbn(&password, &arr).map_or(0, |e| e.score()) +} + +fn email_to_user_inputs(email: &str) -> Vec { + let parts = email.split_once('@'); + match parts { + Some((prefix, _)) => prefix + .trim() + .to_lowercase() + .split(|c: char| !c.is_alphanumeric()) + .map(str::to_owned) + .collect(), + None => vec![], + } +} + +#[cfg(test)] +mod tests { + use super::{email_to_user_inputs, password_strength}; + + #[test] + fn test_password_strength() { + let cases = vec![ + ("password", "random@bitwarden.com", 0), + ("password11", "random@bitwarden.com", 1), + ("Weakpass2", "random@bitwarden.com", 2), + ("GoodPass3!", "random@bitwarden.com", 3), + ("VeryStrong123@#", "random@bitwarden.com", 4), + ]; + + for (password, email, expected) in cases { + let result = password_strength(password.to_owned(), email.to_owned(), vec![]); + assert_eq!(expected, result, "{email}: {password}"); + } + } + + #[test] + fn test_penalize_email() { + let password = "asdfjkhkjwer!"; + + let result = password_strength( + password.to_owned(), + "random@bitwarden.com".to_owned(), + vec![], + ); + assert_eq!(result, 4); + + let result = password_strength( + password.to_owned(), + "asdfjkhkjwer@bitwarden.com".to_owned(), + vec![], + ); + assert_eq!(result, 1); + } + + #[test] + fn test_email_to_user_inputs() { + let email = "random@bitwarden.com"; + let result = email_to_user_inputs(email); + + assert_eq!(result, vec!["random"]); + } +} diff --git a/crates/bitwarden/src/auth/password/validate.rs b/crates/bitwarden/src/auth/password/validate.rs new file mode 100644 index 000000000..c86c1c40d --- /dev/null +++ b/crates/bitwarden/src/auth/password/validate.rs @@ -0,0 +1,61 @@ +use crate::{ + auth::determine_password_hash, + client::{LoginMethod, UserLoginMethod}, + crypto::HashPurpose, + error::{Error, Result}, + Client, +}; + +/// Validate if the provided password matches the password hash stored in the client. +pub(crate) async fn validate_password( + client: &Client, + password: String, + password_hash: String, +) -> Result { + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + if let LoginMethod::User(login_method) = login_method { + match login_method { + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. } => { + let hash = + determine_password_hash(email, kdf, &password, HashPurpose::LocalAuthorization) + .await?; + + Ok(hash == password_hash) + } + } + } else { + Err(Error::NotAuthenticated) + } +} + +#[cfg(test)] +mod tests { + #[tokio::test] + async fn test_validate_password() { + use std::num::NonZeroU32; + + use super::validate_password; + use crate::client::{kdf::Kdf, Client, LoginMethod, UserLoginMethod}; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + email: "test@bitwarden.com".to_string(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(100_000).unwrap(), + }, + client_id: "1".to_string(), + })); + + let password = "password123".to_string(); + let password_hash = "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU=".to_string(); + + let result = validate_password(&client, password, password_hash).await; + + assert!(result.unwrap()); + } +} From fe7bce39c6ff7b0abe6f7212f6eb1ad29add0635 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 9 Jan 2024 16:48:10 +0100 Subject: [PATCH 183/378] Swap custom b64 config to standard (#451) Swap custom b64 config to standard --- crates/bitwarden/src/auth/api/request/mod.rs | 5 ++--- crates/bitwarden/src/auth/login/access_token.rs | 5 ++--- crates/bitwarden/src/client/access_token.rs | 4 ++-- crates/bitwarden/src/crypto/aes_ops.rs | 6 ++---- crates/bitwarden/src/crypto/enc_string/asymmetric.rs | 12 +++--------- crates/bitwarden/src/crypto/enc_string/mod.rs | 9 +++------ crates/bitwarden/src/crypto/enc_string/symmetric.rs | 8 ++------ crates/bitwarden/src/crypto/master_key.rs | 6 +++--- crates/bitwarden/src/crypto/rsa.rs | 5 ++--- crates/bitwarden/src/crypto/symmetric_crypto_key.rs | 9 +++------ .../bitwarden/src/platform/generate_fingerprint.rs | 6 +++--- crates/bitwarden/src/util.rs | 9 ++++----- 12 files changed, 31 insertions(+), 53 deletions(-) diff --git a/crates/bitwarden/src/auth/api/request/mod.rs b/crates/bitwarden/src/auth/api/request/mod.rs index 85b36a983..67796f2f3 100644 --- a/crates/bitwarden/src/auth/api/request/mod.rs +++ b/crates/bitwarden/src/auth/api/request/mod.rs @@ -9,7 +9,7 @@ mod renew_token_request; pub(crate) use access_token_request::*; #[cfg(feature = "internal")] pub(crate) use api_token_request::*; -use base64::Engine; +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; #[cfg(feature = "internal")] pub(crate) use password_token_request::*; #[cfg(feature = "internal")] @@ -19,7 +19,6 @@ use crate::{ auth::api::response::{parse_identity_response, IdentityTokenResponse}, client::ApiConfigurations, error::Result, - util::BASE64_ENGINE, }; async fn send_identity_connect_request( @@ -46,7 +45,7 @@ async fn send_identity_connect_request( } if let Some(email) = email { - request = request.header("Auth-Email", BASE64_ENGINE.encode(email.as_bytes())); + request = request.header("Auth-Email", URL_SAFE_NO_PAD.encode(email.as_bytes())); } let response = request diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 2e11035c6..43418d5f1 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,6 +1,6 @@ use std::path::{Path, PathBuf}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use chrono::Utc; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -16,7 +16,6 @@ use crate::{ crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, secrets_manager::state::{self, ClientState}, - util::BASE64_ENGINE, Client, }; @@ -64,7 +63,7 @@ pub(crate) async fn login_access_token( } let payload: Payload = serde_json::from_slice(&decrypted_payload)?; - let encryption_key = BASE64_ENGINE.decode(payload.encryption_key.clone())?; + let encryption_key = STANDARD.decode(payload.encryption_key.clone())?; let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; let access_token_obj: JWTToken = r.access_token.parse()?; diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index c3d6f2fea..854922c14 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -6,7 +6,7 @@ use uuid::Uuid; use crate::{ crypto::{derive_shareable_key, SymmetricCryptoKey}, error::AccessTokenInvalidError, - util::BASE64_ENGINE, + util::STANDARD_INDIFFERENT, }; pub struct AccessToken { @@ -45,7 +45,7 @@ impl FromStr for AccessToken { return Err(AccessTokenInvalidError::InvalidUuid.into()); }; - let encryption_key = BASE64_ENGINE + let encryption_key = STANDARD_INDIFFERENT .decode(encryption_key) .map_err(AccessTokenInvalidError::InvalidBase64)?; let encryption_key: [u8; 16] = encryption_key.try_into().map_err(|e: Vec<_>| { diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden/src/crypto/aes_ops.rs index 182986c3b..00e71a3fd 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden/src/crypto/aes_ops.rs @@ -122,11 +122,9 @@ fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { #[cfg(test)] mod tests { use aes::cipher::generic_array::sequence::GenericSequence; - use base64::Engine; + use base64::{engine::general_purpose::STANDARD, Engine}; use rand::SeedableRng; - use crate::util::BASE64_ENGINE; - use super::*; /// Helper function for generating a `GenericArray` of size 32 with each element being @@ -175,7 +173,7 @@ mod tests { let iv = generate_vec(16, 0, 1); let iv: &[u8; 16] = iv.as_slice().try_into().unwrap(); let key = generate_generic_array(0, 1); - let data = BASE64_ENGINE.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); + let data = STANDARD.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); let decrypted = decrypt_aes256(iv, data, key).unwrap(); diff --git a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs index f90315afa..3c67c166a 100644 --- a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs +++ b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs @@ -1,14 +1,11 @@ use std::{fmt::Display, str::FromStr}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; #[cfg(feature = "internal")] use rsa::{Oaep, RsaPrivateKey}; use serde::Deserialize; -use crate::{ - error::{EncStringParseError, Error, Result}, - util::BASE64_ENGINE, -}; +use crate::error::{EncStringParseError, Error, Result}; #[cfg(feature = "internal")] use crate::error::CryptoError; @@ -135,10 +132,7 @@ impl Display for AsymmEncString { AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac } => vec![data, mac], }; - let encoded_parts: Vec = parts - .iter() - .map(|part| BASE64_ENGINE.encode(part)) - .collect(); + let encoded_parts: Vec = parts.iter().map(|part| STANDARD.encode(part)).collect(); write!(f, "{}.{}", self.enc_type(), encoded_parts.join("|"))?; diff --git a/crates/bitwarden/src/crypto/enc_string/mod.rs b/crates/bitwarden/src/crypto/enc_string/mod.rs index f8608638a..a998e6056 100644 --- a/crates/bitwarden/src/crypto/enc_string/mod.rs +++ b/crates/bitwarden/src/crypto/enc_string/mod.rs @@ -4,13 +4,10 @@ mod symmetric; use std::str::FromStr; pub use asymmetric::AsymmEncString; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; pub use symmetric::EncString; -use crate::{ - error::{EncStringParseError, Result}, - util::BASE64_ENGINE, -}; +use crate::error::{EncStringParseError, Result}; #[cfg(feature = "mobile")] fn check_length(buf: &[u8], expected: usize) -> Result<()> { @@ -25,7 +22,7 @@ fn check_length(buf: &[u8], expected: usize) -> Result<()> { } fn from_b64_vec(s: &str) -> Result> { - Ok(BASE64_ENGINE + Ok(STANDARD .decode(s) .map_err(EncStringParseError::InvalidBase64)?) } diff --git a/crates/bitwarden/src/crypto/enc_string/symmetric.rs b/crates/bitwarden/src/crypto/enc_string/symmetric.rs index eed7c09ad..798994a1c 100644 --- a/crates/bitwarden/src/crypto/enc_string/symmetric.rs +++ b/crates/bitwarden/src/crypto/enc_string/symmetric.rs @@ -1,7 +1,7 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use serde::Deserialize; #[cfg(feature = "mobile")] @@ -10,7 +10,6 @@ use super::{from_b64, from_b64_vec, split_enc_string}; use crate::{ crypto::{decrypt_aes256_hmac, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, - util::BASE64_ENGINE, }; /// # Encrypted string primitive @@ -181,10 +180,7 @@ impl Display for EncString { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => vec![iv, data, mac], }; - let encoded_parts: Vec = parts - .iter() - .map(|part| BASE64_ENGINE.encode(part)) - .collect(); + let encoded_parts: Vec = parts.iter().map(|part| STANDARD.encode(part)).collect(); write!(f, "{}.{}", self.enc_type(), encoded_parts.join("|"))?; diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 9786da3c2..e259ec334 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -1,5 +1,5 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use rand::Rng; use schemars::JsonSchema; use sha2::Digest; @@ -8,7 +8,7 @@ use super::{ hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; -use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; +use crate::{client::kdf::Kdf, error::Result}; #[derive(Copy, Clone, JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -39,7 +39,7 @@ impl MasterKey { ) .expect("hash is a valid fixed size"); - Ok(BASE64_ENGINE.encode(hash)) + Ok(STANDARD.encode(hash)) } pub(crate) fn make_user_key(&self) -> Result<(UserKey, EncString)> { diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden/src/crypto/rsa.rs index 6feb6ef47..9641237fc 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden/src/crypto/rsa.rs @@ -1,4 +1,4 @@ -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use rsa::{ pkcs8::{EncodePrivateKey, EncodePublicKey}, RsaPrivateKey, RsaPublicKey, @@ -7,7 +7,6 @@ use rsa::{ use crate::{ crypto::{EncString, SymmetricCryptoKey}, error::Result, - util::BASE64_ENGINE, }; #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -28,7 +27,7 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_public_key_der() .map_err(|_| "unable to create public key")?; - let b64 = BASE64_ENGINE.encode(spki.as_bytes()); + let b64 = STANDARD.encode(spki.as_bytes()); let pkcs = priv_key .to_pkcs8_der() .map_err(|_| "unable to create private key")?; diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs index 741fe0559..f6eda5e48 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs @@ -1,12 +1,11 @@ use std::str::FromStr; use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use crate::{ crypto::{derive_shareable_key, generate_random_bytes}, error::{CryptoError, Error}, - util::BASE64_ENGINE, }; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) @@ -32,7 +31,7 @@ impl SymmetricCryptoKey { buf.extend_from_slice(&mac); } - BASE64_ENGINE.encode(&buf) + STANDARD.encode(&buf) } #[cfg(feature = "internal")] @@ -50,9 +49,7 @@ impl FromStr for SymmetricCryptoKey { type Err = Error; fn from_str(s: &str) -> Result { - let bytes = BASE64_ENGINE - .decode(s) - .map_err(|_| CryptoError::InvalidKey)?; + let bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; SymmetricCryptoKey::try_from(bytes.as_slice()) } } diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index a8f45dd87..cd763b765 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -1,10 +1,10 @@ -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use log::info; use rsa::pkcs8::EncodePublicKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{crypto::fingerprint, error::Result, util::BASE64_ENGINE}; +use crate::{crypto::fingerprint, error::Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -25,7 +25,7 @@ pub struct FingerprintResponse { pub(crate) fn generate_fingerprint(input: &FingerprintRequest) -> Result { info!("Generating fingerprint"); - let key = BASE64_ENGINE.decode(&input.public_key)?; + let key = STANDARD.decode(&input.public_key)?; Ok(FingerprintResponse { fingerprint: fingerprint(&input.fingerprint_material, &key)?, diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index 4dbe21ca6..038c3d7ee 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -21,12 +21,11 @@ pub fn default_argon2_parallelism() -> NonZeroU32 { NonZeroU32::new(4).unwrap() } -const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() - .with_encode_padding(true) - .with_decode_padding_mode(DecodePaddingMode::Indifferent); +const INDIFFERENT: GeneralPurposeConfig = + GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent); -pub const BASE64_ENGINE: GeneralPurpose = - GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); +pub const STANDARD_INDIFFERENT: GeneralPurpose = + GeneralPurpose::new(&alphabet::STANDARD, INDIFFERENT); #[cfg(feature = "mobile")] pub(crate) fn capitalize_first_letter(s: &str) -> String { From f0c384e5b8fa162cd8aef42dd6b244ef1c84df7e Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Wed, 10 Jan 2024 11:01:06 -0500 Subject: [PATCH 184/378] SM-1066: Add back the Output option to the help menu in bws (#477) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add back Output to the help menu in `bws` which was removed in [this](https://github.com/bitwarden/sdk/pull/103/commits/37428e215e672ec9ea5a993a4c605b4411181525) commit. ## Code changes - **main.rs:** Unhide Output option to the help menu ## Screenshots Screenshot 2024-01-05 at 12 05 22 ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --- crates/bws/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 117186663..e55df5082 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -34,7 +34,7 @@ struct Cli { #[command(subcommand)] command: Option, - #[arg(short = 'o', long, global = true, value_enum, default_value_t = Output::JSON, help="Output format", hide = true)] + #[arg(short = 'o', long, global = true, value_enum, default_value_t = Output::JSON, help="Output format")] output: Output, #[arg(short = 'c', long, global = true, value_enum, default_value_t = Color::Auto, help="Use colors in the output")] From 339f45e0ac3b3bf9ab213208192664e0fdfd8fef Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 10 Jan 2024 17:06:59 +0100 Subject: [PATCH 185/378] Sanitize totp base32 and use no pad (#492) Fix difference in our totp handling in the sdk and clients repository. --- crates/bitwarden/src/vault/totp.rs | 46 ++++++++++++++++-------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 9bc92229b..6e863d57b 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, str::FromStr}; use crate::error::{Error, Result}; use chrono::{DateTime, Utc}; -use data_encoding::BASE32; +use data_encoding::BASE32_NOPAD; use hmac::{Hmac, Mac}; use reqwest::Url; use schemars::JsonSchema; @@ -12,6 +12,7 @@ type HmacSha1 = Hmac; type HmacSha256 = Hmac; type HmacSha512 = Hmac; +const BASE32_CHARS: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; const STEAM_CHARS: &str = "23456789BCDFGHJKMNPQRTVWXY"; const DEFAULT_ALGORITHM: Algorithm = Algorithm::Sha1; @@ -128,9 +129,16 @@ impl FromStr for Totp { /// - Steam URI fn from_str(key: &str) -> Result { fn decode_secret(secret: &str) -> Result> { - BASE32 - .decode(secret.to_uppercase().as_bytes()) - .map_err(|_| "Unable to decode secret".into()) + // Sanitize the secret to only contain allowed characters + let secret = secret + .to_uppercase() + .chars() + .filter(|c| BASE32_CHARS.contains(*c)) + .collect::(); + + BASE32_NOPAD + .decode(secret.as_bytes()) + .map_err(|e| e.to_string().into()) } let params = if key.starts_with("otpauth://") { @@ -218,30 +226,26 @@ mod tests { #[test] fn test_generate_totp() { - let key = "WQIQ25BRKZYCJVYP".to_string(); - let time = Some( - DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") - .unwrap() - .with_timezone(&Utc), - ); - let response = generate_totp(key, time).unwrap(); - - assert_eq!(response.code, "194506".to_string()); - assert_eq!(response.period, 30); - } + let cases = vec![ + ("WQIQ25BRKZYCJVYP", "194506"), // valid base32 + ("wqiq25brkzycjvyp", "194506"), // lowercase + ("PIUDISEQYA", "829846"), // non padded + ("PIUDISEQYA======", "829846"), // padded + ("PIUD1IS!EQYA=", "829846"), // sanitized + ]; - #[test] - fn test_lowercase_secret() { - let key = "wqiq25brkzycjvyp".to_string(); let time = Some( DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") .unwrap() .with_timezone(&Utc), ); - let response = generate_totp(key, time).unwrap(); - assert_eq!(response.code, "194506".to_string()); - assert_eq!(response.period, 30); + for (key, expected_code) in cases { + let response = generate_totp(key.to_string(), time).unwrap(); + + assert_eq!(response.code, expected_code, "wrong code for key: {key}"); + assert_eq!(response.period, 30); + } } #[test] From 99b0b622513c8bef75aa4738c59262cfb0ff6162 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Jan 2024 13:22:13 +0100 Subject: [PATCH 186/378] Refactor make_user_key to call SymmetricCryptoKey::generate (#495) The `MasterKey` previously had intimate knowledge about `SymmetricCryptKey` in order to be able to generate one. This refactor extracts the knowledge back into `SymmetricCryptoKey` by creating a `SymmetricCryptoKey::generate`. --- .../src/crypto/enc_string/symmetric.rs | 6 ++-- crates/bitwarden/src/crypto/master_key.rs | 15 ++++----- crates/bitwarden/src/crypto/mod.rs | 2 ++ .../src/crypto/symmetric_crypto_key.rs | 33 ++++++++++++++----- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/crates/bitwarden/src/crypto/enc_string/symmetric.rs b/crates/bitwarden/src/crypto/enc_string/symmetric.rs index 798994a1c..3fe0e8ef8 100644 --- a/crates/bitwarden/src/crypto/enc_string/symmetric.rs +++ b/crates/bitwarden/src/crypto/enc_string/symmetric.rs @@ -274,11 +274,13 @@ impl schemars::JsonSchema for EncString { #[cfg(test)] mod tests { use super::EncString; - use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use crate::crypto::{ + symmetric_crypto_key::derive_symmetric_key, KeyDecryptable, KeyEncryptable, + }; #[test] fn test_enc_string_roundtrip() { - let key = SymmetricCryptoKey::generate("test"); + let key = derive_symmetric_key("test"); let test_string = "encrypted_test_string".to_string(); let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index e259ec334..726759ac7 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -1,6 +1,5 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; -use rand::Rng; use schemars::JsonSchema; use sha2::Digest; @@ -69,10 +68,7 @@ fn make_user_key( mut rng: impl rand::RngCore, master_key: &MasterKey, ) -> Result<(UserKey, EncString)> { - let mut user_key = [0u8; 64]; - rng.fill(&mut user_key); - - let user_key = SymmetricCryptoKey::try_from(user_key.as_slice())?; + let user_key = SymmetricCryptoKey::generate(&mut rng); let protected = master_key.encrypt_user_key(&user_key)?; Ok((UserKey::new(user_key), protected)) } @@ -134,7 +130,10 @@ mod tests { use rand::SeedableRng; use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; - use crate::{client::kdf::Kdf, crypto::SymmetricCryptoKey}; + use crate::{ + client::kdf::Kdf, + crypto::{symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}, + }; #[test] fn test_master_key_derive_pbkdf2() { @@ -292,9 +291,9 @@ mod tests { #[test] fn test_make_user_key2() { - let master_key = MasterKey(SymmetricCryptoKey::generate("test1")); + let master_key = MasterKey(derive_symmetric_key("test1")); - let user_key = SymmetricCryptoKey::generate("test2"); + let user_key = derive_symmetric_key("test2"); let encrypted = master_key.encrypt_user_key(&user_key).unwrap(); let decrypted = master_key.decrypt_user_key(encrypted).unwrap(); diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index 94db974d3..5de0cdd06 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -23,6 +23,7 @@ use aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; use hmac::digest::OutputSizeUser; +#[cfg(any(test, feature = "internal"))] use rand::{ distributions::{Distribution, Standard}, Rng, @@ -79,6 +80,7 @@ fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result() -> T where Standard: Distribution, diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs index f6eda5e48..5487dfd98 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs @@ -2,11 +2,9 @@ use std::str::FromStr; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; +use rand::Rng; -use crate::{ - crypto::{derive_shareable_key, generate_random_bytes}, - error::{CryptoError, Error}, -}; +use crate::error::{CryptoError, Error}; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) pub struct SymmetricCryptoKey { @@ -18,9 +16,18 @@ impl SymmetricCryptoKey { const KEY_LEN: usize = 32; const MAC_LEN: usize = 32; - pub fn generate(name: &str) -> Self { - let secret: [u8; 16] = generate_random_bytes(); - derive_shareable_key(secret, name, None) + /// Generate a new random [SymmetricCryptoKey] + pub fn generate(mut rng: impl rand::RngCore) -> Self { + let mut key = [0u8; Self::KEY_LEN]; + let mut mac_key = [0u8; Self::MAC_LEN]; + + rng.fill(&mut key); + rng.fill(&mut mac_key); + + SymmetricCryptoKey { + key: key.into(), + mac_key: Some(mac_key.into()), + } } pub fn to_base64(&self) -> String { @@ -81,15 +88,23 @@ impl std::fmt::Debug for SymmetricCryptoKey { } } +#[cfg(test)] +pub fn derive_symmetric_key(name: &str) -> SymmetricCryptoKey { + use crate::crypto::{derive_shareable_key, generate_random_bytes}; + + let secret: [u8; 16] = generate_random_bytes(); + derive_shareable_key(secret, name, None) +} + #[cfg(test)] mod tests { use std::str::FromStr; - use super::SymmetricCryptoKey; + use super::{derive_symmetric_key, SymmetricCryptoKey}; #[test] fn test_symmetric_crypto_key() { - let key = SymmetricCryptoKey::generate("test"); + let key = derive_symmetric_key("test"); let key2 = SymmetricCryptoKey::from_str(&key.to_base64()).unwrap(); assert_eq!(key.key, key2.key); assert_eq!(key.mac_key, key2.mac_key); From b385d2db062a83fb7938edbb965abdd33d513d10 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Jan 2024 15:05:59 +0100 Subject: [PATCH 187/378] Fix send password handling (#493) We should hash send passwords appropriately using pbkdf. Also changed how SendView handles passwords. It no longer provides the password but rather a boolean field `has_password` to prevent accidentally overriding the password when doing `send.decrypt().encrypt()`. --- crates/bitwarden/src/crypto/master_key.rs | 18 +--- crates/bitwarden/src/crypto/mod.rs | 5 + crates/bitwarden/src/vault/send.rs | 109 ++++++++++++++-------- 3 files changed, 78 insertions(+), 54 deletions(-) diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 726759ac7..b22e11c6b 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -3,10 +3,7 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use schemars::JsonSchema; use sha2::Digest; -use super::{ - hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, - PBKDF_SHA256_HMAC_OUT_SIZE, -}; +use super::{hkdf_expand, EncString, KeyDecryptable, SymmetricCryptoKey, UserKey}; use crate::{client::kdf::Kdf, error::Result}; #[derive(Copy, Clone, JsonSchema)] @@ -31,12 +28,7 @@ impl MasterKey { password: &[u8], purpose: HashPurpose, ) -> Result { - let hash = pbkdf2::pbkdf2_array::( - &self.0.key, - password, - purpose as u32, - ) - .expect("hash is a valid fixed size"); + let hash = super::pbkdf2(&self.0.key, password, purpose as u32); Ok(STANDARD.encode(hash)) } @@ -76,11 +68,7 @@ fn make_user_key( /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { let hash = match kdf { - Kdf::PBKDF2 { iterations } => pbkdf2::pbkdf2_array::< - PbkdfSha256Hmac, - PBKDF_SHA256_HMAC_OUT_SIZE, - >(secret, salt, iterations.get()) - .unwrap(), + Kdf::PBKDF2 { iterations } => super::pbkdf2(secret, salt, iterations.get()), Kdf::Argon2id { iterations, diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index 5de0cdd06..5355a337a 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -87,3 +87,8 @@ where { rand::thread_rng().gen() } + +pub fn pbkdf2(password: &[u8], salt: &[u8], rounds: u32) -> [u8; PBKDF_SHA256_HMAC_OUT_SIZE] { + pbkdf2::pbkdf2_array::(password, salt, rounds) + .expect("hash is a valid fixed size") +} diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index ce100db3e..d8a18a8f6 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,4 +1,7 @@ -use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; +use base64::{ + engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD}, + Engine, +}; use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -14,6 +17,8 @@ use crate::{ error::{CryptoError, Error, Result}, }; +const SEND_ITERATIONS: u32 = 100_000; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -97,7 +102,13 @@ pub struct SendView { pub notes: Option, /// Base64 encoded key pub key: Option, - pub password: Option, + /// Replace or add a password to an existing send. The SDK will always return None when + /// decrypting a [Send] + /// TODO: We should revisit this, one variant is to have `[Create, Update]SendView` DTOs. + pub new_password: Option, + /// Denote if an existing send has a password. The SDK will ignore this value when creating or + /// updating sends. + pub has_password: bool, pub r#type: SendType, pub file: Option, @@ -200,7 +211,8 @@ impl KeyDecryptable for Send { name: self.name.decrypt_with_key(&key)?, notes: self.notes.decrypt_with_key(&key)?, key: Some(URL_SAFE_NO_PAD.encode(k)), - password: self.password.clone(), + new_password: None, + has_password: self.password.is_some(), r#type: self.r#type, file: self.file.decrypt_with_key(&key)?, @@ -267,7 +279,10 @@ impl KeyEncryptable for SendView { name: self.name.encrypt_with_key(&send_key)?, notes: self.notes.encrypt_with_key(&send_key)?, key: k.encrypt_with_key(key)?, - password: self.password.clone(), + password: self.new_password.map(|password| { + let password = crate::crypto::pbkdf2(password.as_bytes(), &k, SEND_ITERATIONS); + STANDARD.encode(password) + }), r#type: self.r#type, file: self.file.encrypt_with_key(&send_key)?, @@ -370,39 +385,12 @@ mod tests { let k = enc.get_key(&None).unwrap(); - // Create a send object, the only value we really care about here is the key - let send = Send { - id: Some("d7fb1e7f-9053-43c0-a02c-b0690098685a".parse().unwrap()), - access_id: Some("fx7711OQwEOgLLBpAJhoWg".into()), - name: "2.u5vXPAepUZ+4lI2vGGKiGg==|hEouC4SvCCb/ifzZzLcfSw==|E2VZUVffehczfIuRSlX2vnPRfflBtXef5tzsWvRrtfM=" - .parse() - .unwrap(), - notes: None, - key: "2.+1KUfOX8A83Xkwk1bumo/w==|Nczvv+DTkeP466cP/wMDnGK6W9zEIg5iHLhcuQG6s+M=|SZGsfuIAIaGZ7/kzygaVUau3LeOvJUlolENBOU+LX7g=" - .parse() - .unwrap(), - password: None, - r#type: super::SendType::File, - file: Some(super::SendFile { - id: Some("7f129hzwu0umkmnmsghkt486w96p749c".into()), - file_name: "2.pnszM3slsCVlOIzuWrfCpA==|85zCg+X8GODvIAPf1Yt3K75YP+ub3wVAi1UvwOVXhPgUo9Gsu23FJgYSOkyKu3Vr|OvTrOugwRH7Mp2BWSuPlfxovoWt9oDRdi1Qo3xHUcdQ=" - .parse() - .unwrap(), - size: Some("1251825".into()), - size_name: Some("1.19 MB".into()), - }), - text: None, - max_access_count: None, - access_count: 0, - disabled: false, - hide_email: false, - revision_date: "2023-08-25T09:14:53Z".parse().unwrap(), - deletion_date: "2023-09-25T09:14:53Z".parse().unwrap(), - expiration_date: None, - }; + let send_key = "2.+1KUfOX8A83Xkwk1bumo/w==|Nczvv+DTkeP466cP/wMDnGK6W9zEIg5iHLhcuQG6s+M=|SZGsfuIAIaGZ7/kzygaVUau3LeOvJUlolENBOU+LX7g=" + .parse() + .unwrap(); // Get the send key - let send_key = Send::get_key(&send.key, k).unwrap(); + let send_key = Send::get_key(&send_key, k).unwrap(); let send_key_b64 = send_key.to_base64(); assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } @@ -458,7 +446,8 @@ mod tests { name: "Test".to_string(), notes: None, key: Some("Pgui0FK85cNhBGWHAlBHBw".to_owned()), - password: None, + new_password: None, + has_password: false, r#type: SendType::Text, file: None, text: Some(SendTextView { @@ -488,7 +477,8 @@ mod tests { name: "Test".to_string(), notes: None, key: Some("Pgui0FK85cNhBGWHAlBHBw".to_owned()), - password: None, + new_password: None, + has_password: false, r#type: SendType::Text, file: None, text: Some(SendTextView { @@ -515,7 +505,7 @@ mod tests { } #[test] - pub fn test_encrypt_no_key() { + pub fn test_create() { let enc = build_encryption_settings(); let key = enc.get_key(&None).unwrap(); @@ -525,7 +515,8 @@ mod tests { name: "Test".to_string(), notes: None, key: None, - password: None, + new_password: None, + has_password: false, r#type: SendType::Text, file: None, text: Some(SendTextView { @@ -553,4 +544,44 @@ mod tests { let t = SendView { key: None, ..v }; assert_eq!(t, view); } + + #[test] + pub fn test_create_password() { + let enc = build_encryption_settings(); + let key = enc.get_key(&None).unwrap(); + + let view = SendView { + id: None, + access_id: Some("ct2APRQtJk-BLLDwAYqhRA".to_owned()), + name: "Test".to_owned(), + notes: None, + key: Some("Pgui0FK85cNhBGWHAlBHBw".to_owned()), + new_password: Some("abc123".to_owned()), + has_password: false, + r#type: SendType::Text, + file: None, + text: Some(SendTextView { + text: Some("This is a test".to_owned()), + hidden: false, + }), + max_access_count: None, + access_count: 0, + disabled: false, + hide_email: false, + revision_date: "2024-01-07T23:56:48.207363Z".parse().unwrap(), + deletion_date: "2024-01-14T23:56:48Z".parse().unwrap(), + expiration_date: None, + }; + + let send: Send = view.encrypt_with_key(key).unwrap(); + + assert_eq!( + send.password, + Some("vTIDfdj3FTDbejmMf+mJWpYdMXsxfeSd1Sma3sjCtiQ=".to_owned()) + ); + + let v: SendView = send.decrypt_with_key(key).unwrap(); + assert_eq!(v.new_password, None); + assert!(v.has_password); + } } From bbc47bb8992b64b6622a56eac2a3649eef0aedfb Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 11 Jan 2024 08:10:13 -0800 Subject: [PATCH 188/378] [BEEEP] - Docker image for `bws` (#305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change Add a `bws` Dockerfile. - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ## Objective This allows us to publish a `bitwarden/bws` docker image. Multi-arch images can be built with the following command: `docker buildx build -f ./crates/bws/Dockerfile --push -t bitwarden/bws --platform linux/amd64,linux/arm64 .` ## Code changes - **`Dockerfile`:** add file ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --------- Co-authored-by: Michał Chęciński Co-authored-by: Michał Chęciński Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> --- .github/workflows/build-cli-docker.yml | 163 +++++++++++++++++++++++++ crates/bws/Dockerfile | 34 ++++++ crates/bws/Dockerfile.dockerignore | 4 + 3 files changed, 201 insertions(+) create mode 100644 .github/workflows/build-cli-docker.yml create mode 100644 crates/bws/Dockerfile create mode 100644 crates/bws/Dockerfile.dockerignore diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml new file mode 100644 index 000000000..5cb6bb678 --- /dev/null +++ b/.github/workflows/build-cli-docker.yml @@ -0,0 +1,163 @@ +--- +name: Build bws Docker image + +on: + push: + paths: + - "crates/bws/**" + workflow_dispatch: + inputs: + sdk_branch: + description: "Server branch name to deploy (examples: 'master', 'rc', 'feature/sm')" + type: string + default: master + pull_request: + paths: + - ".github/workflows/build-cli-docker.yml" + - "crates/bws/**" + +env: + _AZ_REGISTRY: bitwardenprod.azurecr.io + +jobs: + build-docker: + name: Build Docker image + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + + - name: Check Branch to Publish + env: + PUBLISH_BRANCHES: "master,rc,hotfix-rc" + id: publish-branch-check + run: | + REF=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} + + IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES + + if [[ "${publish_branches[*]}" =~ "${REF}" ]]; then + echo "is_publish_branch=true" >> $GITHUB_ENV + else + echo "is_publish_branch=false" >> $GITHUB_ENV + fi + + ########## Set up Docker ########## + - name: Set up QEMU emulators + uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 + + ########## Login to Docker registries ########## + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} + + - name: Login to Azure - CI Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve github PAT secrets + id: retrieve-secret-pat + uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + with: + keyvault: "bitwarden-ci" + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Setup Docker Trust + if: ${{ env.is_publish_branch == 'true' }} + uses: bitwarden/gh-actions/setup-docker-trust@082f5e05ed97c3601c6f3179250b1a761c4d647f + with: + azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + azure-keyvault-name: "bitwarden-ci" + + ########## Generate image tag and build Docker image ########## + - name: Generate Docker image tag + id: tag + run: | + REF=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} + IMAGE_TAG=$(echo "${REF}" | sed "s#/#-#g") # slash safe branch name + if [[ "${IMAGE_TAG}" == "master" ]]; then + IMAGE_TAG=dev + elif [[ ("${IMAGE_TAG}" == "rc") || ("${IMAGE_TAG}" == "hotfix-rc") ]]; then + IMAGE_TAG=rc + fi + + echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT + + - name: Generate tag list + id: tag-list + env: + IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} + IS_PUBLISH_BRANCH: ${{ env.is_publish_branch }} + run: | + if [[ ("${IMAGE_TAG}" == "dev" || "${IMAGE_TAG}" == "rc") && "${IS_PUBLISH_BRANCH}" == "true" ]]; then + echo "tags=$_AZ_REGISTRY/bws:${IMAGE_TAG},bitwarden/bws:${IMAGE_TAG}" >> $GITHUB_OUTPUT + else + echo "tags=$_AZ_REGISTRY/bws:${IMAGE_TAG}" >> $GITHUB_OUTPUT + fi + + - name: Build and push Docker image + uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v3.2.0 + with: + context: . + file: crates/bws/Dockerfile + platforms: | + linux/amd64, + linux/arm64/v8 + push: true + tags: ${{ steps.tag-list.outputs.tags }} + secrets: | + "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" + + - name: Log out of Docker and disable Docker Notary + if: ${{ env.is_publish_branch == 'true' }} + run: | + docker logout + echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-22.04 + needs: build-docker + steps: + - name: Check if any job failed + if: | + github.ref == 'refs/heads/master' + || github.ref == 'refs/heads/rc' + || github.ref == 'refs/heads/hotfix-rc' + env: + BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} + run: | + if [ "$BUILD_DOCKER_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - CI subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + if: failure() + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + if: failure() + with: + keyvault: "bitwarden-ci" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/crates/bws/Dockerfile b/crates/bws/Dockerfile new file mode 100644 index 000000000..d75494648 --- /dev/null +++ b/crates/bws/Dockerfile @@ -0,0 +1,34 @@ +############################################### +# Build stage # +############################################### +FROM --platform=$BUILDPLATFORM rust:1.73 AS build + +# Docker buildx supplies the value for this arg +ARG TARGETPLATFORM + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Copy required project files +COPY . /app + +# Build project +WORKDIR /app/crates/bws +RUN cargo build --release + +############################################### +# App stage # +############################################### +FROM debian:bookworm-slim + +ARG TARGETPLATFORM +LABEL com.bitwarden.product="bitwarden" + +# Copy built project from the build stage +WORKDIR /usr/local/bin +COPY --from=build /app/target/release/bws . +COPY --from=build /etc/ssl/certs /etc/ssl/certs + +ENTRYPOINT ["bws"] + diff --git a/crates/bws/Dockerfile.dockerignore b/crates/bws/Dockerfile.dockerignore new file mode 100644 index 000000000..50f4b1230 --- /dev/null +++ b/crates/bws/Dockerfile.dockerignore @@ -0,0 +1,4 @@ +* +!crates/* +!Cargo.toml +!Cargo.lock From 4c91270873d3d4591828abbd0506a10af93badcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 12 Jan 2024 10:52:43 +0100 Subject: [PATCH 189/378] Implement KeyEncryptable support for Asymmetric keys (#447) --- .../src/client/encryption_settings.rs | 22 ++-- .../src/crypto/asymmetric_crypto_key.rs | 107 +++++++++++++++++ .../src/crypto/enc_string/asymmetric.rs | 110 ++++++++++++------ .../src/crypto/enc_string/symmetric.rs | 8 +- crates/bitwarden/src/crypto/encryptable.rs | 4 +- .../bitwarden/src/crypto/key_encryptable.rs | 58 +++++---- crates/bitwarden/src/crypto/mod.rs | 7 +- .../src/crypto/symmetric_crypto_key.rs | 13 ++- .../src/platform/generate_fingerprint.rs | 9 +- .../bitwarden/src/vault/cipher/attachment.rs | 4 +- crates/bitwarden/src/vault/cipher/card.rs | 4 +- crates/bitwarden/src/vault/cipher/cipher.rs | 6 +- crates/bitwarden/src/vault/cipher/field.rs | 4 +- crates/bitwarden/src/vault/cipher/identity.rs | 4 +- .../bitwarden/src/vault/cipher/local_data.rs | 4 +- crates/bitwarden/src/vault/cipher/login.rs | 8 +- .../bitwarden/src/vault/cipher/secure_note.rs | 4 +- crates/bitwarden/src/vault/collection.rs | 2 +- crates/bitwarden/src/vault/folder.rs | 4 +- .../bitwarden/src/vault/password_history.rs | 4 +- crates/bitwarden/src/vault/send.rs | 14 +-- 21 files changed, 276 insertions(+), 124 deletions(-) create mode 100644 crates/bitwarden/src/crypto/asymmetric_crypto_key.rs diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index ebfbba2b4..1a662adfb 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,22 +1,18 @@ use std::collections::HashMap; -use rsa::RsaPrivateKey; -use uuid::Uuid; #[cfg(feature = "internal")] -use { - crate::{ - client::UserLoginMethod, - crypto::{AsymmEncString, EncString, KeyDecryptable}, - error::{CryptoError, Result}, - }, - rsa::pkcs8::DecodePrivateKey, +use crate::{ + client::UserLoginMethod, + crypto::{AsymmEncString, EncString, KeyDecryptable}, + error::Result, }; +use uuid::Uuid; -use crate::crypto::SymmetricCryptoKey; +use crate::crypto::{AsymmetricCryptoKey, SymmetricCryptoKey}; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, - pub(crate) private_key: Option, + pub(crate) private_key: Option, org_keys: HashMap, } @@ -61,7 +57,7 @@ impl EncryptionSettings { ) -> Result { let private_key = { let dec: Vec = private_key.decrypt_with_key(&user_key)?; - Some(rsa::RsaPrivateKey::from_pkcs8_der(&dec).map_err(|_| CryptoError::InvalidKey)?) + Some(AsymmetricCryptoKey::from_der(&dec)?) }; Ok(EncryptionSettings { @@ -96,7 +92,7 @@ impl EncryptionSettings { // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { - let dec = org_enc_key.decrypt(private_key)?; + let dec: Vec = org_enc_key.decrypt_with_key(private_key)?; let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?; diff --git a/crates/bitwarden/src/crypto/asymmetric_crypto_key.rs b/crates/bitwarden/src/crypto/asymmetric_crypto_key.rs new file mode 100644 index 000000000..93098faa4 --- /dev/null +++ b/crates/bitwarden/src/crypto/asymmetric_crypto_key.rs @@ -0,0 +1,107 @@ +use rsa::RsaPrivateKey; + +use crate::{ + crypto::CryptoKey, + error::{CryptoError, Result}, +}; + +/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) +pub struct AsymmetricCryptoKey { + pub(in crate::crypto) key: RsaPrivateKey, +} + +impl AsymmetricCryptoKey { + pub fn from_pem(pem: &str) -> Result { + use rsa::pkcs8::DecodePrivateKey; + Ok(Self { + key: rsa::RsaPrivateKey::from_pkcs8_pem(pem).map_err(|_| CryptoError::InvalidKey)?, + }) + } + + pub fn from_der(der: &[u8]) -> Result { + use rsa::pkcs8::DecodePrivateKey; + Ok(Self { + key: rsa::RsaPrivateKey::from_pkcs8_der(der).map_err(|_| CryptoError::InvalidKey)?, + }) + } + + pub fn to_der(&self) -> Result> { + use rsa::pkcs8::EncodePrivateKey; + Ok(self + .key + .to_pkcs8_der() + .map_err(|_| CryptoError::InvalidKey)? + .as_bytes() + .to_owned()) + } + + pub fn to_public_der(&self) -> Result> { + use rsa::pkcs8::EncodePublicKey; + Ok(self + .key + .to_public_key() + .to_public_key_der() + .map_err(|_| CryptoError::InvalidKey)? + .as_bytes() + .to_owned()) + } +} + +impl CryptoKey for AsymmetricCryptoKey {} + +// We manually implement these to make sure we don't print any sensitive data +impl std::fmt::Debug for AsymmetricCryptoKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("AsymmetricCryptoKey").finish() + } +} + +#[cfg(test)] +mod tests { + use base64::{engine::general_purpose::STANDARD, Engine}; + + use super::AsymmetricCryptoKey; + + #[test] + fn test_asymmetric_crypto_key() { + let pem_key_str = "-----BEGIN PRIVATE KEY----- +MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5 +qv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYc +afeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4Cwm +qqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyv +b0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZw +P7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2fam +rEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKi +szJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx +0d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+ +8vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVR +jB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKach +vGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI +1u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KR +J30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7 +l+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQ +TjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9 +ClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9Bye +KvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiN +wEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZ +UZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEA +kY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7W +pt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwN +Zy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLi +CVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzup +PFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnf +DnqOsltgPomWZ7xVfMkm9niL2OA= +-----END PRIVATE KEY-----"; + + let der_key_vec = STANDARD.decode("MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDiTQVuzhdygFz5qv14i+XFDGTnDravzUQT1hPKPGUZOUSZ1gwdNgkWqOIaOnR65BHEnL0sp4bnuiYcafeK2JAW5Sc8Z7IxBNSuAwhQmuKx3RochMIiuCkI2/p+JvUQoJu6FBNm8OoJ4CwmqqHGZESMfnpQDCuDrB3JdJEdXhtmnl0C48sGjOk3WaBMcgGqn8LbJDUlyu1zdqyvb0waJf0iV4PJm2fkUl7+57D/2TkpbCqURVnZK1FFIEg8mr6FzSN1F2pOfktkNYZwP7MSNR7o81CkRSCMr7EkIVa+MZYMBx106BMK7FXgWB7nbSpsWKxBk7ZDHkID2famrEcVtrzDAgMBAAECggEBAKwq9OssGGKgjhvUnyrLJHAZ0dqIMyzk+dotkLjX4gKiszJmyqiep6N5sStLNbsZMPtoU/RZMCW0VbJgXFhiEp2YkZU/Py5UAoqw++53J+kx0d/IkPphKbb3xUec0+1mg5O6GljDCQuiZXS1dIa/WfeZcezclW6Dz9WovY6ePjJ+8vEBR1icbNKzyeINd6MtPtpcgQPHtDwHvhPyUDbKDYGbLvjh9nui8h4+ZUlXKuVRjB0ChxiKV1xJRjkrEVoulOOicd5r597WfB2ghax3pvRZ4MdXemCXm3gQYqPVKachvGU+1cPQR/MBJZpxT+EZA97xwtFS3gqwbxJaNFcoE8ECgYEA9OaeYZhQPDo485tI1u/Z7L/3PNape9hBQIXoW7+MgcQ5NiWqYh8Jnj43EIYa0wM/ECQINr1Za8Q5e6KRJ30FcU+kfyjuQ0jeXdNELGU/fx5XXNg/vV8GevHwxRlwzqZTCg6UExUZzbYEQqd7l+wPyETGeua5xCEywA1nX/D101kCgYEA7I6aMFjhEjO71RmzNhqjKJt6DOghoOfQTjhaaanNEhLYSbenFz1mlb21mW67ulmz162saKdIYLxQNJIP8ZPmxh4ummOJI8w9ClHfo8WuCI2hCjJ19xbQJocSbTA5aJg6lA1IDVZMDbQwsnAByPRGpaLHBT/Q9ByeKvCMB+9amXsCgYEAx65yXSkP4sumPBrVHUub6MntERIGRxBgw/drKcPZEMWp0FiNwEuGUBxyUWrG3F69QK/gcqGZE6F/LSu0JvptQaKqgXQiMYJsrRvhbkFvsHpQyUcZUZL1ebFjm5HOxPAgrQaN/bEqxOwwNRjSUWEMzUImg3c06JIZCzbinvudtKECgYEAkY3JF/iIPI/yglP27lKDlCfeeHSYxI3+oTKRhzSAxx8rUGidenJAXeDGDauR/T7Wpt3pGNfddBBK9Z3uC4Iq3DqUCFE4f/taj7ADAJ1Q0Vh7/28/IJM77ojr8J1cpZwNZy2o6PPxhfkagaDjqEeN9Lrs5LD4nEvDkr5CG1vOjmMCgYEAvIBFKRm31NyF8jLiCVuPwC5PzrW5iThDmsWTaXFpB3esUsbICO2pEz872oeQS+Em4GO5vXUlpbbFPzupPFhA8iMJ8TAvemhvc7oM0OZqpU6p3K4seHf6BkwLxumoA3vDJfovu9RuXVcJVOnfDnqOsltgPomWZ7xVfMkm9niL2OA=").unwrap(); + + // Load the two different formats and check they are the same key + let pem_key = AsymmetricCryptoKey::from_pem(pem_key_str).unwrap(); + let der_key = AsymmetricCryptoKey::from_der(&der_key_vec).unwrap(); + assert_eq!(pem_key.key, der_key.key); + + // Check that the keys can be converted back to DER + assert_eq!(der_key.to_der().unwrap(), der_key_vec); + assert_eq!(pem_key.to_der().unwrap(), der_key_vec); + } +} diff --git a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs index 3c67c166a..a2bbee8cb 100644 --- a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs +++ b/crates/bitwarden/src/crypto/enc_string/asymmetric.rs @@ -1,14 +1,13 @@ use std::{fmt::Display, str::FromStr}; use base64::{engine::general_purpose::STANDARD, Engine}; -#[cfg(feature = "internal")] -use rsa::{Oaep, RsaPrivateKey}; +use rsa::Oaep; use serde::Deserialize; -use crate::error::{EncStringParseError, Error, Result}; - -#[cfg(feature = "internal")] -use crate::error::CryptoError; +use crate::{ + crypto::{AsymmetricCryptoKey, KeyDecryptable}, + error::{CryptoError, EncStringParseError, Error, Result}, +}; use super::{from_b64_vec, split_enc_string}; @@ -16,7 +15,7 @@ use super::{from_b64_vec, split_enc_string}; /// /// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are /// are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt -/// data using AsymmetricCryptoKeys. +/// data using [AsymmetricCryptoKey]s. /// /// The flexibility of the [AsymmEncString] type allows for different encryption algorithms to be used /// which is represented by the different variants of the enum. @@ -100,27 +99,6 @@ impl FromStr for AsymmEncString { } } -#[allow(unused)] -impl AsymmEncString { - /// TODO: Convert this to a trait method - #[cfg(feature = "internal")] - pub(crate) fn decrypt(&self, key: &RsaPrivateKey) -> Result> { - Ok(match self { - Self::Rsa2048_OaepSha256_B64 { data } => key.decrypt(Oaep::new::(), data), - Self::Rsa2048_OaepSha1_B64 { data } => key.decrypt(Oaep::new::(), data), - #[allow(deprecated)] - Self::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac: _ } => { - key.decrypt(Oaep::new::(), data) - } - #[allow(deprecated)] - Self::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac: _ } => { - key.decrypt(Oaep::new::(), data) - } - } - .map_err(|_| CryptoError::KeyDecrypt)?) - } -} - impl Display for AsymmEncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let parts: Vec<&[u8]> = match self { @@ -172,6 +150,32 @@ impl AsymmEncString { } } +impl KeyDecryptable> for AsymmEncString { + fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result> { + use AsymmEncString::*; + Ok(match self { + Rsa2048_OaepSha256_B64 { data } => key.key.decrypt(Oaep::new::(), data), + Rsa2048_OaepSha1_B64 { data } => key.key.decrypt(Oaep::new::(), data), + #[allow(deprecated)] + Rsa2048_OaepSha256_HmacSha256_B64 { data, .. } => { + key.key.decrypt(Oaep::new::(), data) + } + #[allow(deprecated)] + Rsa2048_OaepSha1_HmacSha256_B64 { data, .. } => { + key.key.decrypt(Oaep::new::(), data) + } + } + .map_err(|_| CryptoError::KeyDecrypt)?) + } +} + +impl KeyDecryptable for AsymmEncString { + fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result { + let dec: Vec = self.decrypt_with_key(key)?; + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) + } +} + /// Usually we wouldn't want to expose AsymmEncStrings in the API or the schemas. /// But during the transition phase we will expose endpoints using the AsymmEncString type. impl schemars::JsonSchema for AsymmEncString { @@ -188,12 +192,7 @@ impl schemars::JsonSchema for AsymmEncString { mod tests { use super::AsymmEncString; - #[cfg(feature = "internal")] - #[test] - fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { - use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; - - let rsa_private_key: &str = "-----BEGIN PRIVATE KEY----- + const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS 8HzYUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2 e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86LnhD56A9FDUfuI0dVnPcrwNv0YJIo9 @@ -221,15 +220,50 @@ Is3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8+tPVgppLcG0+tMdLjigFQiDUQk2y3 WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz XKZBokBGnjFnTnKcs7nv/O8= -----END PRIVATE KEY-----"; - let private_key = RsaPrivateKey::from_pkcs8_pem(rsa_private_key).unwrap(); + + #[cfg(feature = "internal")] + #[test] + fn test_enc_string_rsa2048_oaep_sha256_b64() { + use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; + + let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); + let enc_str: &str = "3.YFqzW9LL/uLjCnl0RRLtndzGJ1FV27mcwQwGjfJPOVrgCX9nJSUYCCDd0iTIyOZ/zRxG47b6L1Z3qgkEfcxjmrSBq60gijc3E2TBMAg7OCLVcjORZ+i1sOVOudmOPWro6uA8refMrg4lqbieDlbLMzjVEwxfi5WpcL876cD0vYyRwvLO3bzFrsE7x33HHHtZeOPW79RqMn5efsB5Dj9wVheC9Ix9AYDjbo+rjg9qR6guwKmS7k2MSaIQlrDR7yu8LP+ePtiSjx+gszJV5jQGfcx60dtiLQzLS/mUD+RmU7B950Bpx0H7x56lT5yXZbWK5YkoP6qd8B8D2aKbP68Ywg=="; + let enc_string: AsymmEncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 3); + + let res: String = enc_string.decrypt_with_key(&private_key).unwrap(); + assert_eq!(res, "EncryptMe!"); + } + + #[cfg(feature = "internal")] + #[test] + fn test_enc_string_rsa2048_oaep_sha1_b64() { + use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; + + let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); + let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw=="; + let enc_string: AsymmEncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 4); + + let res: String = enc_string.decrypt_with_key(&private_key).unwrap(); + assert_eq!(res, "EncryptMe!"); + } + + #[cfg(feature = "internal")] + #[test] + fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { + use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; + + let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); assert_eq!(enc_string.enc_type(), 6); - let res = enc_string.decrypt(&private_key).unwrap(); - - assert_eq!(std::str::from_utf8(&res).unwrap(), "EncryptMe!"); + let res: String = enc_string.decrypt_with_key(&private_key).unwrap(); + assert_eq!(res, "EncryptMe!"); } #[test] diff --git a/crates/bitwarden/src/crypto/enc_string/symmetric.rs b/crates/bitwarden/src/crypto/enc_string/symmetric.rs index 3fe0e8ef8..801aa9c43 100644 --- a/crates/bitwarden/src/crypto/enc_string/symmetric.rs +++ b/crates/bitwarden/src/crypto/enc_string/symmetric.rs @@ -227,13 +227,13 @@ impl EncString { } impl LocateKey for EncString {} -impl KeyEncryptable for &[u8] { +impl KeyEncryptable for &[u8] { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { EncString::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) } } -impl KeyDecryptable> for EncString { +impl KeyDecryptable> for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { @@ -246,13 +246,13 @@ impl KeyDecryptable> for EncString { } } -impl KeyEncryptable for String { +impl KeyEncryptable for String { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { self.as_bytes().encrypt_with_key(key) } } -impl KeyDecryptable for EncString { +impl KeyDecryptable for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index f1bc78f15..8a8d24d7d 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -29,14 +29,14 @@ pub trait Decryptable { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; } -impl + LocateKey, Output> Encryptable for T { +impl + LocateKey, Output> Encryptable for T { fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; self.encrypt_with_key(key) } } -impl + LocateKey, Output> Decryptable for T { +impl + LocateKey, Output> Decryptable for T { fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; self.decrypt_with_key(key) diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden/src/crypto/key_encryptable.rs index 99c610bb2..852b55c62 100644 --- a/crates/bitwarden/src/crypto/key_encryptable.rs +++ b/crates/bitwarden/src/crypto/key_encryptable.rs @@ -2,66 +2,78 @@ use std::{collections::HashMap, hash::Hash}; use crate::error::Result; -use super::SymmetricCryptoKey; +pub trait CryptoKey {} -pub trait KeyEncryptable { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; +pub trait KeyEncryptable { + fn encrypt_with_key(self, key: &Key) -> Result; } -pub trait KeyDecryptable { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result; +pub trait KeyDecryptable { + fn decrypt_with_key(&self, key: &Key) -> Result; } -impl, Output> KeyEncryptable> for Option { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { +impl, Key: CryptoKey, Output> KeyEncryptable> + for Option +{ + fn encrypt_with_key(self, key: &Key) -> Result> { self.map(|e| e.encrypt_with_key(key)).transpose() } } -impl, Output> KeyDecryptable> for Option { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { +impl, Key: CryptoKey, Output> KeyDecryptable> + for Option +{ + fn decrypt_with_key(&self, key: &Key) -> Result> { self.as_ref().map(|e| e.decrypt_with_key(key)).transpose() } } -impl, Output> KeyEncryptable for Box { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { +impl, Key: CryptoKey, Output> KeyEncryptable + for Box +{ + fn encrypt_with_key(self, key: &Key) -> Result { (*self).encrypt_with_key(key) } } -impl, Output> KeyDecryptable for Box { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { +impl, Key: CryptoKey, Output> KeyDecryptable + for Box +{ + fn decrypt_with_key(&self, key: &Key) -> Result { (**self).decrypt_with_key(key) } } -impl, Output> KeyEncryptable> for Vec { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { +impl, Key: CryptoKey, Output> KeyEncryptable> + for Vec +{ + fn encrypt_with_key(self, key: &Key) -> Result> { self.into_iter().map(|e| e.encrypt_with_key(key)).collect() } } -impl, Output> KeyDecryptable> for Vec { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { +impl, Key: CryptoKey, Output> KeyDecryptable> + for Vec +{ + fn decrypt_with_key(&self, key: &Key) -> Result> { self.iter().map(|e| e.decrypt_with_key(key)).collect() } } -impl, Output, Id: Hash + Eq> KeyEncryptable> - for HashMap +impl, Key: CryptoKey, Output, Id: Hash + Eq> + KeyEncryptable> for HashMap { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result> { + fn encrypt_with_key(self, key: &Key) -> Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?))) .collect() } } -impl, Output, Id: Hash + Eq + Copy> KeyDecryptable> - for HashMap +impl, Key: CryptoKey, Output, Id: Hash + Eq + Copy> + KeyDecryptable> for HashMap { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { + fn decrypt_with_key(&self, key: &Key) -> Result> { self.iter() .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?))) .collect() diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index 5355a337a..f21fdb256 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -2,7 +2,7 @@ //! //! This module contains the cryptographic primitives used throughout the SDK. The module makes a //! best effort to abstract away cryptographic concepts into concepts such as -//! [`EncString`] and [`SymmetricCryptoKey`]. +//! [`EncString`], [`SymmetricCryptoKey`] and [`AsymmetricCryptoKey`]. //! //! ## Conventions: //! @@ -36,11 +36,14 @@ pub use enc_string::{AsymmEncString, EncString}; mod encryptable; pub use encryptable::{Decryptable, Encryptable, LocateKey}; mod key_encryptable; -pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; +pub use key_encryptable::{CryptoKey, KeyDecryptable, KeyEncryptable}; mod aes_ops; use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; mod symmetric_crypto_key; pub use symmetric_crypto_key::SymmetricCryptoKey; +mod asymmetric_crypto_key; +pub use asymmetric_crypto_key::AsymmetricCryptoKey; + mod shareable_key; pub(crate) use shareable_key::derive_shareable_key; diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs index 5487dfd98..6f93d47f6 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden/src/crypto/symmetric_crypto_key.rs @@ -4,12 +4,15 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use rand::Rng; -use crate::error::{CryptoError, Error}; +use crate::{ + crypto::CryptoKey, + error::{CryptoError, Error}, +}; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) pub struct SymmetricCryptoKey { - pub key: GenericArray, - pub mac_key: Option>, + pub(super) key: GenericArray, + pub(super) mac_key: Option>, } impl SymmetricCryptoKey { @@ -81,10 +84,12 @@ impl TryFrom<&[u8]> for SymmetricCryptoKey { } } +impl CryptoKey for SymmetricCryptoKey {} + // We manually implement these to make sure we don't print any sensitive data impl std::fmt::Debug for SymmetricCryptoKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Key").finish() + f.debug_struct("SymmetricCryptoKey").finish() } } diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index cd763b765..1826e195f 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -1,6 +1,5 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use log::info; -use rsa::pkcs8::EncodePublicKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -44,12 +43,8 @@ pub(crate) fn generate_user_fingerprint( .as_ref() .ok_or("Missing private key")?; - let public_key = private_key - .to_public_key() - .to_public_key_der() - .map_err(|_| "Invalid key")?; - - let fingerprint = fingerprint(&fingerprint_material, public_key.as_bytes())?; + let public_key = private_key.to_public_der()?; + let fingerprint = fingerprint(&fingerprint_material, &public_key)?; Ok(fingerprint) } diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index e2d11f592..c22997c83 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -31,7 +31,7 @@ pub struct AttachmentView { pub key: Option, } -impl KeyEncryptable for AttachmentView { +impl KeyEncryptable for AttachmentView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, @@ -44,7 +44,7 @@ impl KeyEncryptable for AttachmentView { } } -impl KeyDecryptable for Attachment { +impl KeyDecryptable for Attachment { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 6f96041e9..c0f97e1df 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -31,7 +31,7 @@ pub struct CardView { pub number: Option, } -impl KeyEncryptable for CardView { +impl KeyEncryptable for CardView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { cardholder_name: self.cardholder_name.encrypt_with_key(key)?, @@ -44,7 +44,7 @@ impl KeyEncryptable for CardView { } } -impl KeyDecryptable for Card { +impl KeyDecryptable for Card { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { cardholder_name: self.cardholder_name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index e44a3757a..d36855a19 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -135,7 +135,7 @@ pub struct CipherListView { pub revision_date: DateTime, } -impl KeyEncryptable for CipherView { +impl KeyEncryptable for CipherView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -169,7 +169,7 @@ impl KeyEncryptable for CipherView { } } -impl KeyDecryptable for Cipher { +impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -286,7 +286,7 @@ impl Cipher { } } -impl KeyDecryptable for Cipher { +impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index dee71872b..bf9352d68 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -41,7 +41,7 @@ pub struct FieldView { linked_id: Option, } -impl KeyEncryptable for FieldView { +impl KeyEncryptable for FieldView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { name: self.name.encrypt_with_key(key)?, @@ -52,7 +52,7 @@ impl KeyEncryptable for FieldView { } } -impl KeyDecryptable for Field { +impl KeyDecryptable for Field { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { name: self.name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index 922d2aee6..c3082ccc9 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -55,7 +55,7 @@ pub struct IdentityView { pub license_number: Option, } -impl KeyEncryptable for IdentityView { +impl KeyEncryptable for IdentityView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { title: self.title.encrypt_with_key(key)?, @@ -80,7 +80,7 @@ impl KeyEncryptable for IdentityView { } } -impl KeyDecryptable for Identity { +impl KeyDecryptable for Identity { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { title: self.title.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index 8d5fe8694..a3d0bf519 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -22,7 +22,7 @@ pub struct LocalDataView { last_launched: Option, } -impl KeyEncryptable for LocalDataView { +impl KeyEncryptable for LocalDataView { fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, @@ -31,7 +31,7 @@ impl KeyEncryptable for LocalDataView { } } -impl KeyDecryptable for LocalData { +impl KeyDecryptable for LocalData { fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index da71f963f..8342fba53 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -64,7 +64,7 @@ pub struct LoginView { pub autofill_on_page_load: Option, } -impl KeyEncryptable for LoginUriView { +impl KeyEncryptable for LoginUriView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { uri: self.uri.encrypt_with_key(key)?, @@ -73,7 +73,7 @@ impl KeyEncryptable for LoginUriView { } } -impl KeyEncryptable for LoginView { +impl KeyEncryptable for LoginView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { username: self.username.encrypt_with_key(key)?, @@ -86,7 +86,7 @@ impl KeyEncryptable for LoginView { } } -impl KeyDecryptable for LoginUri { +impl KeyDecryptable for LoginUri { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { uri: self.uri.decrypt_with_key(key)?, @@ -95,7 +95,7 @@ impl KeyDecryptable for LoginUri { } } -impl KeyDecryptable for Login { +impl KeyDecryptable for Login { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { username: self.username.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 5fbb81811..ee24b74b3 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -29,7 +29,7 @@ pub struct SecureNoteView { r#type: SecureNoteType, } -impl KeyEncryptable for SecureNoteView { +impl KeyEncryptable for SecureNoteView { fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, @@ -37,7 +37,7 @@ impl KeyEncryptable for SecureNoteView { } } -impl KeyDecryptable for SecureNote { +impl KeyDecryptable for SecureNote { fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 3ff5d1350..8b39a9d22 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -46,7 +46,7 @@ impl LocateKey for Collection { enc.get_key(&Some(self.organization_id)) } } -impl KeyDecryptable for Collection { +impl KeyDecryptable for Collection { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 04a4bebf7..f41e0e2b0 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -28,7 +28,7 @@ pub struct FolderView { } impl LocateKey for FolderView {} -impl KeyEncryptable for FolderView { +impl KeyEncryptable for FolderView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, @@ -39,7 +39,7 @@ impl KeyEncryptable for FolderView { } impl LocateKey for Folder {} -impl KeyDecryptable for Folder { +impl KeyDecryptable for Folder { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 786c7a8f2..4475f1cff 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -25,7 +25,7 @@ pub struct PasswordHistoryView { } impl LocateKey for PasswordHistoryView {} -impl KeyEncryptable for PasswordHistoryView { +impl KeyEncryptable for PasswordHistoryView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { password: self.password.encrypt_with_key(key)?, @@ -35,7 +35,7 @@ impl KeyEncryptable for PasswordHistoryView { } impl LocateKey for PasswordHistory {} -impl KeyDecryptable for PasswordHistory { +impl KeyDecryptable for PasswordHistory { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistoryView { password: self.password.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index d8a18a8f6..742d3c592 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -156,7 +156,7 @@ impl Send { } } -impl KeyDecryptable for SendText { +impl KeyDecryptable for SendText { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { text: self.text.decrypt_with_key(key)?, @@ -165,7 +165,7 @@ impl KeyDecryptable for SendText { } } -impl KeyEncryptable for SendTextView { +impl KeyEncryptable for SendTextView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { text: self.text.encrypt_with_key(key)?, @@ -174,7 +174,7 @@ impl KeyEncryptable for SendTextView { } } -impl KeyDecryptable for SendFile { +impl KeyDecryptable for SendFile { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), @@ -185,7 +185,7 @@ impl KeyDecryptable for SendFile { } } -impl KeyEncryptable for SendFileView { +impl KeyEncryptable for SendFileView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), @@ -197,7 +197,7 @@ impl KeyEncryptable for SendFileView { } impl LocateKey for Send {} -impl KeyDecryptable for Send { +impl KeyDecryptable for Send { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key @@ -230,7 +230,7 @@ impl KeyDecryptable for Send { } } -impl KeyDecryptable for Send { +impl KeyDecryptable for Send { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key @@ -253,7 +253,7 @@ impl KeyDecryptable for Send { } impl LocateKey for SendView {} -impl KeyEncryptable for SendView { +impl KeyEncryptable for SendView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key From aef6a21592a14874f9fc172b5a241f1daa84dc50 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Fri, 12 Jan 2024 18:41:12 -0800 Subject: [PATCH 190/378] [SM-1076] - add `state_file_path` param to `access_token_login` (#496) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ## Objective Enable authentication with the state file. Relates to #388. ## Code changes - **`languages/python/bitwarden_sdk/bitwarden_client.py`**: Add optional `state_file_path` parameter to `access_token_login` ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Daniel García --- languages/python/bitwarden_sdk/bitwarden_client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/languages/python/bitwarden_sdk/bitwarden_client.py b/languages/python/bitwarden_sdk/bitwarden_client.py index cb669a40e..b5ea48c44 100644 --- a/languages/python/bitwarden_sdk/bitwarden_client.py +++ b/languages/python/bitwarden_sdk/bitwarden_client.py @@ -12,9 +12,10 @@ def __init__(self, settings: ClientSettings = None): settings_json = json.dumps(settings.to_dict()) self.inner = bitwarden_py.BitwardenClient(settings_json) - def access_token_login(self, access_token: str): + def access_token_login(self, access_token: str, + state_file_path: str = None): self._run_command( - Command(access_token_login=AccessTokenLoginRequest(access_token)) + Command(access_token_login=AccessTokenLoginRequest(access_token, state_file_path)) ) def secrets(self): From 2b33ad740136f9868cc3e23e6375db5ef452c31a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:45:33 +0100 Subject: [PATCH 191/378] [deps]: Update @types/node to v18.19.7 (#502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.5` -> `18.19.7`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.5/18.19.7) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.5/18.19.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.5/18.19.7?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index f1c72fa87..144a79f64 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.5.tgz", - "integrity": "sha512-22MG6T02Hos2JWfa1o5jsIByn+bc5iOt1IS4xyg6OG68Bu+wMonVZzdrgCw693++rpLE9RUT/Bx15BeDzO0j+g==", + "version": "18.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.7.tgz", + "integrity": "sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 1aec442aa7026f8e6bb71b6a69318ddf216dfeb8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:45:54 +0100 Subject: [PATCH 192/378] [deps]: Update prettier to v3.2.2 (#507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`3.1.1` -> `3.2.2`](https://renovatebot.com/diffs/npm/prettier/3.1.1/3.2.2) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.1.1/3.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.1.1/3.2.2?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prettier/prettier (prettier) ### [`v3.2.2`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#322) [Compare Source](https://togithub.com/prettier/prettier/compare/3.2.1...3.2.2) [diff](https://togithub.com/prettier/prettier/compare/3.2.1...3.2.2) ##### Fix crash when parsing template literal CSS in a JSX style tag using a spread attribute ([#​15896](https://togithub.com/prettier/prettier/pull/15896) by [@​eelco](https://togithub.com/eelco)) For example this code would crash before: ```jsx ``` ##### Fix formatting error on optional call expression and member chain ([#​15920](https://togithub.com/prettier/prettier/pull/15920) by [@​sosukesuzuki](https://togithub.com/sosukesuzuki)) ```jsx // Input a(() => {}, c?.d()); // Prettier 3.2.1 TypeError: Cannot read properties of undefined (reading 'type') // Prettier 3.2.2 a(() => {}, c?.d()); ``` ### [`v3.2.1`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#321) [Compare Source](https://togithub.com/prettier/prettier/compare/3.2.0...3.2.1) [diff](https://togithub.com/prettier/prettier/compare/3.2.0...3.2.1) ##### Fix formatting error on member chain ([#​15915](https://togithub.com/prettier/prettier/pull/15915) by [@​sosukesuzuki](https://togithub.com/sosukesuzuki)) ```jsx // Input test().test2().test2(thing?.something); // Prettier 3.2.0 TypeError: Cannot read properties of undefined (reading 'type') // Prettier 3.2.1 test().test2().test2(thing?.something); ``` ### [`v3.2.0`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#320) [Compare Source](https://togithub.com/prettier/prettier/compare/3.1.1...3.2.0) [diff](https://togithub.com/prettier/prettier/compare/3.1.1...3.2.0) 🔗 [Release Notes](https://prettier.io/blog/2024/01/13/3.2.0.html)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2bda48e9..3e47d00a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.1.1", + "prettier": "3.2.2", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", @@ -1470,9 +1470,9 @@ } }, "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz", + "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index 319086900..2becd41f2 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.7.0", "handlebars": "^4.7.8", - "prettier": "3.1.1", + "prettier": "3.2.2", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", From 37bfa28839dce4b139c68c81d8d6f8f5e2849407 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:08:02 +0100 Subject: [PATCH 193/378] [deps]: Update Rust crate async-lock to 3.3.0 (#505) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [async-lock](https://togithub.com/smol-rs/async-lock) | dependencies | minor | `3.2.0` -> `3.3.0` | --- ### Release Notes
smol-rs/async-lock (async-lock) ### [`v3.3.0`](https://togithub.com/smol-rs/async-lock/blob/HEAD/CHANGELOG.md#Version-330) [Compare Source](https://togithub.com/smol-rs/async-lock/compare/v3.2.0...v3.3.0) - Add a `forget()` method for semaphore guards. ([#​73](https://togithub.com/smol-rs/async-lock/issues/73)) - Increase MSRV to v1.60. ([#​75](https://togithub.com/smol-rs/async-lock/issues/75))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden-uniffi/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e04702e37..1542a82a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener 4.0.0", "event-listener-strategy", diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 4bf7b085b..7fc87bb4b 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["lib", "staticlib", "cdylib"] bench = false [dependencies] -async-lock = "3.2.0" +async-lock = "3.3.0" chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", From b5d3617e8acdd17170cb9bbbc43ff15c435f694f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:08:17 +0100 Subject: [PATCH 194/378] [deps]: Update rust-wasm-bindgen monorepo (#504) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [js-sys](https://rustwasm.github.io/wasm-bindgen/) ([source](https://togithub.com/rustwasm/wasm-bindgen/tree/HEAD/crates/js-sys)) | dependencies | patch | `0.3.66` -> `0.3.67` | | [wasm-bindgen](https://rustwasm.github.io/) ([source](https://togithub.com/rustwasm/wasm-bindgen)) | dependencies | patch | `0.2.89` -> `0.2.90` | | [wasm-bindgen-futures](https://rustwasm.github.io/wasm-bindgen/) ([source](https://togithub.com/rustwasm/wasm-bindgen/tree/HEAD/crates/futures)) | dependencies | patch | `0.4.39` -> `0.4.40` | | [wasm-bindgen-test](https://togithub.com/rustwasm/wasm-bindgen) | dev-dependencies | patch | `0.3.39` -> `0.3.40` | --- ### Release Notes
rustwasm/wasm-bindgen (wasm-bindgen) ### [`v0.2.90`](https://togithub.com/rustwasm/wasm-bindgen/blob/HEAD/CHANGELOG.md#0290) [Compare Source](https://togithub.com/rustwasm/wasm-bindgen/compare/0.2.89...0.2.90) Released 2024-01-06 ##### Fixed - Fix JS shim default path detection for the no-modules target. [#​3748](https://togithub.com/rustwasm/wasm-bindgen/pull/3748) ##### Added - Add bindings for `HTMLFormElement.requestSubmit()`. [#​3747](https://togithub.com/rustwasm/wasm-bindgen/pull/3747) - Add bindings for `RTCRtpSender.getCapabilities(DOMString)` method, `RTCRtpCapabilities`, `RTCRtpCodecCapability` and `RTCRtpHeaderExtensionCapability`. [#​3737](https://togithub.com/rustwasm/wasm-bindgen/pull/3737) - Add bindings for `UserActivation`. [#​3719](https://togithub.com/rustwasm/wasm-bindgen/pull/3719) - Add unstable bindings for the Compression Streams API. [#​3752](https://togithub.com/rustwasm/wasm-bindgen/pull/3752) ##### Changed - Stabilize File System API. [#​3745](https://togithub.com/rustwasm/wasm-bindgen/pull/3745) - Stabilize `QueuingStrategy`. [#​3753](https://togithub.com/rustwasm/wasm-bindgen/pull/3753) ##### Fixed - Fixed a compiler error when using `#[wasm_bindgen]` inside `macro_rules!`. [#​3725](https://togithub.com/rustwasm/wasm-bindgen/pull/3725) ##### Removed - Removed Gecko-only `InstallTriggerData` and Gecko-internal `FlexLineGrowthState`, `GridDeclaration`, `GridTrackState`, `RtcLifecycleEvent` and `WebrtcGlobalStatisticsReport` features. [#​3723](https://togithub.com/rustwasm/wasm-bindgen/pull/3723)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 36 ++++++++++++++++---------------- crates/bitwarden-wasm/Cargo.toml | 8 +++---- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1542a82a3..3feb2b7e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1809,9 +1809,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -3894,9 +3894,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "serde", @@ -3906,9 +3906,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", @@ -3921,9 +3921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -3933,9 +3933,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3943,9 +3943,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", @@ -3956,15 +3956,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-bindgen-test" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403" +checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3976,9 +3976,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.39" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89" +checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 4a4d7696c..9cbada205 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -10,11 +10,11 @@ crate-type = ["cdylib"] [dependencies] console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } -js-sys = "0.3.66" +js-sys = "0.3.67" log = "0.4.20" serde = { version = "1.0.195", features = ["derive"] } -wasm-bindgen = { version = "0.2.89", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.39" +wasm-bindgen = { version = "0.2.90", features = ["serde-serialize"] } +wasm-bindgen-futures = "0.4.40" bitwarden-json = { path = "../bitwarden-json", features = [ "secrets", @@ -22,4 +22,4 @@ bitwarden-json = { path = "../bitwarden-json", features = [ ] } [dev-dependencies] -wasm-bindgen-test = "0.3.39" +wasm-bindgen-test = "0.3.40" From 1028efde6557e30d241c03fd4754d32fe38db17a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:08:32 +0100 Subject: [PATCH 195/378] [deps]: Update Rust crate clap to 4.4.16 (#503) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap](https://togithub.com/clap-rs/clap) | dependencies | patch | `4.4.13` -> `4.4.16` | --- ### Release Notes
clap-rs/clap (clap) ### [`v4.4.16`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4416---2024-01-12) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.4.15...v4.4.16) ##### Fixes - Ensure invalid escape sequences in user-defined strings are correctly stripped when terminal doesn't support color ### [`v4.4.15`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4415---2024-01-11) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.4.14...v4.4.15) ##### Fixes - Improve error for `args_conflicts_with_subcommands` - Ensure we error for `args_conflicts_with_subcommands` when using subcommand short and long flags ### [`v4.4.14`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4414---2024-01-08) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.4.13...v4.4.14) ##### Documentation - Fix `find` cookbook entry to allow repeats of flags/options ##### Features - Allow `num_args(0)` on options which allows making them emulate being a flag for position-tracking flags
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 12 ++++++------ crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3feb2b7e7..ad513bd84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" dependencies = [ "anstyle", "anstyle-parse", @@ -687,9 +687,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.13" +version = "4.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642" +checksum = "58e54881c004cec7895b0068a0a954cd5d62da01aef83fa35b1e594497bf5445" dependencies = [ "clap_builder", "clap_derive", @@ -697,9 +697,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "59cb82d7f531603d2fd1f507441cdd35184fa81beff7bd489570de7f773460bb" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 217ac88c1..702232730 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.13", features = ["derive"] } +clap = { version = "4.4.16", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index d1298cf43..0ea4877f4 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.13", features = ["derive", "env"] } +clap = { version = "4.4.16", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 980fe684e..c334d9c01 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.13", features = ["derive", "env", "string"] } +clap = { version = "4.4.16", features = ["derive", "env", "string"] } clap_complete = "4.4.6" color-eyre = "0.6" comfy-table = "^7.1.0" From d2cb4f9c388eb3fb13e3268258557eabfa1202fd Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 15 Jan 2024 16:13:12 +0100 Subject: [PATCH 196/378] [PM-5691] Extract crypto to separate crate (#402) We should make an effort to break up the large `bitwarden` crate into smaller more isolated crates. This extracts the cryptographic primitives into a crate, which better isolates them and may improve compile time slightly. We should continue to extract further areas. --- .github/workflows/build-rust-crates.yml | 1 + .github/workflows/publish-rust-crates.yml | 11 +++ .github/workflows/version-bump.yml | 11 ++- .gitignore | 3 +- Cargo.lock | 39 ++++++-- crates/bitwarden-crypto/Cargo.toml | 45 +++++++++ .../src/aes.rs} | 23 ++--- .../src}/enc_string/asymmetric.rs | 26 ++--- .../src}/enc_string/mod.rs | 2 +- .../src}/enc_string/symmetric.rs | 34 +++---- .../src}/encryptable.rs | 39 ++++---- crates/bitwarden-crypto/src/error.rs | 58 +++++++++++ .../src}/fingerprint.rs | 25 +++-- .../src/keys}/asymmetric_crypto_key.rs | 10 +- .../src/keys}/key_encryptable.rs | 0 .../src/keys}/master_key.rs | 56 +++++++---- crates/bitwarden-crypto/src/keys/mod.rs | 18 ++++ .../src/keys}/shareable_key.rs | 4 +- .../src/keys}/symmetric_crypto_key.rs | 23 ++--- crates/bitwarden-crypto/src/keys/user_key.rs | 19 ++++ crates/bitwarden-crypto/src/lib.rs | 48 +++++++++ .../crypto => bitwarden-crypto/src}/rsa.rs | 13 ++- crates/bitwarden-crypto/src/uniffi_support.rs | 31 ++++++ crates/bitwarden-crypto/src/util.rs | 67 +++++++++++++ .../src/wordlist.rs | 3 +- crates/bitwarden-crypto/uniffi.toml | 8 ++ crates/bitwarden-uniffi/Cargo.toml | 3 + crates/bitwarden-uniffi/src/auth/mod.rs | 7 +- crates/bitwarden-uniffi/src/docs.rs | 3 +- crates/bitwarden-uniffi/src/uniffi_support.rs | 2 +- crates/bitwarden/Cargo.toml | 23 ++--- crates/bitwarden/src/auth/client_auth.rs | 7 +- .../bitwarden/src/auth/login/access_token.rs | 2 +- crates/bitwarden/src/auth/login/api_key.rs | 2 +- crates/bitwarden/src/auth/login/mod.rs | 39 +++++++- crates/bitwarden/src/auth/login/password.rs | 7 +- crates/bitwarden/src/auth/login/two_factor.rs | 3 +- crates/bitwarden/src/auth/mod.rs | 10 +- .../bitwarden/src/auth/password/validate.rs | 5 +- crates/bitwarden/src/auth/register.rs | 9 +- crates/bitwarden/src/client/access_token.rs | 7 +- crates/bitwarden/src/client/client.rs | 18 ++-- .../src/client/encryption_settings.rs | 22 +++-- crates/bitwarden/src/client/kdf.rs | 60 ------------ crates/bitwarden/src/client/mod.rs | 1 - crates/bitwarden/src/crypto/mod.rs | 97 ------------------- crates/bitwarden/src/crypto/user_key.rs | 19 ---- crates/bitwarden/src/error.rs | 37 +------ crates/bitwarden/src/lib.rs | 2 - crates/bitwarden/src/mobile/client_kdf.rs | 6 +- crates/bitwarden/src/mobile/crypto.rs | 15 ++- crates/bitwarden/src/mobile/kdf.rs | 11 +-- .../src/mobile/vault/client_ciphers.rs | 3 +- .../src/mobile/vault/client_collection.rs | 3 +- .../src/mobile/vault/client_folders.rs | 3 +- .../mobile/vault/client_password_history.rs | 3 +- .../src/mobile/vault/client_sends.rs | 7 +- .../bitwarden/src/mobile/vault/client_totp.rs | 7 +- .../src/platform/generate_fingerprint.rs | 8 +- .../src/platform/get_user_api_key.rs | 2 +- .../src/secrets_manager/projects/create.rs | 2 +- .../projects/project_response.rs | 2 +- .../src/secrets_manager/projects/update.rs | 2 +- .../src/secrets_manager/secrets/create.rs | 2 +- .../src/secrets_manager/secrets/list.rs | 2 +- .../secrets/secret_response.rs | 2 +- .../src/secrets_manager/secrets/update.rs | 2 +- crates/bitwarden/src/secrets_manager/state.rs | 5 +- .../src/tool/generators/passphrase.rs | 4 +- .../bitwarden/src/tool/generators/username.rs | 7 +- crates/bitwarden/src/uniffi_support.rs | 36 +------ .../bitwarden/src/vault/cipher/attachment.rs | 12 +-- crates/bitwarden/src/vault/cipher/card.rs | 12 +-- crates/bitwarden/src/vault/cipher/cipher.rs | 20 ++-- crates/bitwarden/src/vault/cipher/field.rs | 12 +-- crates/bitwarden/src/vault/cipher/identity.rs | 12 +-- .../bitwarden/src/vault/cipher/local_data.rs | 10 +- crates/bitwarden/src/vault/cipher/login.rs | 16 +-- .../bitwarden/src/vault/cipher/secure_note.rs | 10 +- crates/bitwarden/src/vault/collection.rs | 13 ++- crates/bitwarden/src/vault/folder.rs | 12 +-- .../bitwarden/src/vault/password_history.rs | 15 +-- crates/bitwarden/src/vault/send.rs | 39 ++++---- crates/bitwarden/src/vault/totp.rs | 6 +- crates/bitwarden/tests/register.rs | 2 +- .../bitwarden/myapplication/MainActivity.kt | 2 +- languages/swift/build.sh | 8 +- 87 files changed, 737 insertions(+), 600 deletions(-) create mode 100644 crates/bitwarden-crypto/Cargo.toml rename crates/{bitwarden/src/crypto/aes_ops.rs => bitwarden-crypto/src/aes.rs} (88%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/enc_string/asymmetric.rs (95%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/enc_string/mod.rs (98%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/enc_string/symmetric.rs (90%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/encryptable.rs (58%) create mode 100644 crates/bitwarden-crypto/src/error.rs rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/fingerprint.rs (81%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src/keys}/asymmetric_crypto_key.rs (97%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src/keys}/key_encryptable.rs (100%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src/keys}/master_key.rs (85%) create mode 100644 crates/bitwarden-crypto/src/keys/mod.rs rename crates/{bitwarden/src/crypto => bitwarden-crypto/src/keys}/shareable_key.rs (94%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src/keys}/symmetric_crypto_key.rs (87%) create mode 100644 crates/bitwarden-crypto/src/keys/user_key.rs create mode 100644 crates/bitwarden-crypto/src/lib.rs rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/rsa.rs (75%) create mode 100644 crates/bitwarden-crypto/src/uniffi_support.rs create mode 100644 crates/bitwarden-crypto/src/util.rs rename crates/{bitwarden => bitwarden-crypto}/src/wordlist.rs (99%) create mode 100644 crates/bitwarden-crypto/uniffi.toml delete mode 100644 crates/bitwarden/src/client/kdf.rs delete mode 100644 crates/bitwarden/src/crypto/mod.rs delete mode 100644 crates/bitwarden/src/crypto/user_key.rs diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index b008540fb..9acc1b37d 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -29,6 +29,7 @@ jobs: package: - bitwarden + - bitwarden-crypto - bitwarden-api-api - bitwarden-api-identity diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index aef94b37e..231ad5626 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -29,6 +29,11 @@ on: required: true default: true type: boolean + publish_bitwarden-crypto: + description: "Publish bitwarden-crypto crate" + required: true + default: true + type: boolean defaults: run: @@ -61,6 +66,7 @@ jobs: PUBLISH_BITWARDEN: ${{ github.event.inputs.publish_bitwarden }} PUBLISH_BITWARDEN_API_API: ${{ github.event.inputs.publish_bitwarden-api-api }} PUBLISH_BITWARDEN_API_IDENTITY: ${{ github.event.inputs.publish_bitwarden-api-identity }} + PUBLISH_BITWARDEN_CRYPTO: ${{ github.event.inputs.publish_bitwarden-crypto }} run: | if [[ "$PUBLISH_BITWARDEN" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_API" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_IDENTITY" == "false" ]]; then echo "===================================" @@ -87,6 +93,11 @@ jobs: PACKAGES_LIST="$PACKAGES_LIST bitwarden-api-identity" fi + if [[ "$PUBLISH_BITWARDEN_CRYPTO" == "true" ]]; then + PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-crypto" + PACKAGES_LIST="$PACKAGES_LIST bitwarden-crypto" + fi + echo "Packages command: " $PACKAGES_COMMAND echo "Packages list: " $PACKAGES_LIST diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index b27a6a989..f3c428c57 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -10,12 +10,13 @@ on: required: true type: choice options: - - napi - bitwarden - bitwarden-api-api - bitwarden-api-identity - - cli + - bitwarden-crypto - bitwarden-json + - cli + - napi version_number: description: "New version (example: '2024.1.0')" required: true @@ -116,6 +117,12 @@ jobs: if: ${{ inputs.project == 'bitwarden-api-identity' }} run: cargo-set-version set-version -p bitwarden-api-identity ${{ inputs.version_number }} + ### bitwarden-crypto + + - name: Bump bitwarden-crypto crate Version + if: ${{ inputs.project == 'bitwarden-crypto' }} + run: cargo-set-version set-version -p bitwarden-crypto ${{ inputs.version_number }} + ### cli - name: Bump cli Version diff --git a/.gitignore b/.gitignore index 23cbaba20..63c5875a3 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,7 @@ languages/swift/BitwardenFFI.xcframework languages/swift/tmp languages/swift/.build languages/swift/.swiftpm -languages/kotlin/sdk/src/main/java/com/bitwarden/sdk/bitwarden_uniffi.kt -languages/kotlin/sdk/src/main/java/com/bitwarden/core/bitwarden.kt +languages/kotlin/sdk/src/main/java/com/bitwarden/**/*.kt # Schemas crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts diff --git a/Cargo.lock b/Cargo.lock index ad513bd84..31a4b4d05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,26 +346,18 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" name = "bitwarden" version = "0.4.0" dependencies = [ - "aes", - "argon2", "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", - "cbc", + "bitwarden-crypto", "chrono", "data-encoding", "getrandom 0.2.11", - "hkdf", "hmac", - "lazy_static", "log", - "num-bigint", - "num-traits", - "pbkdf2", "rand 0.8.5", "rand_chacha 0.3.1", "reqwest", - "rsa", "rustls-platform-verifier", "schemars", "serde", @@ -374,7 +366,6 @@ dependencies = [ "serde_repr", "sha1", "sha2", - "subtle", "thiserror", "tokio", "uniffi", @@ -428,6 +419,33 @@ dependencies = [ "supports-color", ] +[[package]] +name = "bitwarden-crypto" +version = "0.1.0" +dependencies = [ + "aes", + "argon2", + "base64 0.21.5", + "cbc", + "hkdf", + "hmac", + "num-bigint", + "num-traits", + "pbkdf2", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rsa", + "schemars", + "serde", + "serde_json", + "sha1", + "sha2", + "subtle", + "thiserror", + "uniffi", + "uuid", +] + [[package]] name = "bitwarden-json" version = "0.3.0" @@ -469,6 +487,7 @@ version = "0.1.0" dependencies = [ "async-lock", "bitwarden", + "bitwarden-crypto", "chrono", "env_logger", "schemars", diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml new file mode 100644 index 000000000..4b7ac6cc4 --- /dev/null +++ b/crates/bitwarden-crypto/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "bitwarden-crypto" +version = "0.1.0" +authors = ["Bitwarden Inc"] +license-file = "LICENSE" +repository = "https://github.com/bitwarden/sdk" +homepage = "https://bitwarden.com" +description = """ +Bitwarden Cryptographic primitives +""" +keywords = ["bitwarden"] +edition = "2021" +rust-version = "1.57" + +[features] +default = [] + +mobile = ["uniffi"] + +[dependencies] +aes = ">=0.8.2, <0.9" +argon2 = { version = ">=0.5.0, <0.6", features = [ + "alloc", +], default-features = false } +base64 = ">=0.21.2, <0.22" +cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } +hkdf = ">=0.12.3, <0.13" +hmac = ">=0.12.1, <0.13" +num-bigint = ">=0.4, <0.5" +num-traits = ">=0.2.15, <0.3" +pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } +rand = ">=0.8.5, <0.9" +rsa = ">=0.9.2, <0.10" +schemars = { version = ">=0.8, <0.9", features = ["uuid1"] } +serde = { version = ">=1.0, <2.0", features = ["derive"] } +sha1 = ">=0.10.5, <0.11" +sha2 = ">=0.10.6, <0.11" +subtle = ">=2.5.0, <3.0" +thiserror = ">=1.0.40, <2.0" +uniffi = { version = "=0.25.2", optional = true } +uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } + +[dev-dependencies] +rand_chacha = "0.3.1" +serde_json = ">=1.0.96, <2.0" diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden-crypto/src/aes.rs similarity index 88% rename from crates/bitwarden/src/crypto/aes_ops.rs rename to crates/bitwarden-crypto/src/aes.rs index 00e71a3fd..cb4bf3102 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -2,11 +2,8 @@ //! //! Contains low level AES operations used by the rest of the library. //! -//! **Warning**: Consider carefully if you have to use these functions directly, as generally we -//! expose higher level functions that are easier to use and more secure. -//! -//! In most cases you should use the [EncString] with [KeyEncryptable][super::KeyEncryptable] & -//! [KeyDecryptable][super::KeyDecryptable] instead. +//! In most cases you should use the [EncString][crate::EncString] with +//! [KeyEncryptable][crate::KeyEncryptable] & [KeyDecryptable][crate::KeyDecryptable] instead. use aes::cipher::{ block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, @@ -16,14 +13,18 @@ use hmac::Mac; use subtle::ConstantTimeEq; use crate::{ - crypto::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, error::{CryptoError, Result}, + util::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, }; /// Decrypt using AES-256 in CBC mode. /// /// Behaves similar to [decrypt_aes256_hmac], but does not validate the MAC. -pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) -> Result> { +pub(crate) fn decrypt_aes256( + iv: &[u8; 16], + data: Vec, + key: GenericArray, +) -> Result> { // Decrypt data let iv = GenericArray::from_slice(iv); let mut data = data; @@ -41,7 +42,7 @@ pub fn decrypt_aes256(iv: &[u8; 16], data: Vec, key: GenericArray) /// Decrypt using AES-256 in CBC mode with MAC. /// /// Behaves similar to [decrypt_aes256], but also validates the MAC. -pub fn decrypt_aes256_hmac( +pub(crate) fn decrypt_aes256_hmac( iv: &[u8; 16], mac: &[u8; 32], data: Vec, @@ -50,7 +51,7 @@ pub fn decrypt_aes256_hmac( ) -> Result> { let res = generate_mac(&mac_key, iv, &data)?; if res.ct_ne(mac).into() { - return Err(CryptoError::InvalidMac.into()); + return Err(CryptoError::InvalidMac); } decrypt_aes256(iv, data, key) } @@ -63,7 +64,7 @@ pub fn decrypt_aes256_hmac( /// /// A AesCbc256_B64 EncString #[allow(unused)] -pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { +pub(crate) fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { let rng = rand::thread_rng(); let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); @@ -77,7 +78,7 @@ pub fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], /// ## Returns /// /// A AesCbc256_HmacSha256_B64 EncString -pub fn encrypt_aes256_hmac( +pub(crate) fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, key: GenericArray, diff --git a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs similarity index 95% rename from crates/bitwarden/src/crypto/enc_string/asymmetric.rs rename to crates/bitwarden-crypto/src/enc_string/asymmetric.rs index a2bbee8cb..0c48ce14a 100644 --- a/crates/bitwarden/src/crypto/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -4,13 +4,12 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use rsa::Oaep; use serde::Deserialize; +use super::{from_b64_vec, split_enc_string}; use crate::{ - crypto::{AsymmetricCryptoKey, KeyDecryptable}, - error::{CryptoError, EncStringParseError, Error, Result}, + error::{CryptoError, EncStringParseError, Result}, + AsymmetricCryptoKey, KeyDecryptable, }; -use super::{from_b64_vec, split_enc_string}; - /// # Encrypted string primitive /// /// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are @@ -64,7 +63,7 @@ impl std::fmt::Debug for AsymmEncString { /// Deserializes an [AsymmEncString] from a string. impl FromStr for AsymmEncString { - type Err = Error; + type Err = CryptoError; fn from_str(s: &str) -> Result { let (enc_type, parts) = split_enc_string(s); @@ -153,7 +152,7 @@ impl AsymmEncString { impl KeyDecryptable> for AsymmEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result> { use AsymmEncString::*; - Ok(match self { + match self { Rsa2048_OaepSha256_B64 { data } => key.key.decrypt(Oaep::new::(), data), Rsa2048_OaepSha1_B64 { data } => key.key.decrypt(Oaep::new::(), data), #[allow(deprecated)] @@ -165,14 +164,14 @@ impl KeyDecryptable> for AsymmEncString { key.key.decrypt(Oaep::new::(), data) } } - .map_err(|_| CryptoError::KeyDecrypt)?) + .map_err(|_| CryptoError::KeyDecrypt) } } impl KeyDecryptable for AsymmEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String) } } @@ -190,7 +189,7 @@ impl schemars::JsonSchema for AsymmEncString { #[cfg(test)] mod tests { - use super::AsymmEncString; + use super::{AsymmEncString, AsymmetricCryptoKey, KeyDecryptable}; const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS @@ -221,11 +220,8 @@ WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz XKZBokBGnjFnTnKcs7nv/O8= -----END PRIVATE KEY-----"; - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha256_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "3.YFqzW9LL/uLjCnl0RRLtndzGJ1FV27mcwQwGjfJPOVrgCX9nJSUYCCDd0iTIyOZ/zRxG47b6L1Z3qgkEfcxjmrSBq60gijc3E2TBMAg7OCLVcjORZ+i1sOVOudmOPWro6uA8refMrg4lqbieDlbLMzjVEwxfi5WpcL876cD0vYyRwvLO3bzFrsE7x33HHHtZeOPW79RqMn5efsB5Dj9wVheC9Ix9AYDjbo+rjg9qR6guwKmS7k2MSaIQlrDR7yu8LP+ePtiSjx+gszJV5jQGfcx60dtiLQzLS/mUD+RmU7B950Bpx0H7x56lT5yXZbWK5YkoP6qd8B8D2aKbP68Ywg=="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); @@ -236,11 +232,8 @@ XKZBokBGnjFnTnKcs7nv/O8= assert_eq!(res, "EncryptMe!"); } - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha1_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw=="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); @@ -251,11 +244,8 @@ XKZBokBGnjFnTnKcs7nv/O8= assert_eq!(res, "EncryptMe!"); } - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); diff --git a/crates/bitwarden/src/crypto/enc_string/mod.rs b/crates/bitwarden-crypto/src/enc_string/mod.rs similarity index 98% rename from crates/bitwarden/src/crypto/enc_string/mod.rs rename to crates/bitwarden-crypto/src/enc_string/mod.rs index a998e6056..740e9589d 100644 --- a/crates/bitwarden/src/crypto/enc_string/mod.rs +++ b/crates/bitwarden-crypto/src/enc_string/mod.rs @@ -1,3 +1,4 @@ +/// Encrypted string types mod asymmetric; mod symmetric; @@ -9,7 +10,6 @@ pub use symmetric::EncString; use crate::error::{EncStringParseError, Result}; -#[cfg(feature = "mobile")] fn check_length(buf: &[u8], expected: usize) -> Result<()> { if buf.len() < expected { return Err(EncStringParseError::InvalidLength { diff --git a/crates/bitwarden/src/crypto/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs similarity index 90% rename from crates/bitwarden/src/crypto/enc_string/symmetric.rs rename to crates/bitwarden-crypto/src/enc_string/symmetric.rs index 801aa9c43..d6dd44374 100644 --- a/crates/bitwarden/src/crypto/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -4,12 +4,10 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use serde::Deserialize; -#[cfg(feature = "mobile")] -use super::check_length; -use super::{from_b64, from_b64_vec, split_enc_string}; +use super::{check_length, from_b64, from_b64_vec, split_enc_string}; use crate::{ - crypto::{decrypt_aes256_hmac, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::{CryptoError, EncStringParseError, Error, Result}, + error::{CryptoError, EncStringParseError, Result}, + KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, }; /// # Encrypted string primitive @@ -73,7 +71,7 @@ impl std::fmt::Debug for EncString { /// Deserializes an [EncString] from a string. impl FromStr for EncString { - type Err = Error; + type Err = CryptoError; fn from_str(s: &str) -> Result { let (enc_type, parts) = split_enc_string(s); @@ -107,13 +105,11 @@ impl FromStr for EncString { impl EncString { /// Synthetic sugar for mapping `Option` to `Result>` - #[cfg(feature = "internal")] - pub(crate) fn try_from_optional(s: Option) -> Result, Error> { + pub fn try_from_optional(s: Option) -> Result, CryptoError> { s.map(|s| s.parse()).transpose() } - #[cfg(feature = "mobile")] - pub(crate) fn from_buffer(buf: &[u8]) -> Result { + pub fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { return Err(EncStringParseError::NoType.into()); } @@ -147,8 +143,7 @@ impl EncString { } } - #[cfg(feature = "mobile")] - pub(crate) fn to_buffer(&self) -> Result> { + pub fn to_buffer(&self) -> Result> { let mut buf; match self { @@ -207,12 +202,12 @@ impl serde::Serialize for EncString { } impl EncString { - pub(crate) fn encrypt_aes256_hmac( + pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, key: GenericArray, ) -> Result { - let (iv, mac, data) = crate::crypto::encrypt_aes256_hmac(data_dec, mac_key, key)?; + let (iv, mac, data) = crate::aes::encrypt_aes256_hmac(data_dec, mac_key, key)?; Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } @@ -238,10 +233,10 @@ impl KeyDecryptable> for EncString { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; - let dec = decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?; + let dec = crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?; Ok(dec) } - _ => Err(CryptoError::InvalidKey.into()), + _ => Err(CryptoError::InvalidKey), } } } @@ -255,7 +250,7 @@ impl KeyEncryptable for String { impl KeyDecryptable for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String) } } @@ -274,9 +269,7 @@ impl schemars::JsonSchema for EncString { #[cfg(test)] mod tests { use super::EncString; - use crate::crypto::{ - symmetric_crypto_key::derive_symmetric_key, KeyDecryptable, KeyEncryptable, - }; + use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable}; #[test] fn test_enc_string_roundtrip() { @@ -305,7 +298,6 @@ mod tests { assert_eq!(serde_json::to_string(&t).unwrap(), serialized); } - #[cfg(feature = "mobile")] #[test] fn test_enc_from_to_buffer() { let enc_str: &str = "2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8="; diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden-crypto/src/encryptable.rs similarity index 58% rename from crates/bitwarden/src/crypto/encryptable.rs rename to crates/bitwarden-crypto/src/encryptable.rs index 8a8d24d7d..9f1256afa 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden-crypto/src/encryptable.rs @@ -2,17 +2,16 @@ use std::{collections::HashMap, hash::Hash}; use uuid::Uuid; -use crate::{ - client::encryption_settings::EncryptionSettings, - error::{Error, Result}, -}; +use crate::{CryptoError, KeyDecryptable, KeyEncryptable, Result, SymmetricCryptoKey}; -use super::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +pub trait KeyContainer { + fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey>; +} pub trait LocateKey { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, org_id: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(org_id) @@ -21,36 +20,40 @@ pub trait LocateKey { /// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Encryptable { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result; } /// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Decryptable { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result; } impl + LocateKey, Output> Encryptable for T { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result { + let key = self + .locate_key(enc, org_id) + .ok_or(CryptoError::MissingKey)?; self.encrypt_with_key(key) } } impl + LocateKey, Output> Decryptable for T { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result { + let key = self + .locate_key(enc, org_id) + .ok_or(CryptoError::MissingKey)?; self.decrypt_with_key(key) } } impl, Output> Encryptable> for Vec { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result> { + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.into_iter().map(|e| e.encrypt(enc, org_id)).collect() } } impl, Output> Decryptable> for Vec { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result> { + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.iter().map(|e| e.decrypt(enc, org_id)).collect() } } @@ -58,11 +61,7 @@ impl, Output> Decryptable> for Vec { impl, Output, Id: Hash + Eq> Encryptable> for HashMap { - fn encrypt( - self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result> { + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) .collect() @@ -74,7 +73,7 @@ impl, Output, Id: Hash + Eq + Copy> Decryptable, ) -> Result> { self.iter() diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs new file mode 100644 index 000000000..059cc88f1 --- /dev/null +++ b/crates/bitwarden-crypto/src/error.rs @@ -0,0 +1,58 @@ +use std::fmt::Debug; + +use thiserror::Error; + +use crate::fingerprint::FingerprintError; + +#[derive(Debug, Error)] +pub enum CryptoError { + #[error("The provided key is not the expected type")] + InvalidKey, + #[error("The cipher's MAC doesn't match the expected value")] + InvalidMac, + #[error("Error while decrypting EncString")] + KeyDecrypt, + #[error("The cipher key has an invalid length")] + InvalidKeyLen, + #[error("The value is not a valid UTF8 String")] + InvalidUtf8String, + #[error("Missing Key")] + MissingKey, + + #[error("EncString error, {0}")] + EncString(#[from] EncStringParseError), + + #[error("Rsa error, {0}")] + RsaError(#[from] RsaError), + + #[error("Fingerprint error, {0}")] + FingerprintError(#[from] FingerprintError), + + #[error("Number is zero")] + ZeroNumber, +} + +#[derive(Debug, Error)] +pub enum EncStringParseError { + #[error("No type detected, missing '.' separator")] + NoType, + #[error("Invalid symmetric type, got type {enc_type} with {parts} parts")] + InvalidTypeSymm { enc_type: String, parts: usize }, + #[error("Invalid asymmetric type, got type {enc_type} with {parts} parts")] + InvalidTypeAsymm { enc_type: String, parts: usize }, + #[error("Error decoding base64: {0}")] + InvalidBase64(#[from] base64::DecodeError), + #[error("Invalid length: expected {expected}, got {got}")] + InvalidLength { expected: usize, got: usize }, +} + +#[derive(Debug, Error)] +pub enum RsaError { + #[error("Unable to create public key")] + CreatePublicKey, + #[error("Unable to create private key")] + CreatePrivateKey, +} + +/// Alias for `Result`. +pub(crate) type Result = std::result::Result; diff --git a/crates/bitwarden/src/crypto/fingerprint.rs b/crates/bitwarden-crypto/src/fingerprint.rs similarity index 81% rename from crates/bitwarden/src/crypto/fingerprint.rs rename to crates/bitwarden-crypto/src/fingerprint.rs index 707a07ca6..d3e69d577 100644 --- a/crates/bitwarden/src/crypto/fingerprint.rs +++ b/crates/bitwarden-crypto/src/fingerprint.rs @@ -1,27 +1,34 @@ +//! # Fingerprint +//! +//! Provides a way to derive fingerprints from fingerprint material and public keys. This is most +//! commonly used for account fingerprints, where the fingerprint material is the user's id and the +//! public key is the user's public key. + use num_bigint::BigUint; use num_traits::cast::ToPrimitive; use sha2::Digest; +use thiserror::Error; -use crate::{error::Result, wordlist::EFF_LONG_WORD_LIST}; +use crate::{error::Result, wordlist::EFF_LONG_WORD_LIST, CryptoError}; /// Computes a fingerprint of the given `fingerprint_material` using the given `public_key`. /// /// This is commonly used for account fingerprints. With the following arguments: /// - `fingerprint_material`: user's id. /// - `public_key`: user's public key. -pub(crate) fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result { +pub fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result { let mut h = sha2::Sha256::new(); h.update(public_key); h.finalize(); let hkdf = - hkdf::Hkdf::::from_prk(public_key).map_err(|_| "hkdf::InvalidLength")?; + hkdf::Hkdf::::from_prk(public_key).map_err(|_| CryptoError::InvalidKeyLen)?; let mut user_fingerprint = [0u8; 32]; hkdf.expand(fingerprint_material.as_bytes(), &mut user_fingerprint) - .map_err(|_| "hkdf::expand")?; + .map_err(|_| CryptoError::InvalidKeyLen)?; - Ok(hash_word(user_fingerprint).unwrap()) + hash_word(user_fingerprint) } /// Derive a 5 word phrase from a 32 byte hash. @@ -34,7 +41,7 @@ fn hash_word(hash: [u8; 32]) -> Result { let hash_arr: Vec = hash.to_vec(); let entropy_available = hash_arr.len() * 4; if num_words as f64 * entropy_per_word > entropy_available as f64 { - return Err("Output entropy of hash function is too small".into()); + return Err(FingerprintError::EntropyTooSmall.into()); } let mut phrase = Vec::new(); @@ -50,6 +57,12 @@ fn hash_word(hash: [u8; 32]) -> Result { Ok(phrase.join("-")) } +#[derive(Debug, Error)] +pub enum FingerprintError { + #[error("Entropy is too small")] + EntropyTooSmall, +} + #[cfg(test)] mod tests { use super::fingerprint; diff --git a/crates/bitwarden/src/crypto/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs similarity index 97% rename from crates/bitwarden/src/crypto/asymmetric_crypto_key.rs rename to crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index 93098faa4..a3e06800b 100644 --- a/crates/bitwarden/src/crypto/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -1,13 +1,11 @@ use rsa::RsaPrivateKey; -use crate::{ - crypto::CryptoKey, - error::{CryptoError, Result}, -}; +use super::key_encryptable::CryptoKey; +use crate::error::{CryptoError, Result}; -/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) +/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct AsymmetricCryptoKey { - pub(in crate::crypto) key: RsaPrivateKey, + pub(crate) key: RsaPrivateKey, } impl AsymmetricCryptoKey { diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden-crypto/src/keys/key_encryptable.rs similarity index 100% rename from crates/bitwarden/src/crypto/key_encryptable.rs rename to crates/bitwarden-crypto/src/keys/key_encryptable.rs diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs similarity index 85% rename from crates/bitwarden/src/crypto/master_key.rs rename to crates/bitwarden-crypto/src/keys/master_key.rs index b22e11c6b..bdd626a1a 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -1,10 +1,29 @@ +use std::num::NonZeroU32; + use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; use sha2::Digest; -use super::{hkdf_expand, EncString, KeyDecryptable, SymmetricCryptoKey, UserKey}; -use crate::{client::kdf::Kdf, error::Result}; +use crate::{ + util::{self, hkdf_expand}, + EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey, +}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum Kdf { + PBKDF2 { + iterations: NonZeroU32, + }, + Argon2id { + iterations: NonZeroU32, + memory: NonZeroU32, + parallelism: NonZeroU32, + }, +} #[derive(Copy, Clone, JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -13,8 +32,10 @@ pub enum HashPurpose { LocalAuthorization = 2, } -/// A Master Key. -pub(crate) struct MasterKey(SymmetricCryptoKey); +/// Master Key. +/// +/// Derived from the users master password, used to protect the [UserKey]. +pub struct MasterKey(SymmetricCryptoKey); impl MasterKey { /// Derives a users master key from their password, email and KDF. @@ -22,29 +43,27 @@ impl MasterKey { derive_key(password, email, kdf).map(Self) } - /// Derive the master key hash, used for server authorization. - pub(crate) fn derive_master_key_hash( - &self, - password: &[u8], - purpose: HashPurpose, - ) -> Result { - let hash = super::pbkdf2(&self.0.key, password, purpose as u32); + /// Derive the master key hash, used for local and remote password validation. + pub fn derive_master_key_hash(&self, password: &[u8], purpose: HashPurpose) -> Result { + let hash = util::pbkdf2(&self.0.key, password, purpose as u32); Ok(STANDARD.encode(hash)) } - pub(crate) fn make_user_key(&self) -> Result<(UserKey, EncString)> { + /// Generate a new random user key and encrypt it with the master key. + pub fn make_user_key(&self) -> Result<(UserKey, EncString)> { make_user_key(rand::thread_rng(), self) } - pub(crate) fn decrypt_user_key(&self, user_key: EncString) -> Result { + /// Decrypt the users user key + pub fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_slice()) } - pub(crate) fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result { + pub fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result { let stretched_key = stretch_master_key(self)?; EncString::encrypt_aes256_hmac( @@ -68,7 +87,7 @@ fn make_user_key( /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { let hash = match kdf { - Kdf::PBKDF2 { iterations } => super::pbkdf2(secret, salt, iterations.get()), + Kdf::PBKDF2 { iterations } => crate::util::pbkdf2(secret, salt, iterations.get()), Kdf::Argon2id { iterations, @@ -117,11 +136,8 @@ mod tests { use rand::SeedableRng; - use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; - use crate::{ - client::kdf::Kdf, - crypto::{symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}, - }; + use super::{make_user_key, stretch_master_key, HashPurpose, Kdf, MasterKey}; + use crate::{keys::symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}; #[test] fn test_master_key_derive_pbkdf2() { diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs new file mode 100644 index 000000000..4f53456ef --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -0,0 +1,18 @@ +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; + +mod master_key; +pub use master_key::{HashPurpose, Kdf, MasterKey}; + +mod shareable_key; +pub use shareable_key::derive_shareable_key; + +mod symmetric_crypto_key; +#[cfg(test)] +pub use symmetric_crypto_key::derive_symmetric_key; +pub use symmetric_crypto_key::SymmetricCryptoKey; +mod asymmetric_crypto_key; +pub use asymmetric_crypto_key::AsymmetricCryptoKey; + +mod user_key; +pub use user_key::UserKey; diff --git a/crates/bitwarden/src/crypto/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs similarity index 94% rename from crates/bitwarden/src/crypto/shareable_key.rs rename to crates/bitwarden-crypto/src/keys/shareable_key.rs index 4127b0712..a13f17155 100644 --- a/crates/bitwarden/src/crypto/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -1,13 +1,13 @@ use aes::cipher::{generic_array::GenericArray, typenum::U64}; use hmac::{Hmac, Mac}; -use crate::crypto::{hkdf_expand, SymmetricCryptoKey}; +use crate::{keys::SymmetricCryptoKey, util::hkdf_expand}; /// Derive a shareable key using hkdf from secret and name. /// /// A specialized variant of this function was called `CryptoService.makeSendKey` in the Bitwarden /// `clients` repository. -pub(crate) fn derive_shareable_key( +pub fn derive_shareable_key( secret: [u8; 16], name: &str, info: Option<&str>, diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs similarity index 87% rename from crates/bitwarden/src/crypto/symmetric_crypto_key.rs rename to crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 6f93d47f6..31b00fd54 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -4,15 +4,13 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use rand::Rng; -use crate::{ - crypto::CryptoKey, - error::{CryptoError, Error}, -}; +use super::key_encryptable::CryptoKey; +use crate::CryptoError; -/// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) +/// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { - pub(super) key: GenericArray, - pub(super) mac_key: Option>, + pub(crate) key: GenericArray, + pub(crate) mac_key: Option>, } impl SymmetricCryptoKey { @@ -44,8 +42,7 @@ impl SymmetricCryptoKey { STANDARD.encode(&buf) } - #[cfg(feature = "internal")] - pub(super) fn to_vec(&self) -> Vec { + pub fn to_vec(&self) -> Vec { let mut buf = Vec::new(); buf.extend_from_slice(&self.key); if let Some(mac) = self.mac_key { @@ -56,7 +53,7 @@ impl SymmetricCryptoKey { } impl FromStr for SymmetricCryptoKey { - type Err = Error; + type Err = CryptoError; fn from_str(s: &str) -> Result { let bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; @@ -65,7 +62,7 @@ impl FromStr for SymmetricCryptoKey { } impl TryFrom<&[u8]> for SymmetricCryptoKey { - type Error = Error; + type Error = CryptoError; fn try_from(value: &[u8]) -> Result { if value.len() == Self::KEY_LEN + Self::MAC_LEN { @@ -79,7 +76,7 @@ impl TryFrom<&[u8]> for SymmetricCryptoKey { mac_key: None, }) } else { - Err(CryptoError::InvalidKeyLen.into()) + Err(CryptoError::InvalidKeyLen) } } } @@ -95,7 +92,7 @@ impl std::fmt::Debug for SymmetricCryptoKey { #[cfg(test)] pub fn derive_symmetric_key(name: &str) -> SymmetricCryptoKey { - use crate::crypto::{derive_shareable_key, generate_random_bytes}; + use crate::{derive_shareable_key, generate_random_bytes}; let secret: [u8; 16] = generate_random_bytes(); derive_shareable_key(secret, name, None) diff --git a/crates/bitwarden-crypto/src/keys/user_key.rs b/crates/bitwarden-crypto/src/keys/user_key.rs new file mode 100644 index 000000000..6620236ec --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/user_key.rs @@ -0,0 +1,19 @@ +use crate::{ + rsa::{make_key_pair, RsaKeyPair}, + Result, SymmetricCryptoKey, +}; + +/// User Key +/// +/// The User Key is the symmetric encryption key used to decrypt the user's vault. +pub struct UserKey(pub SymmetricCryptoKey); + +impl UserKey { + pub fn new(key: SymmetricCryptoKey) -> Self { + Self(key) + } + + pub fn make_key_pair(&self) -> Result { + make_key_pair(&self.0) + } +} diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs new file mode 100644 index 000000000..a7399ce8e --- /dev/null +++ b/crates/bitwarden-crypto/src/lib.rs @@ -0,0 +1,48 @@ +//! # Bitwarden Cryptographic primitives +//! +//! This crate contains the cryptographic primitives used throughout the SDK. The crate makes a +//! best effort to abstract away cryptographic concepts into concepts such as [`EncString`], +//! [`AsymmEncString`] and [`SymmetricCryptoKey`]. +//! +//! ## Conventions: +//! +//! - Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`. +//! - Functions that generate non deterministically keys are prefixed with `make_`. +//! +//! ## Differences from `clients` +//! +//! There are some noteworthy differences compared to the other Bitwarden +//! [clients](https://github.com/bitwarden/clients). These changes are made in an effort to +//! introduce conventions in how we name things, improve best practices and abstracting away +//! internal complexity. +//! +//! - `CryptoService.makeSendKey` & `AccessService.createAccessToken` are replaced by the generic +//! `derive_shareable_key` +//! - MasterKey operations such as `makeMasterKey` and `hashMasterKey` are moved to the MasterKey +//! struct. + +mod aes; +mod enc_string; +pub use enc_string::{AsymmEncString, EncString}; +mod encryptable; +pub use encryptable::{Decryptable, Encryptable, KeyContainer, LocateKey}; +mod error; +pub use error::CryptoError; +pub(crate) use error::Result; +mod fingerprint; +pub use fingerprint::fingerprint; +mod keys; +pub use keys::*; +mod rsa; +pub use crate::rsa::RsaKeyPair; +mod util; +pub use util::generate_random_bytes; +mod wordlist; +pub use util::pbkdf2; +pub use wordlist::EFF_LONG_WORD_LIST; + +#[cfg(feature = "mobile")] +uniffi::setup_scaffolding!(); + +#[cfg(feature = "mobile")] +mod uniffi_support; diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs similarity index 75% rename from crates/bitwarden/src/crypto/rsa.rs rename to crates/bitwarden-crypto/src/rsa.rs index 9641237fc..ff665c247 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -5,10 +5,13 @@ use rsa::{ }; use crate::{ - crypto::{EncString, SymmetricCryptoKey}, - error::Result, + error::{Result, RsaError}, + EncString, SymmetricCryptoKey, }; +/// RSA Key Pair +/// +/// Consists of a public key and an encrypted private key. #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct RsaKeyPair { /// Base64 encoded DER representation of the public key @@ -17,7 +20,7 @@ pub struct RsaKeyPair { pub private: EncString, } -pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { +pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let mut rng = rand::thread_rng(); let bits = 2048; let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); @@ -25,12 +28,12 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let spki = pub_key .to_public_key_der() - .map_err(|_| "unable to create public key")?; + .map_err(|_| RsaError::CreatePublicKey)?; let b64 = STANDARD.encode(spki.as_bytes()); let pkcs = priv_key .to_pkcs8_der() - .map_err(|_| "unable to create private key")?; + .map_err(|_| RsaError::CreatePrivateKey)?; let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs new file mode 100644 index 000000000..0ff0194f9 --- /dev/null +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -0,0 +1,31 @@ +use std::num::NonZeroU32; + +use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; + +uniffi::custom_type!(NonZeroU32, u32); + +impl UniffiCustomTypeConverter for NonZeroU32 { + type Builtin = u32; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::new(val).ok_or(CryptoError::ZeroNumber.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.get() + } +} + +uniffi::custom_type!(EncString, String); + +impl UniffiCustomTypeConverter for EncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + val.parse().map_err(|e: CryptoError| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} diff --git a/crates/bitwarden-crypto/src/util.rs b/crates/bitwarden-crypto/src/util.rs new file mode 100644 index 000000000..261424e51 --- /dev/null +++ b/crates/bitwarden-crypto/src/util.rs @@ -0,0 +1,67 @@ +use ::aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; +use hmac::digest::OutputSizeUser; +use rand::{ + distributions::{Distribution, Standard}, + Rng, +}; + +use crate::{CryptoError, Result}; + +pub(crate) type PbkdfSha256Hmac = hmac::Hmac; +pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = + <::OutputSize as Unsigned>::USIZE; + +/// [RFC5869](https://datatracker.ietf.org/doc/html/rfc5869) HKDF-Expand operation +pub(crate) fn hkdf_expand>( + prk: &[u8], + info: Option<&str>, +) -> Result> { + let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| CryptoError::InvalidKeyLen)?; + let mut key = GenericArray::::default(); + + let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); + hkdf.expand(i, &mut key) + .map_err(|_| CryptoError::InvalidKeyLen)?; + + Ok(key) +} + +/// Generate random bytes that are cryptographically secure +pub fn generate_random_bytes() -> T +where + Standard: Distribution, +{ + rand::thread_rng().gen() +} + +pub fn pbkdf2(password: &[u8], salt: &[u8], rounds: u32) -> [u8; PBKDF_SHA256_HMAC_OUT_SIZE] { + pbkdf2::pbkdf2_array::(password, salt, rounds) + .expect("hash is a valid fixed size") +} + +#[cfg(test)] +mod tests { + use aes::cipher::typenum::U64; + + use super::*; + + #[test] + fn test_hkdf_expand() { + let prk = &[ + 23, 152, 120, 41, 214, 16, 156, 133, 71, 226, 178, 135, 208, 255, 66, 101, 189, 70, + 173, 30, 39, 215, 175, 236, 38, 180, 180, 62, 196, 4, 159, 70, + ]; + let info = Some("info"); + + let result: GenericArray = hkdf_expand(prk, info).unwrap(); + + let expected_output: [u8; 64] = [ + 6, 114, 42, 38, 87, 231, 30, 109, 30, 255, 104, 129, 255, 94, 92, 108, 124, 145, 215, + 208, 17, 60, 135, 22, 70, 158, 40, 53, 45, 182, 8, 63, 65, 87, 239, 234, 185, 227, 153, + 122, 115, 205, 144, 56, 102, 149, 92, 139, 217, 102, 119, 57, 37, 57, 251, 178, 18, 52, + 94, 77, 132, 215, 239, 100, + ]; + + assert_eq!(result.as_slice(), expected_output); + } +} diff --git a/crates/bitwarden/src/wordlist.rs b/crates/bitwarden-crypto/src/wordlist.rs similarity index 99% rename from crates/bitwarden/src/wordlist.rs rename to crates/bitwarden-crypto/src/wordlist.rs index 4974969e6..4cc30ff74 100644 --- a/crates/bitwarden/src/wordlist.rs +++ b/crates/bitwarden-crypto/src/wordlist.rs @@ -1,6 +1,5 @@ // EFF's Long Wordlist from https://www.eff.org/dice -#[cfg(feature = "internal")] -pub(crate) const EFF_LONG_WORD_LIST: &[&str] = &[ +pub const EFF_LONG_WORD_LIST: &[&str] = &[ "abacus", "abdomen", "abdominal", diff --git a/crates/bitwarden-crypto/uniffi.toml b/crates/bitwarden-crypto/uniffi.toml new file mode 100644 index 000000000..f5826906b --- /dev/null +++ b/crates/bitwarden-crypto/uniffi.toml @@ -0,0 +1,8 @@ +[bindings.kotlin] +package_name = "com.bitwarden.crypto" +generate_immutable_records = true + +[bindings.swift] +ffi_module_name = "BitwardenCryptoFFI" +module_name = "BitwardenCrypto" +generate_immutable_records = true diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 7fc87bb4b..eadaaf8d2 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -22,6 +22,9 @@ schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.25.2" bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0", features = [ + "mobile", +] } [build-dependencies] uniffi = { version = "=0.25.2", features = ["build"] } diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 1dc102b3e..f67aa3a02 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -1,10 +1,7 @@ use std::sync::Arc; -use bitwarden::{ - auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}, - client::kdf::Kdf, - crypto::HashPurpose, -}; +use bitwarden::auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}; +use bitwarden_crypto::{HashPurpose, Kdf}; use crate::{error::Result, Client}; diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index e7acbdcae..3ba0e061b 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,7 +1,5 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, - client::kdf::Kdf, - crypto::HashPurpose, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, platform::FingerprintRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, @@ -10,6 +8,7 @@ use bitwarden::{ TotpResponse, }, }; +use bitwarden_crypto::{HashPurpose, Kdf}; use schemars::JsonSchema; #[derive(JsonSchema)] diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index 72a67f698..a91e3de5f 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,4 +1,4 @@ -use bitwarden::crypto::EncString; +use bitwarden_crypto::EncString; // Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 79910bca4..d69279881 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -15,21 +15,21 @@ rust-version = "1.57" [features] default = ["secrets"] -secrets = [] # Secrets manager API -internal = [] # Internal testing methods -mobile = ["uniffi", "internal"] # Mobile-specific features +secrets = [] # Secrets manager API +internal = [] # Internal testing methods +mobile = [ + "uniffi", + "internal", + "bitwarden-crypto/mobile", +] # Mobile-specific features wasm-bindgen = ["chrono/wasmbind"] [dependencies] -aes = ">=0.8.2, <0.9" -argon2 = { version = ">=0.5.0, <0.6", features = [ - "alloc", -], default-features = false } base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } -cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", @@ -38,18 +38,12 @@ chrono = { version = ">=0.4.26, <0.5", features = [ data-encoding = ">=2.5.0, <3.0" # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } -hkdf = ">=0.12.3, <0.13" hmac = ">=0.12.1, <0.13" -lazy_static = ">=1.4.0, <2.0" log = ">=0.4.18, <0.5" -num-bigint = ">=0.4, <0.5" -num-traits = ">=0.2.15, <0.3" -pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = [ "json", ], default-features = false } -rsa = ">=0.9.2, <0.10" schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" @@ -57,7 +51,6 @@ serde_qs = ">=0.12.0, <0.13" serde_repr = ">=0.1.12, <0.2" sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" -subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.2", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 6c9ddbd4d..d4379d1eb 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -15,7 +15,7 @@ use crate::{ register::{make_register_keys, register}, RegisterKeyResponse, RegisterRequest, }, - client::kdf::Kdf, + client::Kdf, }; pub struct ClientAuth<'a> { @@ -70,9 +70,10 @@ impl<'a> ClientAuth<'a> { } pub async fn prelogin(&mut self, email: String) -> Result { - use crate::auth::login::request_prelogin; + use crate::auth::login::{parse_prelogin, request_prelogin}; - request_prelogin(self.client, email).await?.try_into() + let response = request_prelogin(self.client, email).await?; + parse_prelogin(response) } pub async fn login_password( diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 43418d5f1..e4cce33e4 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,6 +1,7 @@ use std::path::{Path, PathBuf}; use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; use chrono::Utc; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -13,7 +14,6 @@ use crate::{ JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, error::{Error, Result}, secrets_manager::state::{self, ClientState}, Client, diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index 9370559b4..e161ececd 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::EncString; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +9,6 @@ use crate::{ JWTToken, }, client::{LoginMethod, UserLoginMethod}, - crypto::EncString, error::Result, Client, }; diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index d2f66b569..afd7873a4 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -1,6 +1,6 @@ #[cfg(feature = "internal")] use { - crate::{client::Client, error::Result}, + crate::{client::Kdf, error::Result, Client}, bitwarden_api_identity::{ apis::accounts_api::accounts_prelogin_post, models::{PreloginRequestModel, PreloginResponseModel}, @@ -45,3 +45,40 @@ pub(crate) async fn request_prelogin( let config = client.get_api_configurations().await; Ok(accounts_prelogin_post(&config.identity, Some(request_model)).await?) } + +#[cfg(feature = "internal")] +pub(crate) fn parse_prelogin(response: PreloginResponseModel) -> Result { + use std::num::NonZeroU32; + + use bitwarden_api_identity::models::KdfType; + + use crate::util::{ + default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, + default_pbkdf2_iterations, + }; + + let kdf = response.kdf.ok_or("KDF not found")?; + + Ok(match kdf { + KdfType::Variant0 => Kdf::PBKDF2 { + iterations: response + .kdf_iterations + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_pbkdf2_iterations), + }, + KdfType::Variant1 => Kdf::Argon2id { + iterations: response + .kdf_iterations + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_iterations), + memory: response + .kdf_memory + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_memory), + parallelism: response + .kdf_parallelism + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_parallelism), + }, + }) +} diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 7a93c68e0..e5d579aa2 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -6,8 +6,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "internal")] use crate::{ auth::{api::request::PasswordTokenRequest, login::TwoFactorRequest}, - client::{kdf::Kdf, LoginMethod}, - crypto::EncString, + client::{Kdf, LoginMethod}, Client, }; use crate::{ @@ -23,7 +22,9 @@ pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { - use crate::{auth::determine_password_hash, client::UserLoginMethod, crypto::HashPurpose}; + use bitwarden_crypto::{EncString, HashPurpose}; + + use crate::{auth::determine_password_hash, client::UserLoginMethod}; info!("password logging in"); debug!("{:#?}, {:#?}", client, input); diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index cf3cb7907..45be042c7 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -1,9 +1,10 @@ use bitwarden_api_api::models::TwoFactorEmailRequestModel; +use bitwarden_crypto::HashPurpose; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{auth::determine_password_hash, crypto::HashPurpose, error::Result, Client}; +use crate::{auth::determine_password_hash, error::Result, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 49be82d1c..e80ab28cf 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -10,14 +10,12 @@ pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; #[cfg(feature = "internal")] +use bitwarden_crypto::{HashPurpose, MasterKey}; +#[cfg(feature = "internal")] pub use register::{RegisterKeyResponse, RegisterRequest}; #[cfg(feature = "internal")] -use crate::{ - client::kdf::Kdf, - crypto::{HashPurpose, MasterKey}, - error::Result, -}; +use crate::{client::Kdf, error::Result}; #[cfg(feature = "internal")] async fn determine_password_hash( @@ -27,7 +25,7 @@ async fn determine_password_hash( purpose: HashPurpose, ) -> Result { let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; - master_key.derive_master_key_hash(password.as_bytes(), purpose) + Ok(master_key.derive_master_key_hash(password.as_bytes(), purpose)?) } #[cfg(test)] diff --git a/crates/bitwarden/src/auth/password/validate.rs b/crates/bitwarden/src/auth/password/validate.rs index c86c1c40d..f6d22e11a 100644 --- a/crates/bitwarden/src/auth/password/validate.rs +++ b/crates/bitwarden/src/auth/password/validate.rs @@ -1,7 +1,8 @@ +use bitwarden_crypto::HashPurpose; + use crate::{ auth::determine_password_hash, client::{LoginMethod, UserLoginMethod}, - crypto::HashPurpose, error::{Error, Result}, Client, }; @@ -40,7 +41,7 @@ mod tests { use std::num::NonZeroU32; use super::validate_password; - use crate::client::{kdf::Kdf, Client, LoginMethod, UserLoginMethod}; + use crate::client::{Client, Kdf, LoginMethod, UserLoginMethod}; let mut client = Client::new(None); client.set_login_method(LoginMethod::User(UserLoginMethod::Username { diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 206c1905b..2b0c9503b 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -2,16 +2,11 @@ use bitwarden_api_identity::{ apis::accounts_api::accounts_register_post, models::{KeysRequestModel, RegisterRequestModel}, }; +use bitwarden_crypto::{HashPurpose, MasterKey, RsaKeyPair}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - client::kdf::Kdf, - crypto::{HashPurpose, MasterKey, RsaKeyPair}, - error::Result, - util::default_pbkdf2_iterations, - Client, -}; +use crate::{client::Kdf, error::Result, util::default_pbkdf2_iterations, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index 854922c14..4a6d5ed8c 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -1,13 +1,10 @@ use std::{fmt::Debug, str::FromStr}; use base64::Engine; +use bitwarden_crypto::{derive_shareable_key, SymmetricCryptoKey}; use uuid::Uuid; -use crate::{ - crypto::{derive_shareable_key, SymmetricCryptoKey}, - error::AccessTokenInvalidError, - util::STANDARD_INDIFFERENT, -}; +use crate::{error::AccessTokenInvalidError, util::STANDARD_INDIFFERENT}; pub struct AccessToken { pub access_token_id: Uuid, diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 2c5d9b387..34d99c0a3 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,10 @@ use std::path::PathBuf; +#[cfg(feature = "internal")] +pub use bitwarden_crypto::Kdf; +use bitwarden_crypto::SymmetricCryptoKey; +#[cfg(feature = "internal")] +use bitwarden_crypto::{AsymmEncString, EncString}; use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -8,20 +13,15 @@ use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] -use crate::{ - client::kdf::Kdf, - crypto::{AsymmEncString, EncString}, - platform::{ - get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, - UserApiKeyResponse, - }, +use crate::platform::{ + get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, + UserApiKeyResponse, }; use crate::{ client::{ client_settings::{ClientSettings, DeviceType}, encryption_settings::EncryptionSettings, }, - crypto::SymmetricCryptoKey, error::{Error, Result}, }; @@ -255,7 +255,7 @@ impl Client { pin_protected_user_key: EncString, private_key: EncString, ) -> Result<&EncryptionSettings> { - use crate::crypto::MasterKey; + use bitwarden_crypto::MasterKey; let pin_key = match &self.login_method { Some(LoginMethod::User( diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 1a662adfb..612449cbd 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,14 +1,12 @@ use std::collections::HashMap; #[cfg(feature = "internal")] -use crate::{ - client::UserLoginMethod, - crypto::{AsymmEncString, EncString, KeyDecryptable}, - error::Result, -}; +use bitwarden_crypto::{AsymmEncString, EncString}; +use bitwarden_crypto::{AsymmetricCryptoKey, KeyContainer, SymmetricCryptoKey}; use uuid::Uuid; -use crate::crypto::{AsymmetricCryptoKey, SymmetricCryptoKey}; +#[cfg(feature = "internal")] +use crate::{client::UserLoginMethod, error::Result}; pub struct EncryptionSettings { user_key: SymmetricCryptoKey, @@ -31,7 +29,7 @@ impl EncryptionSettings { user_key: EncString, private_key: EncString, ) -> Result { - use crate::crypto::MasterKey; + use bitwarden_crypto::MasterKey; match login_method { UserLoginMethod::Username { email, kdf, .. } @@ -55,6 +53,8 @@ impl EncryptionSettings { user_key: SymmetricCryptoKey, private_key: EncString, ) -> Result { + use bitwarden_crypto::KeyDecryptable; + let private_key = { let dec: Vec = private_key.decrypt_with_key(&user_key)?; Some(AsymmetricCryptoKey::from_der(&dec)?) @@ -82,6 +82,8 @@ impl EncryptionSettings { &mut self, org_enc_keys: Vec<(Uuid, AsymmEncString)>, ) -> Result<&mut Self> { + use bitwarden_crypto::KeyDecryptable; + use crate::error::Error; let private_key = self.private_key.as_ref().ok_or(Error::VaultLocked)?; @@ -114,3 +116,9 @@ impl EncryptionSettings { } } } + +impl KeyContainer for EncryptionSettings { + fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { + EncryptionSettings::get_key(self, org_id) + } +} diff --git a/crates/bitwarden/src/client/kdf.rs b/crates/bitwarden/src/client/kdf.rs deleted file mode 100644 index 2f6787d8d..000000000 --- a/crates/bitwarden/src/client/kdf.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::num::NonZeroU32; - -#[cfg(feature = "internal")] -use bitwarden_api_identity::models::{KdfType, PreloginResponseModel}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -#[cfg(feature = "internal")] -use crate::error::{Error, Result}; - -#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] -pub enum Kdf { - PBKDF2 { - iterations: NonZeroU32, - }, - Argon2id { - iterations: NonZeroU32, - memory: NonZeroU32, - parallelism: NonZeroU32, - }, -} - -#[cfg(feature = "internal")] -impl TryFrom for Kdf { - type Error = Error; - - fn try_from(response: PreloginResponseModel) -> Result { - use crate::util::{ - default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, - default_pbkdf2_iterations, - }; - - let kdf = response.kdf.ok_or("KDF not found")?; - - Ok(match kdf { - KdfType::Variant0 => Kdf::PBKDF2 { - iterations: response - .kdf_iterations - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_pbkdf2_iterations), - }, - KdfType::Variant1 => Kdf::Argon2id { - iterations: response - .kdf_iterations - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_iterations), - memory: response - .kdf_memory - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_memory), - parallelism: response - .kdf_parallelism - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_parallelism), - }, - }) - } -} diff --git a/crates/bitwarden/src/client/mod.rs b/crates/bitwarden/src/client/mod.rs index 25a2f5db0..c3719fce2 100644 --- a/crates/bitwarden/src/client/mod.rs +++ b/crates/bitwarden/src/client/mod.rs @@ -6,7 +6,6 @@ pub(crate) mod access_token; mod client; pub mod client_settings; pub(crate) mod encryption_settings; -pub mod kdf; pub use access_token::AccessToken; pub use client::Client; diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs deleted file mode 100644 index f21fdb256..000000000 --- a/crates/bitwarden/src/crypto/mod.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! # Cryptographic primitives -//! -//! This module contains the cryptographic primitives used throughout the SDK. The module makes a -//! best effort to abstract away cryptographic concepts into concepts such as -//! [`EncString`], [`SymmetricCryptoKey`] and [`AsymmetricCryptoKey`]. -//! -//! ## Conventions: -//! -//! - Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`. -//! - Functions that generate new keys are prefixed with `make_`. -//! -//! ## Differences from [`clients`](https://github.com/bitwarden/clients) -//! -//! There are some noteworthy differences compared to the other Bitwarden clients. These changes -//! are made in an effort to introduce conventions in how we name things, improve best practices -//! and abstracting away internal complexity. -//! -//! - `CryptoService.makeSendKey` & `AccessService.createAccessToken` are replaced by the generic -//! `derive_shareable_key` -//! - MasterKey operations such as `makeMasterKey` and `hashMasterKey` are moved to the MasterKey -//! struct. -//! - -use aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; -use hmac::digest::OutputSizeUser; -#[cfg(any(test, feature = "internal"))] -use rand::{ - distributions::{Distribution, Standard}, - Rng, -}; - -use crate::error::Result; - -mod enc_string; -pub use enc_string::{AsymmEncString, EncString}; -mod encryptable; -pub use encryptable::{Decryptable, Encryptable, LocateKey}; -mod key_encryptable; -pub use key_encryptable::{CryptoKey, KeyDecryptable, KeyEncryptable}; -mod aes_ops; -use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; -mod symmetric_crypto_key; -pub use symmetric_crypto_key::SymmetricCryptoKey; -mod asymmetric_crypto_key; -pub use asymmetric_crypto_key::AsymmetricCryptoKey; - -mod shareable_key; -pub(crate) use shareable_key::derive_shareable_key; - -#[cfg(feature = "internal")] -mod master_key; -#[cfg(feature = "internal")] -pub use master_key::HashPurpose; -#[cfg(feature = "internal")] -pub(crate) use master_key::MasterKey; -#[cfg(feature = "internal")] -mod user_key; -#[cfg(feature = "internal")] -pub(crate) use user_key::UserKey; -#[cfg(feature = "internal")] -mod rsa; -#[cfg(feature = "internal")] -pub use self::rsa::RsaKeyPair; - -#[cfg(feature = "internal")] -mod fingerprint; -#[cfg(feature = "internal")] -pub(crate) use fingerprint::fingerprint; - -pub(crate) type PbkdfSha256Hmac = hmac::Hmac; -pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = - <::OutputSize as Unsigned>::USIZE; - -/// RFC5869 HKDF-Expand operation -fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result> { - let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| "invalid prk length")?; - let mut key = GenericArray::::default(); - - let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); - hkdf.expand(i, &mut key).map_err(|_| "invalid length")?; - - Ok(key) -} - -/// Generate random bytes that are cryptographically secure -#[cfg(any(test, feature = "internal"))] -pub(crate) fn generate_random_bytes() -> T -where - Standard: Distribution, -{ - rand::thread_rng().gen() -} - -pub fn pbkdf2(password: &[u8], salt: &[u8], rounds: u32) -> [u8; PBKDF_SHA256_HMAC_OUT_SIZE] { - pbkdf2::pbkdf2_array::(password, salt, rounds) - .expect("hash is a valid fixed size") -} diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs deleted file mode 100644 index 7f5bae413..000000000 --- a/crates/bitwarden/src/crypto/user_key.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::{ - crypto::{ - rsa::{make_key_pair, RsaKeyPair}, - SymmetricCryptoKey, - }, - error::Result, -}; - -pub(crate) struct UserKey(pub(super) SymmetricCryptoKey); - -impl UserKey { - pub(crate) fn new(key: SymmetricCryptoKey) -> Self { - Self(key) - } - - pub(crate) fn make_key_pair(&self) -> Result { - make_key_pair(&self.0) - } -} diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 48cb7da16..627e92e78 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -24,10 +24,7 @@ pub enum Error { MissingFields, #[error("Cryptography error, {0}")] - Crypto(#[from] CryptoError), - - #[error("Error parsing EncString: {0}")] - InvalidEncString(#[from] EncStringParseError), + Crypto(#[from] bitwarden_crypto::CryptoError), #[error("Error parsing Identity response: {0}")] IdentityFail(crate::auth::api::response::IdentityTokenFailResponse), @@ -86,38 +83,6 @@ pub enum AccessTokenInvalidError { InvalidBase64Length { expected: usize, got: usize }, } -#[derive(Debug, Error)] -pub enum CryptoError { - #[error("The provided key is not the expected type")] - InvalidKey, - #[error("The cipher's MAC doesn't match the expected value")] - InvalidMac, - #[error("Error while decrypting EncString")] - KeyDecrypt, - #[error("The cipher key has an invalid length")] - InvalidKeyLen, - #[error("There is no encryption key for the provided organization")] - NoKeyForOrg, - #[error("The value is not a valid UTF8 String")] - InvalidUtf8String, - #[error("Missing key")] - MissingKey, -} - -#[derive(Debug, Error)] -pub enum EncStringParseError { - #[error("No type detected, missing '.' separator")] - NoType, - #[error("Invalid symmetric type, got type {enc_type} with {parts} parts")] - InvalidTypeSymm { enc_type: String, parts: usize }, - #[error("Invalid asymmetric type, got type {enc_type} with {parts} parts")] - InvalidTypeAsymm { enc_type: String, parts: usize }, - #[error("Error decoding base64: {0}")] - InvalidBase64(#[from] base64::DecodeError), - #[error("Invalid length: expected {expected}, got {got}")] - InvalidLength { expected: usize, got: usize }, -} - // Ensure that the error messages implement Send and Sync #[cfg(test)] const _: () = { diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index a8dd60399..a0a1c1b95 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -55,7 +55,6 @@ uniffi::setup_scaffolding!(); pub mod admin_console; pub mod auth; pub mod client; -pub mod crypto; pub mod error; #[cfg(feature = "mobile")] pub mod mobile; @@ -70,7 +69,6 @@ pub(crate) mod uniffi_support; mod util; #[cfg(feature = "internal")] pub mod vault; -pub mod wordlist; pub use client::Client; diff --git a/crates/bitwarden/src/mobile/client_kdf.rs b/crates/bitwarden/src/mobile/client_kdf.rs index 6b895f78a..4e62e5d59 100644 --- a/crates/bitwarden/src/mobile/client_kdf.rs +++ b/crates/bitwarden/src/mobile/client_kdf.rs @@ -1,6 +1,6 @@ -use crate::{ - client::kdf::Kdf, crypto::HashPurpose, error::Result, mobile::kdf::hash_password, Client, -}; +use bitwarden_crypto::HashPurpose; + +use crate::{client::Kdf, error::Result, mobile::kdf::hash_password, Client}; pub struct ClientKdf<'a> { pub(crate) client: &'a crate::Client, diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index ca5dea703..8894b19db 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; +use bitwarden_crypto::{AsymmEncString, EncString}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - client::kdf::Kdf, - crypto::{AsymmEncString, EncString}, + client::Kdf, error::{Error, Result}, Client, }; @@ -50,7 +50,7 @@ pub enum InitUserCryptoMethod { #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { - use crate::crypto::SymmetricCryptoKey; + use bitwarden_crypto::SymmetricCryptoKey; let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), @@ -118,10 +118,9 @@ pub struct DerivePinKeyResponse { #[cfg(feature = "internal")] pub fn derive_pin_key(client: &mut Client, pin: String) -> Result { - use crate::{ - client::{LoginMethod, UserLoginMethod}, - crypto::{KeyEncryptable, MasterKey}, - }; + use bitwarden_crypto::{KeyEncryptable, MasterKey}; + + use crate::client::{LoginMethod, UserLoginMethod}; let derived_key = match &client.login_method { Some(LoginMethod::User( @@ -145,7 +144,7 @@ pub fn derive_pin_key(client: &mut Client, pin: String) -> Result Result { let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf_params)?; - master_key.derive_master_key_hash(password.as_bytes(), purpose) + Ok(master_key.derive_master_key_hash(password.as_bytes(), purpose)?) } diff --git a/crates/bitwarden/src/mobile/vault/client_ciphers.rs b/crates/bitwarden/src/mobile/vault/client_ciphers.rs index 87b77cfd5..4e34021ee 100644 --- a/crates/bitwarden/src/mobile/vault/client_ciphers.rs +++ b/crates/bitwarden/src/mobile/vault/client_ciphers.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{Cipher, CipherListView, CipherView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_collection.rs b/crates/bitwarden/src/mobile/vault/client_collection.rs index 80535406c..9cb5d1711 100644 --- a/crates/bitwarden/src/mobile/vault/client_collection.rs +++ b/crates/bitwarden/src/mobile/vault/client_collection.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::Decryptable; + use super::client_vault::ClientVault; use crate::{ - crypto::Decryptable, error::Result, vault::{Collection, CollectionView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_folders.rs b/crates/bitwarden/src/mobile/vault/client_folders.rs index b6f6a72f4..fec3ad7db 100644 --- a/crates/bitwarden/src/mobile/vault/client_folders.rs +++ b/crates/bitwarden/src/mobile/vault/client_folders.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{Folder, FolderView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_password_history.rs b/crates/bitwarden/src/mobile/vault/client_password_history.rs index d873f8dfc..99727232b 100644 --- a/crates/bitwarden/src/mobile/vault/client_password_history.rs +++ b/crates/bitwarden/src/mobile/vault/client_password_history.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{PasswordHistory, PasswordHistoryView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index b1de05f44..45d9a7825 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -1,8 +1,9 @@ use std::path::Path; +use bitwarden_crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}, error::{Error, Result}, vault::{Send, SendListView, SendView}, Client, @@ -47,7 +48,7 @@ impl<'a> ClientSends<'a> { let key = Send::get_key(&send.key, key)?; let buf = EncString::from_buffer(encrypted_buffer)?; - buf.decrypt_with_key(&key) + Ok(buf.decrypt_with_key(&key)?) } pub async fn encrypt(&self, send_view: SendView) -> Result { @@ -79,7 +80,7 @@ impl<'a> ClientSends<'a> { let key = Send::get_key(&send.key, key)?; let enc = buffer.encrypt_with_key(&key)?; - enc.to_buffer() + Ok(enc.to_buffer()?) } } diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs index 75bfd204c..1d4ffd486 100644 --- a/crates/bitwarden/src/mobile/vault/client_totp.rs +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -1,9 +1,10 @@ use chrono::{DateTime, Utc}; -use crate::error::Result; -use crate::vault::{generate_totp, TotpResponse}; - use super::client_vault::ClientVault; +use crate::{ + error::Result, + vault::{generate_totp, TotpResponse}, +}; impl<'a> ClientVault<'a> { /// Generate a TOTP code from a provided key. diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index 1826e195f..59d81d652 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -1,9 +1,10 @@ use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::fingerprint; use log::info; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{crypto::fingerprint, error::Result}; +use crate::error::Result; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -53,13 +54,12 @@ pub(crate) fn generate_user_fingerprint( mod tests { use std::num::NonZeroU32; + use super::*; use crate::{ - client::{kdf::Kdf, LoginMethod, UserLoginMethod}, + client::{Kdf, LoginMethod, UserLoginMethod}, Client, }; - use super::*; - #[test] fn test_generate_user_fingerprint() { let user_key = "2.oZg5RYpU2HjUAKI1DUQCkg==|PyRzI9kZpt66P2OedH8CHOeU0/lgKLkhIJiKDijdyFqIemBSIBoslhfQh/P1TK9xgZp0smgD6+5+yNbZfOpBaCVrsT3WWAO78xOWizduRe4=|xfDLDZSJ+yZAdh388flVg7SMDBJuMs0+CHTjutKs4uQ="; diff --git a/crates/bitwarden/src/platform/get_user_api_key.rs b/crates/bitwarden/src/platform/get_user_api_key.rs index 994a7a7ab..2eaa21894 100644 --- a/crates/bitwarden/src/platform/get_user_api_key.rs +++ b/crates/bitwarden/src/platform/get_user_api_key.rs @@ -2,6 +2,7 @@ use bitwarden_api_api::{ apis::accounts_api::accounts_api_key_post, models::{ApiKeyResponseModel, SecretVerificationRequestModel}, }; +use bitwarden_crypto::{HashPurpose, MasterKey}; use log::{debug, info}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -9,7 +10,6 @@ use serde::{Deserialize, Serialize}; use super::SecretVerificationRequest; use crate::{ client::{LoginMethod, UserLoginMethod}, - crypto::{HashPurpose, MasterKey}, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/secrets_manager/projects/create.rs b/crates/bitwarden/src/secrets_manager/projects/create.rs index 996a3463e..ab3b7bd62 100644 --- a/crates/bitwarden/src/secrets_manager/projects/create.rs +++ b/crates/bitwarden/src/secrets_manager/projects/create.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectCreateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::ProjectResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/projects/project_response.rs b/crates/bitwarden/src/secrets_manager/projects/project_response.rs index b8c82806b..1e6f6a158 100644 --- a/crates/bitwarden/src/secrets_manager/projects/project_response.rs +++ b/crates/bitwarden/src/secrets_manager/projects/project_response.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectResponseModel; +use bitwarden_crypto::{Decryptable, EncString}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -6,7 +7,6 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/projects/update.rs b/crates/bitwarden/src/secrets_manager/projects/update.rs index 6a0479d88..e00609ff4 100644 --- a/crates/bitwarden/src/secrets_manager/projects/update.rs +++ b/crates/bitwarden/src/secrets_manager/projects/update.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectUpdateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::ProjectResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/create.rs b/crates/bitwarden/src/secrets_manager/secrets/create.rs index a1bb81799..4f84223dc 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/create.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/create.rs @@ -1,11 +1,11 @@ use bitwarden_api_api::models::SecretCreateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; use crate::{ - crypto::KeyEncryptable, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/list.rs b/crates/bitwarden/src/secrets_manager/secrets/list.rs index 1f4ccba3f..7fa46d164 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/list.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/list.rs @@ -1,13 +1,13 @@ use bitwarden_api_api::models::{ SecretWithProjectsListResponseModel, SecretsWithProjectsInnerSecret, }; +use bitwarden_crypto::{Decryptable, EncString}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ client::{encryption_settings::EncryptionSettings, Client}, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs index a7fe49200..fe1a4d342 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs @@ -1,6 +1,7 @@ use bitwarden_api_api::models::{ BaseSecretResponseModel, BaseSecretResponseModelListResponseModel, SecretResponseModel, }; +use bitwarden_crypto::{Decryptable, EncString}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +9,6 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/update.rs b/crates/bitwarden/src/secrets_manager/secrets/update.rs index 970812c5a..f9e54f810 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/update.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/update.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::SecretUpdateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::SecretResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/state.rs b/crates/bitwarden/src/secrets_manager/state.rs index d39603d34..4efa4403b 100644 --- a/crates/bitwarden/src/secrets_manager/state.rs +++ b/crates/bitwarden/src/secrets_manager/state.rs @@ -1,11 +1,12 @@ +use std::{fmt::Debug, path::Path}; + +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable}; use serde::{Deserialize, Serialize}; use crate::{ client::AccessToken, - crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::{Error, Result}, }; -use std::{fmt::Debug, path::Path}; const STATE_VERSION: u32 = 1; diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden/src/tool/generators/passphrase.rs index 7c5c8e434..f64b39dc2 100644 --- a/crates/bitwarden/src/tool/generators/passphrase.rs +++ b/crates/bitwarden/src/tool/generators/passphrase.rs @@ -1,8 +1,10 @@ -use crate::{error::Result, util::capitalize_first_letter, wordlist::EFF_LONG_WORD_LIST}; +use bitwarden_crypto::EFF_LONG_WORD_LIST; use rand::{seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::{error::Result, util::capitalize_first_letter}; + /// Passphrase generator request options. #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] diff --git a/crates/bitwarden/src/tool/generators/username.rs b/crates/bitwarden/src/tool/generators/username.rs index 666772714..20b101fa0 100644 --- a/crates/bitwarden/src/tool/generators/username.rs +++ b/crates/bitwarden/src/tool/generators/username.rs @@ -1,8 +1,10 @@ -use crate::{error::Result, util::capitalize_first_letter, wordlist::EFF_LONG_WORD_LIST}; +use bitwarden_crypto::EFF_LONG_WORD_LIST; use rand::{distributions::Distribution, seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::{error::Result, util::capitalize_first_letter}; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -84,9 +86,10 @@ impl ForwarderServiceType { // Generate a username using the specified email forwarding service // This requires an HTTP client to be passed in, as the service will need to make API calls pub async fn generate(self, http: &reqwest::Client, website: Option) -> Result { - use crate::tool::generators::username_forwarders::*; use ForwarderServiceType::*; + use crate::tool::generators::username_forwarders::*; + match self { AddyIo { api_token, diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 795aa9f50..fb7650d36 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,40 +1,12 @@ use std::{num::NonZeroU32, str::FromStr}; +use bitwarden_crypto::{AsymmEncString, EncString}; use uuid::Uuid; -use crate::{ - crypto::{AsymmEncString, EncString}, - error::Error, - UniffiCustomTypeConverter, -}; +use crate::UniffiCustomTypeConverter; -uniffi::custom_type!(NonZeroU32, u32); - -impl UniffiCustomTypeConverter for NonZeroU32 { - type Builtin = u32; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::new(val).ok_or(Error::from("Number is zero").into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.get() - } -} - -uniffi::custom_type!(EncString, String); - -impl UniffiCustomTypeConverter for EncString { - type Builtin = String; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::from_str(&val).map_err(|e| e.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.to_string() - } -} +uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); +uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::custom_type!(AsymmEncString, String); diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index c22997c83..fa4a35fc7 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,10 +1,10 @@ +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -32,7 +32,7 @@ pub struct AttachmentView { } impl KeyEncryptable for AttachmentView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, url: self.url, @@ -45,7 +45,7 @@ impl KeyEncryptable for AttachmentView { } impl KeyDecryptable for Attachment { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index c0f97e1df..05c3aa631 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,11 +1,11 @@ use bitwarden_api_api::models::CipherCardModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -32,7 +32,7 @@ pub struct CardView { } impl KeyEncryptable for CardView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { cardholder_name: self.cardholder_name.encrypt_with_key(key)?, exp_month: self.exp_month.encrypt_with_key(key)?, @@ -45,7 +45,7 @@ impl KeyEncryptable for CardView { } impl KeyDecryptable for Card { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { cardholder_name: self.cardholder_name.decrypt_with_key(key)?, exp_month: self.exp_month.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index d36855a19..07d8da226 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,4 +1,8 @@ use bitwarden_api_api::models::CipherDetailsResponseModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -11,8 +15,6 @@ use super::{ login, secure_note, }; use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, error::{Error, Result}, vault::password_history, }; @@ -136,7 +138,7 @@ pub struct CipherListView { } impl KeyEncryptable for CipherView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -170,7 +172,7 @@ impl KeyEncryptable for CipherView { } impl KeyDecryptable for Cipher { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -211,7 +213,7 @@ impl Cipher { fn get_cipher_key( key: &SymmetricCryptoKey, ciphers_key: &Option, - ) -> Result> { + ) -> Result, CryptoError> { ciphers_key .as_ref() .map(|k| { @@ -221,7 +223,7 @@ impl Cipher { .transpose() } - fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { @@ -287,7 +289,7 @@ impl Cipher { } impl KeyDecryptable for Cipher { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -318,7 +320,7 @@ impl KeyDecryptable for Cipher { impl LocateKey for Cipher { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&self.organization_id) @@ -327,7 +329,7 @@ impl LocateKey for Cipher { impl LocateKey for CipherView { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&self.organization_id) diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index bf9352d68..6bb106c32 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,13 +1,13 @@ use bitwarden_api_api::models::CipherFieldModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use super::linked_id::LinkedIdType; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -42,7 +42,7 @@ pub struct FieldView { } impl KeyEncryptable for FieldView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { name: self.name.encrypt_with_key(key)?, value: self.value.encrypt_with_key(key)?, @@ -53,7 +53,7 @@ impl KeyEncryptable for FieldView { } impl KeyDecryptable for Field { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { name: self.name.decrypt_with_key(key)?, value: self.value.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index c3082ccc9..c4154aeba 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,11 +1,11 @@ use bitwarden_api_api::models::CipherIdentityModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -56,7 +56,7 @@ pub struct IdentityView { } impl KeyEncryptable for IdentityView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { title: self.title.encrypt_with_key(key)?, first_name: self.first_name.encrypt_with_key(key)?, @@ -81,7 +81,7 @@ impl KeyEncryptable for IdentityView { } impl KeyDecryptable for Identity { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { title: self.title.decrypt_with_key(key)?, first_name: self.first_name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index a3d0bf519..6a85512c2 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,11 +1,7 @@ +use bitwarden_crypto::{CryptoError, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -23,7 +19,7 @@ pub struct LocalDataView { } impl KeyEncryptable for LocalDataView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -32,7 +28,7 @@ impl KeyEncryptable for LocalDataView { } impl KeyDecryptable for LocalData { - fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 8342fba53..139750d51 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,13 +1,13 @@ use bitwarden_api_api::models::{CipherLoginModel, CipherLoginUriModel}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -65,7 +65,7 @@ pub struct LoginView { } impl KeyEncryptable for LoginUriView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, @@ -74,7 +74,7 @@ impl KeyEncryptable for LoginUriView { } impl KeyEncryptable for LoginView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { username: self.username.encrypt_with_key(key)?, password: self.password.encrypt_with_key(key)?, @@ -87,7 +87,7 @@ impl KeyEncryptable for LoginView { } impl KeyDecryptable for LoginUri { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, @@ -96,7 +96,7 @@ impl KeyDecryptable for LoginUri { } impl KeyDecryptable for Login { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { username: self.username.decrypt_with_key(key)?, password: self.password.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index ee24b74b3..8f7069ee1 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,12 +1,10 @@ use bitwarden_api_api::models::CipherSecureNoteModel; +use bitwarden_crypto::{CryptoError, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{ - crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -30,7 +28,7 @@ pub struct SecureNoteView { } impl KeyEncryptable for SecureNoteView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, }) @@ -38,7 +36,7 @@ impl KeyEncryptable for SecureNoteView { } impl KeyDecryptable for SecureNote { - fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 8b39a9d22..a78209fc9 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,13 +1,12 @@ use bitwarden_api_api::models::CollectionDetailsResponseModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyContainer, KeyDecryptable, LocateKey, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -40,14 +39,14 @@ pub struct CollectionView { impl LocateKey for Collection { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&Some(self.organization_id)) } } impl KeyDecryptable for Collection { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index f41e0e2b0..a6b9790bc 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,13 +1,13 @@ use bitwarden_api_api::models::FolderResponseModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] @@ -29,7 +29,7 @@ pub struct FolderView { impl LocateKey for FolderView {} impl KeyEncryptable for FolderView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, name: self.name.encrypt_with_key(key)?, @@ -40,7 +40,7 @@ impl KeyEncryptable for FolderView { impl LocateKey for Folder {} impl KeyDecryptable for Folder { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, name: self.name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 4475f1cff..333420b6a 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,12 +1,12 @@ use bitwarden_api_api::models::CipherPasswordHistoryModel; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, - error::{Error, Result}, -}; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -26,7 +26,7 @@ pub struct PasswordHistoryView { impl LocateKey for PasswordHistoryView {} impl KeyEncryptable for PasswordHistoryView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, @@ -36,7 +36,10 @@ impl KeyEncryptable for PasswordHistoryView impl LocateKey for PasswordHistory {} impl KeyDecryptable for PasswordHistory { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + key: &SymmetricCryptoKey, + ) -> Result { Ok(PasswordHistoryView { password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 742d3c592..8ed405b4c 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -3,19 +3,17 @@ use base64::{ Engine, }; use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; +use bitwarden_crypto::{ + derive_shareable_key, generate_random_bytes, CryptoError, EncString, KeyDecryptable, + KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; -use crate::{ - crypto::{ - derive_shareable_key, generate_random_bytes, EncString, KeyDecryptable, KeyEncryptable, - LocateKey, SymmetricCryptoKey, - }, - error::{CryptoError, Error, Result}, -}; +use crate::error::{Error, Result}; const SEND_ITERATIONS: u32 = 100_000; @@ -145,19 +143,19 @@ impl Send { pub(crate) fn get_key( send_key: &EncString, enc_key: &SymmetricCryptoKey, - ) -> Result { + ) -> Result { let key: Vec = send_key.decrypt_with_key(enc_key)?; Self::derive_shareable_key(&key) } - fn derive_shareable_key(key: &[u8]) -> Result { + fn derive_shareable_key(key: &[u8]) -> Result { let key = key.try_into().map_err(|_| CryptoError::InvalidKeyLen)?; Ok(derive_shareable_key(key, "send", Some("send"))) } } impl KeyDecryptable for SendText { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { text: self.text.decrypt_with_key(key)?, hidden: self.hidden, @@ -166,7 +164,7 @@ impl KeyDecryptable for SendText { } impl KeyEncryptable for SendTextView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { text: self.text.encrypt_with_key(key)?, hidden: self.hidden, @@ -175,7 +173,7 @@ impl KeyEncryptable for SendTextView { } impl KeyDecryptable for SendFile { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), file_name: self.file_name.decrypt_with_key(key)?, @@ -186,7 +184,7 @@ impl KeyDecryptable for SendFile { } impl KeyEncryptable for SendFileView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), file_name: self.file_name.encrypt_with_key(key)?, @@ -198,7 +196,7 @@ impl KeyEncryptable for SendFileView { impl LocateKey for Send {} impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let k: Vec = self.key.decrypt_with_key(key)?; @@ -231,7 +229,7 @@ impl KeyDecryptable for Send { } impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; @@ -254,7 +252,7 @@ impl KeyDecryptable for Send { impl LocateKey for SendView {} impl KeyEncryptable for SendView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let k = match (self.key, self.id) { @@ -268,7 +266,7 @@ impl KeyEncryptable for SendView { key.to_vec() } // Existing send without key - _ => return Err(CryptoError::InvalidKey.into()), + _ => return Err(CryptoError::InvalidKey), }; let send_key = Send::derive_shareable_key(&k)?; @@ -280,7 +278,7 @@ impl KeyEncryptable for SendView { notes: self.notes.encrypt_with_key(&send_key)?, key: k.encrypt_with_key(key)?, password: self.new_password.map(|password| { - let password = crate::crypto::pbkdf2(password.as_bytes(), &k, SEND_ITERATIONS); + let password = bitwarden_crypto::pbkdf2(password.as_bytes(), &k, SEND_ITERATIONS); STANDARD.encode(password) }), @@ -360,10 +358,11 @@ impl TryFrom for SendText { #[cfg(test)] mod tests { + use bitwarden_crypto::{KeyDecryptable, KeyEncryptable}; + use super::{Send, SendText, SendTextView, SendType}; use crate::{ - client::{encryption_settings::EncryptionSettings, kdf::Kdf, UserLoginMethod}, - crypto::{KeyDecryptable, KeyEncryptable}, + client::{encryption_settings::EncryptionSettings, Kdf, UserLoginMethod}, vault::SendView, }; diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 6e863d57b..223c8c504 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -1,6 +1,5 @@ use std::{collections::HashMap, str::FromStr}; -use crate::error::{Error, Result}; use chrono::{DateTime, Utc}; use data_encoding::BASE32_NOPAD; use hmac::{Hmac, Mac}; @@ -8,6 +7,8 @@ use reqwest::Url; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::error::{Error, Result}; + type HmacSha1 = Hmac; type HmacSha256 = Hmac; type HmacSha512 = Hmac; @@ -221,9 +222,10 @@ fn derive_binary(hash: Vec) -> u32 { #[cfg(test)] mod tests { - use super::*; use chrono::Utc; + use super::*; + #[test] fn test_generate_totp() { let cases = vec![ diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs index 956fe86ce..8e523e26f 100644 --- a/crates/bitwarden/tests/register.rs +++ b/crates/bitwarden/tests/register.rs @@ -5,10 +5,10 @@ async fn test_register_initialize_crypto() { use std::num::NonZeroU32; use bitwarden::{ - client::kdf::Kdf, mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, Client, }; + use bitwarden_crypto::Kdf; let mut client = Client::new(None); diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index c38c14a07..dd79ff870 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -24,12 +24,12 @@ import androidx.compose.ui.unit.dp import androidx.fragment.app.FragmentActivity import com.bitwarden.core.DateTime import com.bitwarden.core.Folder -import com.bitwarden.core.HashPurpose import com.bitwarden.core.InitOrgCryptoRequest import com.bitwarden.core.InitUserCryptoMethod import com.bitwarden.core.InitUserCryptoRequest import com.bitwarden.core.Kdf import com.bitwarden.core.Uuid +import com.bitwarden.crypto.HashPurpose import com.bitwarden.myapplication.ui.theme.MyApplicationTheme import com.bitwarden.sdk.Client import io.ktor.client.HttpClient diff --git a/languages/swift/build.sh b/languages/swift/build.sh index 69da98415..87f9cecdb 100755 --- a/languages/swift/build.sh +++ b/languages/swift/build.sh @@ -28,14 +28,16 @@ cargo run -p uniffi-bindgen generate \ --out-dir tmp/bindings # Move generated swift bindings -mv ./tmp/bindings/BitwardenSDK.swift ./Sources/BitwardenSdk/ mv ./tmp/bindings/BitwardenCore.swift ./Sources/BitwardenSdk/ +mv ./tmp/bindings/BitwardenCrypto.swift ./Sources/BitwardenSdk/ +mv ./tmp/bindings/BitwardenSDK.swift ./Sources/BitwardenSdk/ # Massage the generated files to fit xcframework mkdir tmp/Headers -mv ./tmp/bindings/BitwardenFFI.h ./tmp/Headers/ mv ./tmp/bindings/BitwardenCoreFFI.h ./tmp/Headers/ -cat ./tmp/bindings/BitwardenFFI.modulemap ./tmp/bindings/BitwardenCoreFFI.modulemap > ./tmp/Headers/module.modulemap +mv ./tmp/bindings/BitwardenCryptoFFI.h ./tmp/Headers/ +mv ./tmp/bindings/BitwardenFFI.h ./tmp/Headers/ +cat ./tmp/bindings/BitwardenFFI.modulemap ./tmp/bindings/BitwardenCoreFFI.modulemap ./tmp/bindings/BitwardenCryptoFFI.modulemap > ./tmp/Headers/module.modulemap # Build xcframework xcodebuild -create-xcframework \ From a1e57c14ad200da613c21bd323be316f5e511700 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 15 Jan 2024 16:43:20 +0100 Subject: [PATCH 197/378] Add derive_pin_user_key (#508) Adds support for using pin when require master password is enabled. --- crates/bitwarden-uniffi/src/crypto.rs | 13 +++ crates/bitwarden/src/mobile/client_crypto.rs | 12 ++- crates/bitwarden/src/mobile/crypto.rs | 102 ++++++++++++++++--- languages/kotlin/doc.md | 35 ++++++- 4 files changed, 140 insertions(+), 22 deletions(-) diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 25d577ba5..e54aae435 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use bitwarden::mobile::crypto::{ DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, }; +use bitwarden_crypto::EncString; use crate::{error::Result, Client}; @@ -53,4 +54,16 @@ impl ClientCrypto { pub async fn derive_pin_key(&self, pin: String) -> Result { Ok(self.0 .0.write().await.crypto().derive_pin_key(pin).await?) } + + /// Derives the pin protected user key from encrypted pin. Used when pin requires master password on first unlock. + pub async fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .derive_pin_user_key(encrypted_pin) + .await?) + } } diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index cddb7c140..6f8887002 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -1,10 +1,13 @@ +#[cfg(feature = "internal")] +use bitwarden_crypto::EncString; + use crate::Client; #[cfg(feature = "internal")] use crate::{ error::Result, mobile::crypto::{ - derive_pin_key, get_user_encryption_key, initialize_org_crypto, initialize_user_crypto, - DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, + derive_pin_key, derive_pin_user_key, get_user_encryption_key, initialize_org_crypto, + initialize_user_crypto, DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, }, }; @@ -32,6 +35,11 @@ impl<'a> ClientCrypto<'a> { pub async fn derive_pin_key(&mut self, pin: String) -> Result { derive_pin_key(self.client, pin) } + + #[cfg(feature = "internal")] + pub async fn derive_pin_user_key(&mut self, encrypted_pin: EncString) -> Result { + derive_pin_user_key(self.client, encrypted_pin) + } } impl<'a> Client { diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 8894b19db..a96d85ec6 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -1,9 +1,13 @@ use std::collections::HashMap; use bitwarden_crypto::{AsymmEncString, EncString}; +#[cfg(feature = "internal")] +use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, MasterKey, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +#[cfg(feature = "internal")] +use crate::client::{LoginMethod, UserLoginMethod}; use crate::{ client::Kdf, error::{Error, Result}, @@ -50,8 +54,6 @@ pub enum InitUserCryptoMethod { #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { - use bitwarden_crypto::SymmetricCryptoKey; - let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), email: req.email, @@ -112,35 +114,65 @@ pub async fn get_user_encryption_key(client: &mut Client) -> Result { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct DerivePinKeyResponse { + /// [UserKey] protected by PIN pin_protected_user_key: EncString, + /// PIN protected by [UserKey] encrypted_pin: EncString, } #[cfg(feature = "internal")] pub fn derive_pin_key(client: &mut Client, pin: String) -> Result { - use bitwarden_crypto::{KeyEncryptable, MasterKey}; - - use crate::client::{LoginMethod, UserLoginMethod}; - - let derived_key = match &client.login_method { - Some(LoginMethod::User( - UserLoginMethod::Username { email, kdf, .. } - | UserLoginMethod::ApiKey { email, kdf, .. }, - )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, - _ => return Err(Error::NotAuthenticated), - }; - let user_key = client .get_encryption_settings()? .get_key(&None) .ok_or(Error::VaultLocked)?; + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + let pin_protected_user_key = derive_pin_protected_user_key(&pin, login_method, user_key)?; + Ok(DerivePinKeyResponse { - pin_protected_user_key: derived_key.encrypt_user_key(user_key)?, + pin_protected_user_key, encrypted_pin: pin.encrypt_with_key(user_key)?, }) } +#[cfg(feature = "internal")] +pub fn derive_pin_user_key(client: &mut Client, encrypted_pin: EncString) -> Result { + let user_key = client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + + let pin: String = encrypted_pin.decrypt_with_key(user_key)?; + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + derive_pin_protected_user_key(&pin, login_method, user_key) +} + +#[cfg(feature = "internal")] +fn derive_pin_protected_user_key( + pin: &str, + login_method: &LoginMethod, + user_key: &SymmetricCryptoKey, +) -> Result { + let derived_key = match login_method { + LoginMethod::User( + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. }, + ) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, + _ => return Err(Error::NotAuthenticated), + }; + + Ok(derived_key.encrypt_user_key(user_key)?) +} + #[cfg(test)] mod tests { use super::*; @@ -171,8 +203,8 @@ mod tests { let pin_key = derive_pin_key(&mut client, "1234".into()).unwrap(); + // Verify we can unlock with the pin let mut client2 = Client::new(None); - initialize_user_crypto( &mut client2, InitUserCryptoRequest { @@ -204,5 +236,43 @@ mod tests { .unwrap() .to_base64() ); + + // Verify we can derive the pin protected user key from the encrypted pin + let pin_protected_user_key = + derive_pin_user_key(&mut client, pin_key.encrypted_pin).unwrap(); + + let mut client3 = Client::new(None); + + initialize_user_crypto( + &mut client3, + InitUserCryptoRequest { + kdf_params: Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }, + email: "test@bitwarden.com".into(), + private_key: priv_key.to_owned(), + method: InitUserCryptoMethod::Pin { + pin: "1234".into(), + pin_protected_user_key, + }, + }, + ) + .await + .unwrap(); + + assert_eq!( + client + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64(), + client3 + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64() + ); } } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 27b376051..896cf7a76 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -246,6 +246,18 @@ initialize another client instance by using the PIN and the PIN key with **Output**: std::result::Result +### `derive_pin_user_key` + +Derives the pin protected user key from encrypted pin. Used when pin requires master password on +first unlock. + +**Arguments**: + +- self: +- encrypted_pin: [EncString](#encstring) + +**Output**: std::result::Result + ## ClientExporters ### `export_vault` @@ -852,6 +864,16 @@ implementations. +## `EncString` + + + + + + + +
KeyTypeDescription
+ ## `ExportFormat` @@ -1428,13 +1450,18 @@ implementations. - - + + - + - + + + + + + From c1badb7348ae4262b2494d339fc9cf3d43c43834 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 16 Jan 2024 11:53:32 +0100 Subject: [PATCH 198/378] Rename AsymmEncString to AsymmetricEncString (#510) Rename `AsymmEncString` to `AsymmetricEncString` to be consistent. We could consider renaming `AsymetricCryptoKey` to `AsymmCryptoKey` or some other variant if we prefer. --- .../src/enc_string/asymmetric.rs | 84 +++++++++---------- crates/bitwarden-crypto/src/enc_string/mod.rs | 2 +- crates/bitwarden-crypto/src/lib.rs | 4 +- crates/bitwarden/src/client/client.rs | 4 +- .../src/client/encryption_settings.rs | 6 +- crates/bitwarden/src/mobile/crypto.rs | 4 +- crates/bitwarden/src/uniffi_support.rs | 6 +- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 0c48ce14a..4c1dc3c8c 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -12,11 +12,11 @@ use crate::{ /// # Encrypted string primitive /// -/// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are -/// are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt -/// data using [AsymmetricCryptoKey]s. +/// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. +/// They are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt data using +/// [AsymmetricCryptoKey]s. /// -/// The flexibility of the [AsymmEncString] type allows for different encryption algorithms to be used +/// The flexibility of the [AsymmetricEncString] type allows for different encryption algorithms to be used /// which is represented by the different variants of the enum. /// /// ## Note @@ -25,12 +25,12 @@ use crate::{ /// variants, but we should be opinionated in which variants are used for encrypting. /// /// ## Variants -/// - [Rsa2048_OaepSha256_B64](AsymmEncString::Rsa2048_OaepSha256_B64) -/// - [Rsa2048_OaepSha1_B64](AsymmEncString::Rsa2048_OaepSha1_B64) +/// - [Rsa2048_OaepSha256_B64](AsymmetricEncString::Rsa2048_OaepSha256_B64) +/// - [Rsa2048_OaepSha1_B64](AsymmetricEncString::Rsa2048_OaepSha1_B64) /// /// ## Serialization /// -/// [AsymmEncString] implements [Display] and [FromStr] to allow for easy serialization and uses a +/// [AsymmetricEncString] implements [Display] and [FromStr] to allow for easy serialization and uses a /// custom scheme to represent the different variants. /// /// The scheme is one of the following schemes: @@ -41,7 +41,7 @@ use crate::{ /// - `[data]`: is the encrypted data. #[derive(Clone)] #[allow(unused, non_camel_case_types)] -pub enum AsymmEncString { +pub enum AsymmetricEncString { /// 3 Rsa2048_OaepSha256_B64 { data: Vec }, /// 4 @@ -54,15 +54,15 @@ pub enum AsymmEncString { Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec, mac: Vec }, } -/// To avoid printing sensitive information, [AsymmEncString] debug prints to `AsymmEncString`. -impl std::fmt::Debug for AsymmEncString { +/// To avoid printing sensitive information, [AsymmetricEncString] debug prints to `AsymmetricEncString`. +impl std::fmt::Debug for AsymmetricEncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("AsymmEncString").finish() + f.debug_struct("AsymmetricEncString").finish() } } -/// Deserializes an [AsymmEncString] from a string. -impl FromStr for AsymmEncString { +/// Deserializes an [AsymmetricEncString] from a string. +impl FromStr for AsymmetricEncString { type Err = CryptoError; fn from_str(s: &str) -> Result { @@ -70,23 +70,23 @@ impl FromStr for AsymmEncString { match (enc_type, parts.len()) { ("3", 1) => { let data = from_b64_vec(parts[0])?; - Ok(AsymmEncString::Rsa2048_OaepSha256_B64 { data }) + Ok(AsymmetricEncString::Rsa2048_OaepSha256_B64 { data }) } ("4", 1) => { let data = from_b64_vec(parts[0])?; - Ok(AsymmEncString::Rsa2048_OaepSha1_B64 { data }) + Ok(AsymmetricEncString::Rsa2048_OaepSha1_B64 { data }) } #[allow(deprecated)] ("5", 2) => { let data = from_b64_vec(parts[0])?; let mac: Vec = from_b64_vec(parts[1])?; - Ok(AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac }) + Ok(AsymmetricEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac }) } #[allow(deprecated)] ("6", 2) => { let data = from_b64_vec(parts[0])?; let mac: Vec = from_b64_vec(parts[1])?; - Ok(AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac }) + Ok(AsymmetricEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac }) } (enc_type, parts) => Err(EncStringParseError::InvalidTypeAsymm { @@ -98,15 +98,15 @@ impl FromStr for AsymmEncString { } } -impl Display for AsymmEncString { +impl Display for AsymmetricEncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let parts: Vec<&[u8]> = match self { - AsymmEncString::Rsa2048_OaepSha256_B64 { data } => vec![data], - AsymmEncString::Rsa2048_OaepSha1_B64 { data } => vec![data], + AsymmetricEncString::Rsa2048_OaepSha256_B64 { data } => vec![data], + AsymmetricEncString::Rsa2048_OaepSha1_B64 { data } => vec![data], #[allow(deprecated)] - AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac } => vec![data, mac], + AsymmetricEncString::Rsa2048_OaepSha256_HmacSha256_B64 { data, mac } => vec![data, mac], #[allow(deprecated)] - AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac } => vec![data, mac], + AsymmetricEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac } => vec![data, mac], }; let encoded_parts: Vec = parts.iter().map(|part| STANDARD.encode(part)).collect(); @@ -117,7 +117,7 @@ impl Display for AsymmEncString { } } -impl<'de> Deserialize<'de> for AsymmEncString { +impl<'de> Deserialize<'de> for AsymmetricEncString { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, @@ -126,7 +126,7 @@ impl<'de> Deserialize<'de> for AsymmEncString { } } -impl serde::Serialize for AsymmEncString { +impl serde::Serialize for AsymmetricEncString { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, @@ -135,23 +135,23 @@ impl serde::Serialize for AsymmEncString { } } -impl AsymmEncString { - /// The numerical representation of the encryption type of the [AsymmEncString]. +impl AsymmetricEncString { + /// The numerical representation of the encryption type of the [AsymmetricEncString]. const fn enc_type(&self) -> u8 { match self { - AsymmEncString::Rsa2048_OaepSha256_B64 { .. } => 3, - AsymmEncString::Rsa2048_OaepSha1_B64 { .. } => 4, + AsymmetricEncString::Rsa2048_OaepSha256_B64 { .. } => 3, + AsymmetricEncString::Rsa2048_OaepSha1_B64 { .. } => 4, #[allow(deprecated)] - AsymmEncString::Rsa2048_OaepSha256_HmacSha256_B64 { .. } => 5, + AsymmetricEncString::Rsa2048_OaepSha256_HmacSha256_B64 { .. } => 5, #[allow(deprecated)] - AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, + AsymmetricEncString::Rsa2048_OaepSha1_HmacSha256_B64 { .. } => 6, } } } -impl KeyDecryptable> for AsymmEncString { +impl KeyDecryptable> for AsymmetricEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result> { - use AsymmEncString::*; + use AsymmetricEncString::*; match self { Rsa2048_OaepSha256_B64 { data } => key.key.decrypt(Oaep::new::(), data), Rsa2048_OaepSha1_B64 { data } => key.key.decrypt(Oaep::new::(), data), @@ -168,18 +168,18 @@ impl KeyDecryptable> for AsymmEncString { } } -impl KeyDecryptable for AsymmEncString { +impl KeyDecryptable for AsymmetricEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String) } } -/// Usually we wouldn't want to expose AsymmEncStrings in the API or the schemas. -/// But during the transition phase we will expose endpoints using the AsymmEncString type. -impl schemars::JsonSchema for AsymmEncString { +/// Usually we wouldn't want to expose AsymmetricEncStrings in the API or the schemas. +/// But during the transition phase we will expose endpoints using the AsymmetricEncString type. +impl schemars::JsonSchema for AsymmetricEncString { fn schema_name() -> String { - "AsymmEncString".to_string() + "AsymmetricEncString".to_string() } fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { @@ -189,7 +189,7 @@ impl schemars::JsonSchema for AsymmEncString { #[cfg(test)] mod tests { - use super::{AsymmEncString, AsymmetricCryptoKey, KeyDecryptable}; + use super::{AsymmetricCryptoKey, AsymmetricEncString, KeyDecryptable}; const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS @@ -224,7 +224,7 @@ XKZBokBGnjFnTnKcs7nv/O8= fn test_enc_string_rsa2048_oaep_sha256_b64() { let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "3.YFqzW9LL/uLjCnl0RRLtndzGJ1FV27mcwQwGjfJPOVrgCX9nJSUYCCDd0iTIyOZ/zRxG47b6L1Z3qgkEfcxjmrSBq60gijc3E2TBMAg7OCLVcjORZ+i1sOVOudmOPWro6uA8refMrg4lqbieDlbLMzjVEwxfi5WpcL876cD0vYyRwvLO3bzFrsE7x33HHHtZeOPW79RqMn5efsB5Dj9wVheC9Ix9AYDjbo+rjg9qR6guwKmS7k2MSaIQlrDR7yu8LP+ePtiSjx+gszJV5jQGfcx60dtiLQzLS/mUD+RmU7B950Bpx0H7x56lT5yXZbWK5YkoP6qd8B8D2aKbP68Ywg=="; - let enc_string: AsymmEncString = enc_str.parse().unwrap(); + let enc_string: AsymmetricEncString = enc_str.parse().unwrap(); assert_eq!(enc_string.enc_type(), 3); @@ -236,7 +236,7 @@ XKZBokBGnjFnTnKcs7nv/O8= fn test_enc_string_rsa2048_oaep_sha1_b64() { let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw=="; - let enc_string: AsymmEncString = enc_str.parse().unwrap(); + let enc_string: AsymmetricEncString = enc_str.parse().unwrap(); assert_eq!(enc_string.enc_type(), 4); @@ -248,7 +248,7 @@ XKZBokBGnjFnTnKcs7nv/O8= fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; - let enc_string: AsymmEncString = enc_str.parse().unwrap(); + let enc_string: AsymmetricEncString = enc_str.parse().unwrap(); assert_eq!(enc_string.enc_type(), 6); @@ -260,7 +260,7 @@ XKZBokBGnjFnTnKcs7nv/O8= fn test_enc_string_serialization() { #[derive(serde::Serialize, serde::Deserialize)] struct Test { - key: AsymmEncString, + key: AsymmetricEncString, } let cipher = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; diff --git a/crates/bitwarden-crypto/src/enc_string/mod.rs b/crates/bitwarden-crypto/src/enc_string/mod.rs index 740e9589d..e1433821f 100644 --- a/crates/bitwarden-crypto/src/enc_string/mod.rs +++ b/crates/bitwarden-crypto/src/enc_string/mod.rs @@ -4,7 +4,7 @@ mod symmetric; use std::str::FromStr; -pub use asymmetric::AsymmEncString; +pub use asymmetric::AsymmetricEncString; use base64::{engine::general_purpose::STANDARD, Engine}; pub use symmetric::EncString; diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index a7399ce8e..3c1aced24 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -2,7 +2,7 @@ //! //! This crate contains the cryptographic primitives used throughout the SDK. The crate makes a //! best effort to abstract away cryptographic concepts into concepts such as [`EncString`], -//! [`AsymmEncString`] and [`SymmetricCryptoKey`]. +//! [`AsymmetricEncString`] and [`SymmetricCryptoKey`]. //! //! ## Conventions: //! @@ -23,7 +23,7 @@ mod aes; mod enc_string; -pub use enc_string::{AsymmEncString, EncString}; +pub use enc_string::{AsymmetricEncString, EncString}; mod encryptable; pub use encryptable::{Decryptable, Encryptable, KeyContainer, LocateKey}; mod error; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 34d99c0a3..3ccb7f9ca 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; pub use bitwarden_crypto::Kdf; use bitwarden_crypto::SymmetricCryptoKey; #[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString}; use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -280,7 +280,7 @@ impl Client { #[cfg(feature = "internal")] pub(crate) fn initialize_org_crypto( &mut self, - org_keys: Vec<(Uuid, AsymmEncString)>, + org_keys: Vec<(Uuid, AsymmetricEncString)>, ) -> Result<&EncryptionSettings> { let enc = self .encryption_settings diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 612449cbd..c8126b4fe 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; -#[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmEncString, EncString}; use bitwarden_crypto::{AsymmetricCryptoKey, KeyContainer, SymmetricCryptoKey}; +#[cfg(feature = "internal")] +use bitwarden_crypto::{AsymmetricEncString, EncString}; use uuid::Uuid; #[cfg(feature = "internal")] @@ -80,7 +80,7 @@ impl EncryptionSettings { #[cfg(feature = "internal")] pub(crate) fn set_org_keys( &mut self, - org_enc_keys: Vec<(Uuid, AsymmEncString)>, + org_enc_keys: Vec<(Uuid, AsymmetricEncString)>, ) -> Result<&mut Self> { use bitwarden_crypto::KeyDecryptable; diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index a96d85ec6..c32a1d1d8 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use bitwarden_crypto::{AsymmEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString}; #[cfg(feature = "internal")] use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, MasterKey, SymmetricCryptoKey}; use schemars::JsonSchema; @@ -89,7 +89,7 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct InitOrgCryptoRequest { /// The encryption keys for all the organizations the user is a part of - pub organization_keys: HashMap, + pub organization_keys: HashMap, } #[cfg(feature = "internal")] diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index fb7650d36..7da53c8b5 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,6 +1,6 @@ use std::{num::NonZeroU32, str::FromStr}; -use bitwarden_crypto::{AsymmEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString}; use uuid::Uuid; use crate::UniffiCustomTypeConverter; @@ -8,9 +8,9 @@ use crate::UniffiCustomTypeConverter; uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); -uniffi::custom_type!(AsymmEncString, String); +uniffi::custom_type!(AsymmetricEncString, String); -impl UniffiCustomTypeConverter for AsymmEncString { +impl UniffiCustomTypeConverter for AsymmetricEncString { type Builtin = String; fn into_custom(val: Self::Builtin) -> uniffi::Result { From fc07604e1153dac4fdd5e44691fafdfcad3e5cb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:18:18 -0500 Subject: [PATCH 199/378] [deps]: Update gh minor (#506) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 8 ++++---- .github/workflows/build-cli-docker.yml | 14 +++++++------- .github/workflows/build-cli.yml | 14 +++++++------- .github/workflows/build-dotnet.yml | 12 ++++++------ .github/workflows/build-java.yml | 10 +++++----- .github/workflows/build-napi.yml | 6 +++--- .github/workflows/build-rust-crates.yml | 4 ++-- .github/workflows/build-rust-cross-platform.yml | 4 ++-- .github/workflows/direct-minimal-versions.yml | 2 +- .github/workflows/generate_schemas.yml | 16 ++++++++-------- .github/workflows/golang-release.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/publish-dotnet.yml | 10 +++++----- .github/workflows/publish-php.yml | 10 +++++----- .github/workflows/publish-ruby.yml | 12 ++++++------ .github/workflows/publish-rust-crates.yml | 4 ++-- .github/workflows/release-cli.yml | 4 ++-- .github/workflows/release-napi.yml | 2 +- .github/workflows/rust-test.yml | 6 +++--- .github/workflows/version-bump.yml | 4 ++-- 20 files changed, 73 insertions(+), 73 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index f8bee2f56..361769ef9 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -33,7 +33,7 @@ jobs: toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: ${{ matrix.settings.target }}-cargo @@ -46,7 +46,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so @@ -75,7 +75,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: cargo-combine-cache @@ -86,7 +86,7 @@ jobs: java-version: 17 - name: Download Artifacts - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 - name: Move artifacts working-directory: languages/kotlin/sdk/src/main/jniLibs diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index 5cb6bb678..5d3fbd354 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Check Branch to Publish env: @@ -44,14 +44,14 @@ jobs: ########## Set up Docker ########## - name: Set up QEMU emulators - uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 + uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 ########## Login to Docker registries ########## - name: Login to Azure - Prod Subscription - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} @@ -59,7 +59,7 @@ jobs: run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} - name: Login to Azure - CI Subscription - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -104,7 +104,7 @@ jobs: fi - name: Build and push Docker image - uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v3.2.0 + uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1 with: context: . file: crates/bws/Dockerfile @@ -141,7 +141,7 @@ jobs: fi - name: Login to Azure - CI subscription - uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 if: failure() with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index b0f3e7b63..abcbcbedf 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -69,7 +69,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} @@ -99,7 +99,7 @@ jobs: run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip @@ -118,12 +118,12 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: bws-x86_64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip - name: Download aarch64-apple-darwin artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: bws-aarch64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip @@ -142,7 +142,7 @@ jobs: run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws - name: Upload artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip path: ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip @@ -163,7 +163,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: cargo-cli-about @@ -177,7 +177,7 @@ jobs: sed -i.bak 's/\$NAME\$/Bitwarden Secrets Manager CLI/g' THIRDPARTY.html - name: Upload artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: THIRDPARTY.html path: ./crates/bws/THIRDPARTY.html diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 904cea204..08d290c4e 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -35,25 +35,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 @@ -71,7 +71,7 @@ jobs: working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: Bitwarden.Sdk.0.0.1.nupkg path: | diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index d2bc049d1..18621e170 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download Java schemas artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: sdk-schemas-java path: languages/java/src/main/java/bit/sdk/schema/ @@ -36,25 +36,25 @@ jobs: java-version: 17 - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/java/src/main/resources/darwin-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/java/src/main/resources/darwin-aarch64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/java/src/main/resources/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/java/src/main/resources/windows-x64 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index ef72e7f1e..1581a8d66 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -67,12 +67,12 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: schemas.ts path: ${{ github.workspace }}/crates/bitwarden-napi/src-ts/bitwarden_client/ @@ -84,7 +84,7 @@ jobs: run: ${{ matrix.settings.build }} - name: Upload artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: sdk-bitwarden-napi-${{ matrix.settings.target }} path: ${{ github.workspace }}/crates/bitwarden-napi/sdk-napi.*.node diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 9acc1b37d..9d575d5d1 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -44,7 +44,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Build run: cargo build -p ${{ matrix.package }} --release @@ -74,7 +74,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 8999295a2..52c44abeb 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -30,7 +30,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Add build architecture run: rustup target add ${{ matrix.settings.target }} @@ -41,7 +41,7 @@ jobs: run: cargo build --target ${{ matrix.settings.target }} --release - name: Upload Artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: libbitwarden_c_files-${{ matrix.settings.target }} path: | diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index eb911072f..8db6e3c2e 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -45,7 +45,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: dmv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 53bbf34e3..55c9c07d9 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -31,54 +31,54 @@ jobs: run: npm ci - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: NPM Schemas run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: schemas.ts path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: schemas.cs path: ${{ github.workspace }}/languages/csharp/Bitwarden.Sdk/schemas.cs if-no-files-found: error - name: Upload python schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* diff --git a/.github/workflows/golang-release.yml b/.github/workflows/golang-release.yml index f42d428f9..1578dee57 100644 --- a/.github/workflows/golang-release.yml +++ b/.github/workflows/golang-release.yml @@ -34,7 +34,7 @@ jobs: go-version: ${{ env.GO_VERSION }} - name: Cache dependencies - uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 + uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f11ff4ced..dbf357d3b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -25,7 +25,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Cargo fmt run: cargo fmt --check diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index a7a6a6e0e..fc8771d38 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -37,25 +37,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index 6ed52537a..e2ab44bee 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup PHP with PECL extension - uses: shivammathur/setup-php@e6f75134d35752277f093989e72e140eaa222f35 # 2.28.0 + uses: shivammathur/setup-php@6d7209f44a25a59e904b1ee9f3b0c33ab2cd888d # 2.29.0 with: php-version: "8.0" tools: composer @@ -33,25 +33,25 @@ jobs: working-directory: languages/php/ - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 4315dea66..b3f4aa3c3 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,36 +23,36 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 # v1.165.1 + uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 with: ruby-version: 3.2 - name: Download Ruby schemas artifact - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: schemas.rb path: languages/ruby/bitwarden_sdk/lib - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/ubuntu-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 231ad5626..a264815ed 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -114,7 +114,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -131,7 +131,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index ee08c2be8..a6059a1d5 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -128,7 +128,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Login to Azure - uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} @@ -145,7 +145,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 57498c681..02e29c527 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -126,7 +126,7 @@ jobs: run: npm run tsc - name: Login to Azure - uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index ee8c55a22..8dfcf1783 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -44,7 +44,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Test run: cargo test --all-features @@ -64,7 +64,7 @@ jobs: components: llvm-tools - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-llvm-cov run: cargo install cargo-llvm-cov --version 0.5.38 @@ -93,7 +93,7 @@ jobs: targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Check run: cargo check -p bitwarden-wasm --target wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index f3c428c57..ade4134e1 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -36,13 +36,13 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-release run: cargo install cargo-edit - name: Login to Azure - CI Subscription - uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.5.1 + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} From b75b5d8257bc72f2b8b93c9a782003c2236bd5ca Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:56:21 -0500 Subject: [PATCH 200/378] Update Bitwarden action hashes to target 'main' branch (#513) --- .github/workflows/build-cli-docker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index 5d3fbd354..4605da5e5 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -65,14 +65,14 @@ jobs: - name: Retrieve github PAT secrets id: retrieve-secret-pat - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: "bitwarden-ci" secrets: "github-pat-bitwarden-devops-bot-repo-scope" - name: Setup Docker Trust if: ${{ env.is_publish_branch == 'true' }} - uses: bitwarden/gh-actions/setup-docker-trust@082f5e05ed97c3601c6f3179250b1a761c4d647f + uses: bitwarden/gh-actions/setup-docker-trust@main with: azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} azure-keyvault-name: "bitwarden-ci" @@ -148,7 +148,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + uses: bitwarden/gh-actions/get-keyvault-secrets@main if: failure() with: keyvault: "bitwarden-ci" From 8b435e52f2cce832132890b5dc12f3e01a6512c1 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 18 Jan 2024 10:54:27 +0100 Subject: [PATCH 201/378] Fix lib architectures in language SDKs (#498) - Rename `ubuntu-x64` to `linux-x64` to better match the usage. - Resolve java using the wrong prefixes. It should be `x86_64` for architecture, and windows should use `win32`. Resolves #491 --- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-java.yml | 7 ++++--- .github/workflows/publish-dotnet.yml | 2 +- .github/workflows/publish-php.yml | 6 +++--- .github/workflows/publish-ruby.yml | 6 +++--- languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj | 2 +- languages/php/src/BitwardenLib.php | 2 +- languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec | 2 +- languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb | 2 +- 9 files changed, 16 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 08d290c4e..568683a58 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -50,7 +50,7 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 + path: languages/csharp/Bitwarden.Sdk/linux-x64 - name: Download x86_64-pc-windows-msvc files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 18621e170..3c574d823 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -4,6 +4,7 @@ on: push: branches: - main + workflow_dispatch: jobs: generate_schemas: @@ -39,7 +40,7 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-apple-darwin - path: languages/java/src/main/resources/darwin-x64 + path: languages/java/src/main/resources/darwin-x86-64 - name: Download aarch64-apple-darwin files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 @@ -51,13 +52,13 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: languages/java/src/main/resources/ubuntu-x64 + path: languages/java/src/main/resources/linux-x86-64 - name: Download x86_64-pc-windows-msvc files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc - path: languages/java/src/main/resources/windows-x64 + path: languages/java/src/main/resources/win32-x86-64 - name: Publish Maven uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1 diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index fc8771d38..031a8b36f 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -52,7 +52,7 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: languages/csharp/Bitwarden.Sdk/ubuntu-x64 + path: languages/csharp/Bitwarden.Sdk/linux-x64 - name: Download x86_64-pc-windows-msvc files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index e2ab44bee..7406aae33 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -48,7 +48,7 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: temp/ubuntu-x64 + path: temp/linux-x64 - name: Download x86_64-pc-windows-msvc files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 @@ -59,11 +59,11 @@ jobs: - name: Copy lib files run: | mkdir -p languages/php/src/lib/macos-arm64 - mkdir -p languages/php/src/lib/ubuntu-x64 + mkdir -p languages/php/src/lib/linux-x64 mkdir -p languages/php/src/lib/macos-x64 mkdir -p languages/php/src/lib/windows-x64 - platforms=("macos-arm64" "ubuntu-x64" "macos-x64" "windows-x64") + platforms=("macos-arm64" "linux-x64" "macos-x64" "windows-x64") files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") for ((i=0; i<${#platforms[@]}; i++)); do diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index b3f4aa3c3..545e43f76 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -49,7 +49,7 @@ jobs: uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: temp/ubuntu-x64 + path: temp/linux-x64 - name: Download x86_64-pc-windows-msvc files uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 @@ -60,11 +60,11 @@ jobs: - name: Copy lib files run: | mkdir -p languages/ruby/bitwarden_sdk/lib/macos-arm64 - mkdir -p languages/ruby/bitwarden_sdk/lib/ubuntu-x64 + mkdir -p languages/ruby/bitwarden_sdk/lib/linux-x64 mkdir -p languages/ruby/bitwarden_sdk/lib/macos-x64 mkdir -p languages/ruby/bitwarden_sdk/lib/windows-x64 - platforms=("macos-arm64" "ubuntu-x64" "macos-x64" "windows-x64") + platforms=("macos-arm64" "linux-x64" "macos-x64" "windows-x64") files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") for ((i=0; i<${#platforms[@]}; i++)); do diff --git a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj index 183ea8db9..3717aefdf 100644 --- a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj +++ b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj @@ -62,7 +62,7 @@ true runtimes/osx-arm64/native - + Always true runtimes/linux-x64/native diff --git a/languages/php/src/BitwardenLib.php b/languages/php/src/BitwardenLib.php index 3eb3ed5f4..351728986 100644 --- a/languages/php/src/BitwardenLib.php +++ b/languages/php/src/BitwardenLib.php @@ -27,7 +27,7 @@ public function __construct() $lib_file = __DIR__.'/../../../target/debug/bitwarden_c.dll'; } } elseif (PHP_OS === 'Linux') { - $lib_file = '/lib/ubuntu-x64/libbitwarden_c.so'; + $lib_file = '/lib/linux-x64/libbitwarden_c.so'; if (file_exists($lib_file) == false) { $lib_file = __DIR__.'/../../../target/debug/libbitwarden_c.so'; } diff --git a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec index 596531035..d11a57f38 100644 --- a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec +++ b/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec @@ -25,7 +25,7 @@ Gem::Specification.new do |spec| end end - spec.files += Dir.glob('lib/ubuntu-x64/**/*') + spec.files += Dir.glob('lib/linux-x64/**/*') spec.files += Dir.glob('lib/macos-x64/**/*') spec.files += Dir.glob('lib/windows-x64/**/*') spec.files += Dir.glob('lib/macos-arm64/**/*') diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb b/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb index e09541788..8217d87b0 100644 --- a/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb +++ b/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb @@ -19,7 +19,7 @@ def self.mac_with_intel? end File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.dylib', __dir__) when /linux/ - local_file = File.expand_path('ubuntu-x64/libbitwarden_c.so', __dir__) + local_file = File.expand_path('linux-x64/libbitwarden_c.so', __dir__) File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.so', __dir__) when /mswin|mingw/ local_file = File.expand_path('windows-x64/bitwarden_c.dll', __dir__) From d70deac437333522725d0dd269e79e7edab7d55a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 18 Jan 2024 13:10:30 +0100 Subject: [PATCH 202/378] [PM-5348] Encrypt/decrypt attachment files (#490) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add encryption/decryption support for attachment files --- .../bitwarden-uniffi/src/vault/attachments.rs | 94 +++++++++++ crates/bitwarden-uniffi/src/vault/mod.rs | 6 + .../src/mobile/vault/client_attachments.rs | 89 +++++++++++ crates/bitwarden/src/mobile/vault/mod.rs | 2 + .../bitwarden/src/vault/cipher/attachment.rs | 127 +++++++++++++++ crates/bitwarden/src/vault/cipher/cipher.rs | 2 +- crates/bitwarden/src/vault/mod.rs | 7 +- languages/kotlin/doc.md | 146 ++++++++++++++++++ support/docs/docs.ts | 1 + 9 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 crates/bitwarden-uniffi/src/vault/attachments.rs create mode 100644 crates/bitwarden/src/mobile/vault/client_attachments.rs diff --git a/crates/bitwarden-uniffi/src/vault/attachments.rs b/crates/bitwarden-uniffi/src/vault/attachments.rs new file mode 100644 index 000000000..0c099b779 --- /dev/null +++ b/crates/bitwarden-uniffi/src/vault/attachments.rs @@ -0,0 +1,94 @@ +use std::{path::Path, sync::Arc}; + +use bitwarden::vault::{Attachment, AttachmentEncryptResult, AttachmentView, Cipher}; + +use crate::{Client, Result}; + +#[derive(uniffi::Object)] +pub struct ClientAttachments(pub Arc); + +#[uniffi::export(async_runtime = "tokio")] +impl ClientAttachments { + /// Encrypt an attachment file in memory + pub async fn encrypt_buffer( + &self, + cipher: Cipher, + attachment: AttachmentView, + buffer: Vec, + ) -> Result { + Ok(self + .0 + .0 + .read() + .await + .vault() + .attachments() + .encrypt_buffer(cipher, attachment, &buffer) + .await?) + } + + /// Encrypt an attachment file located in the file system + pub async fn encrypt_file( + &self, + cipher: Cipher, + attachment: AttachmentView, + decrypted_file_path: String, + encrypted_file_path: String, + ) -> Result { + Ok(self + .0 + .0 + .read() + .await + .vault() + .attachments() + .encrypt_file( + cipher, + attachment, + Path::new(&decrypted_file_path), + Path::new(&encrypted_file_path), + ) + .await?) + } + /// Decrypt an attachment file in memory + pub async fn decrypt_buffer( + &self, + cipher: Cipher, + attachment: Attachment, + buffer: Vec, + ) -> Result> { + Ok(self + .0 + .0 + .read() + .await + .vault() + .attachments() + .decrypt_buffer(cipher, attachment, &buffer) + .await?) + } + + /// Decrypt an attachment file located in the file system + pub async fn decrypt_file( + &self, + cipher: Cipher, + attachment: Attachment, + encrypted_file_path: String, + decrypted_file_path: String, + ) -> Result<()> { + Ok(self + .0 + .0 + .read() + .await + .vault() + .attachments() + .decrypt_file( + cipher, + attachment, + Path::new(&encrypted_file_path), + Path::new(&decrypted_file_path), + ) + .await?) + } +} diff --git a/crates/bitwarden-uniffi/src/vault/mod.rs b/crates/bitwarden-uniffi/src/vault/mod.rs index 435e7f355..2205e0673 100644 --- a/crates/bitwarden-uniffi/src/vault/mod.rs +++ b/crates/bitwarden-uniffi/src/vault/mod.rs @@ -5,6 +5,7 @@ use chrono::{DateTime, Utc}; use crate::{error::Result, Client}; +pub mod attachments; pub mod ciphers; pub mod collections; pub mod folders; @@ -41,6 +42,11 @@ impl ClientVault { Arc::new(sends::ClientSends(self.0.clone())) } + /// Attachment file operations + pub fn attachments(self: Arc) -> Arc { + Arc::new(attachments::ClientAttachments(self.0.clone())) + } + /// Generate a TOTP code from a provided key. /// /// The key can be either: diff --git a/crates/bitwarden/src/mobile/vault/client_attachments.rs b/crates/bitwarden/src/mobile/vault/client_attachments.rs new file mode 100644 index 000000000..c436f10fd --- /dev/null +++ b/crates/bitwarden/src/mobile/vault/client_attachments.rs @@ -0,0 +1,89 @@ +use std::path::Path; + +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}; + +use super::client_vault::ClientVault; +use crate::{ + error::{Error, Result}, + vault::{ + Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView, + Cipher, + }, + Client, +}; + +pub struct ClientAttachments<'a> { + pub(crate) client: &'a Client, +} + +impl<'a> ClientAttachments<'a> { + pub async fn encrypt_buffer( + &self, + cipher: Cipher, + attachment: AttachmentView, + buffer: &[u8], + ) -> Result { + let enc = self.client.get_encryption_settings()?; + let key = cipher.locate_key(enc, &None).ok_or(Error::VaultLocked)?; + + Ok(AttachmentFileView { + cipher, + attachment, + contents: buffer, + } + .encrypt_with_key(key)?) + } + pub async fn encrypt_file( + &self, + cipher: Cipher, + attachment: AttachmentView, + decrypted_file_path: &Path, + encrypted_file_path: &Path, + ) -> Result { + let data = std::fs::read(decrypted_file_path).unwrap(); + let AttachmentEncryptResult { + attachment, + contents, + } = self.encrypt_buffer(cipher, attachment, &data).await?; + std::fs::write(encrypted_file_path, contents)?; + Ok(attachment) + } + + pub async fn decrypt_buffer( + &self, + cipher: Cipher, + attachment: Attachment, + encrypted_buffer: &[u8], + ) -> Result> { + let enc = self.client.get_encryption_settings()?; + let key = cipher.locate_key(enc, &None).ok_or(Error::VaultLocked)?; + + AttachmentFile { + cipher, + attachment, + contents: EncString::from_buffer(encrypted_buffer)?, + } + .decrypt_with_key(key) + .map_err(Error::Crypto) + } + pub async fn decrypt_file( + &self, + cipher: Cipher, + attachment: Attachment, + encrypted_file_path: &Path, + decrypted_file_path: &Path, + ) -> Result<()> { + let data = std::fs::read(encrypted_file_path).unwrap(); + let decrypted = self.decrypt_buffer(cipher, attachment, &data).await?; + std::fs::write(decrypted_file_path, decrypted)?; + Ok(()) + } +} + +impl<'a> ClientVault<'a> { + pub fn attachments(&'a self) -> ClientAttachments<'a> { + ClientAttachments { + client: self.client, + } + } +} diff --git a/crates/bitwarden/src/mobile/vault/mod.rs b/crates/bitwarden/src/mobile/vault/mod.rs index 97f9556af..a2d4d91b3 100644 --- a/crates/bitwarden/src/mobile/vault/mod.rs +++ b/crates/bitwarden/src/mobile/vault/mod.rs @@ -1,3 +1,4 @@ +mod client_attachments; mod client_ciphers; mod client_collection; mod client_folders; @@ -6,6 +7,7 @@ mod client_sends; mod client_totp; mod client_vault; +pub use client_attachments::ClientAttachments; pub use client_ciphers::ClientCiphers; pub use client_collection::ClientCollections; pub use client_folders::ClientFolders; diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index fa4a35fc7..3e1e47025 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -6,6 +6,8 @@ use serde::{Deserialize, Serialize}; use crate::error::{Error, Result}; +use super::Cipher; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -31,6 +33,65 @@ pub struct AttachmentView { pub key: Option, } +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct AttachmentEncryptResult { + pub attachment: Attachment, + pub contents: Vec, +} + +pub struct AttachmentFile { + pub cipher: Cipher, + pub attachment: Attachment, + pub contents: EncString, +} + +pub struct AttachmentFileView<'a> { + pub cipher: Cipher, + pub attachment: AttachmentView, + pub contents: &'a [u8], +} + +impl<'a> KeyEncryptable for AttachmentFileView<'a> { + fn encrypt_with_key( + self, + key: &SymmetricCryptoKey, + ) -> Result { + let ciphers_key = Cipher::get_cipher_key(key, &self.cipher.key)?; + let ciphers_key = ciphers_key.as_ref().unwrap_or(key); + + let mut attachment = self.attachment; + + // Because this is a new attachment, we have to generate a key for it, encrypt the contents with it, and then encrypt the key with the cipher key + let attachment_key = SymmetricCryptoKey::generate(rand::thread_rng()); + let encrypted_contents = self.contents.encrypt_with_key(&attachment_key)?; + attachment.key = Some(attachment_key.to_vec().encrypt_with_key(ciphers_key)?); + + Ok(AttachmentEncryptResult { + attachment: attachment.encrypt_with_key(ciphers_key)?, + contents: encrypted_contents.to_buffer()?, + }) + } +} + +impl KeyDecryptable> for AttachmentFile { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result, CryptoError> { + let ciphers_key = Cipher::get_cipher_key(key, &self.cipher.key)?; + let ciphers_key = ciphers_key.as_ref().unwrap_or(key); + + let attachment_key: Vec = self + .attachment + .key + .as_ref() + .ok_or(CryptoError::MissingKey)? + .decrypt_with_key(ciphers_key)?; + let attachment_key = SymmetricCryptoKey::try_from(attachment_key.as_slice())?; + + self.contents.decrypt_with_key(&attachment_key) + } +} + impl KeyEncryptable for AttachmentView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { @@ -71,3 +132,69 @@ impl TryFrom for Attachment }) } } + +#[cfg(test)] +mod tests { + use base64::{engine::general_purpose::STANDARD, Engine}; + + use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; + + use crate::vault::{ + cipher::cipher::{CipherRepromptType, CipherType}, + Attachment, AttachmentFile, Cipher, + }; + + #[test] + fn test_attachment_key() { + let user_key : SymmetricCryptoKey = "w2LO+nwV4oxwswVYCxlOfRUseXfvU03VzvKQHrqeklPgiMZrspUe6sOBToCnDn9Ay0tuCBn8ykVVRb7PWhub2Q==".parse().unwrap(); + + let attachment = Attachment { + id: None, + url: None, + size: Some("161".into()), + size_name: Some("161 Bytes".into()), + file_name: Some("2.M3z1MOO9eBG9BWRTEUbPog==|jPw0By1AakHDfoaY8UOwOQ==|eP9/J1583OJpHsSM4ZnXZzdBHfqVTXnOXGlkkmAKSfA=".parse().unwrap()), + key: Some("2.r288/AOSPiaLFkW07EBGBw==|SAmnnCbOLFjX5lnURvoualOetQwuyPc54PAmHDTRrhT0gwO9ailna9U09q9bmBfI5XrjNNEsuXssgzNygRkezoVQvZQggZddOwHB6KQW5EQ=|erIMUJp8j+aTcmhdE50zEX+ipv/eR1sZ7EwULJm/6DY=".parse().unwrap()) + }; + + let cipher = Cipher { + id: None, + organization_id: None, + folder_id: None, + collection_ids: Vec::new(), + key: Some("2.Gg8yCM4IIgykCZyq0O4+cA==|GJLBtfvSJTDJh/F7X4cJPkzI6ccnzJm5DYl3yxOW2iUn7DgkkmzoOe61sUhC5dgVdV0kFqsZPcQ0yehlN1DDsFIFtrb4x7LwzJNIkMgxNyg=|1rGkGJ8zcM5o5D0aIIwAyLsjMLrPsP3EWm3CctBO3Fw=".parse().unwrap()), + name: "2.d24xECyEdMZ3MG9s6SrGNw==|XvJlTeu5KJ22M3jKosy6iw==|8xGiQty4X61cDMx6PVqkJfSQ0ZTdA/5L9TpG7QfovoM=".parse().unwrap(), + notes: None, + r#type: CipherType::Login, + login: None, + identity: None, + card: None, + secure_note: None, + favorite: false, + reprompt: CipherRepromptType::None, + organization_use_totp: false, + edit: true, + view_password: true, + local_data: None, + attachments: None, + fields: None, + password_history: None, + creation_date: "2023-07-24T12:05:09.466666700Z".parse().unwrap(), + deleted_date: None, + revision_date: "2023-07-27T19:28:05.240Z".parse().unwrap(), + }; + + let enc_file = STANDARD.decode(b"Ao00qr1xLsV+ZNQpYZ/UwEwOWo3hheKwCYcOGIbsorZ6JIG2vLWfWEXCVqP0hDuzRvmx8otApNZr8pJYLNwCe1aQ+ySHQYGkdubFjoMojulMbQ959Y4SJ6Its/EnVvpbDnxpXTDpbutDxyhxfq1P3lstL2G9rObJRrxiwdGlRGu1h94UA1fCCkIUQux5LcqUee6W4MyQmRnsUziH8gGzmtI=").unwrap(); + let original = STANDARD.decode(b"rMweTemxOL9D0iWWfRxiY3enxiZ5IrwWD6ef2apGO6MvgdGhy2fpwmATmn7BpSj9lRumddLLXm7u8zSp6hnXt1hS71YDNh78LjGKGhGL4sbg8uNnpa/I6GK/83jzqGYN7+ESbg==").unwrap(); + + let dec = AttachmentFile { + cipher, + attachment, + contents: EncString::from_buffer(&enc_file).unwrap(), + } + .decrypt_with_key(&user_key) + .unwrap(); + + assert_eq!(dec, original); + } +} diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 07d8da226..010f3cd8a 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -210,7 +210,7 @@ impl Cipher { /// Note that some ciphers do not have individual encryption keys, /// in which case this will return Ok(None) and the key associated /// with this cipher's user or organization must be used instead - fn get_cipher_key( + pub(super) fn get_cipher_key( key: &SymmetricCryptoKey, ciphers_key: &Option, ) -> Result, CryptoError> { diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index 6ac43a4d0..dce7b0e04 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -6,7 +6,12 @@ mod send; #[cfg(feature = "mobile")] mod totp; -pub use cipher::{Cipher, CipherListView, CipherView}; +pub use cipher::{ + attachment::{ + Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView, + }, + Cipher, CipherListView, CipherView, +}; pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 896cf7a76..ccf193301 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -138,6 +138,62 @@ password, use the email OTP. **Output**: std::result::Result<,BitwardenError> +## ClientAttachments + +### `encrypt_buffer` + +Encrypt an attachment file in memory + +**Arguments**: + +- self: +- cipher: [Cipher](#cipher) +- attachment: [AttachmentView](#attachmentview) +- buffer: Vec<> + +**Output**: std::result::Result + +### `encrypt_file` + +Encrypt an attachment file located in the file system + +**Arguments**: + +- self: +- cipher: [Cipher](#cipher) +- attachment: [AttachmentView](#attachmentview) +- decrypted_file_path: String +- encrypted_file_path: String + +**Output**: std::result::Result + +### `decrypt_buffer` + +Decrypt an attachment file in memory + +**Arguments**: + +- self: +- cipher: [Cipher](#cipher) +- attachment: [Attachment](#attachment) +- buffer: Vec<> + +**Output**: std::result::Result + +### `decrypt_file` + +Decrypt an attachment file located in the file system + +**Arguments**: + +- self: +- cipher: [Cipher](#cipher) +- attachment: [Attachment](#attachment) +- encrypted_file_path: String +- decrypted_file_path: String + +**Output**: std::result::Result<,BitwardenError> + ## ClientCiphers ### `encrypt` @@ -541,6 +597,16 @@ Sends operations **Output**: Arc +### `attachments` + +Attachment file operations + +**Arguments**: + +- self: Arc + +**Output**: Arc + ### `generate_totp` Generate a TOTP code from a provided key. @@ -564,6 +630,86 @@ The key can be either: References are generated from the JSON schemas and should mostly match the kotlin and swift implementations. +## `Attachment` + +
keystring,nullBase64 encoded key
passwordnewPassword string,nullReplace or add a password to an existing send. The SDK will always return None when decrypting a [Send] TODO: We should revisit this, one variant is to have `[Create, Update]SendView` DTOs.
hasPasswordbooleanDenote if an existing send has a password. The SDK will ignore this value when creating or updating sends.
type
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescription
idstring,null
urlstring,null
sizestring,null
sizeNamestring,nullReadable size, ex: "4.2 KB" or "1.43 GB"
fileName
key
+ +## `AttachmentView` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescription
idstring,null
urlstring,null
sizestring,null
sizeNamestring,null
fileNamestring,null
key
+ ## `Cipher` diff --git a/support/docs/docs.ts b/support/docs/docs.ts index b547b4502..067ff0827 100644 --- a/support/docs/docs.ts +++ b/support/docs/docs.ts @@ -21,6 +21,7 @@ const template = Handlebars.compile( const rootElements = [ "Client", "ClientAuth", + "ClientAttachments", "ClientCiphers", "ClientCollections", "ClientCrypto", From 9cad470324eafac94918e776fe86a0dea6182be9 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 18 Jan 2024 07:09:14 -0800 Subject: [PATCH 203/378] Sm 989 create build pipeline for the python language wrapper (#369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Type of change - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Package the Python SDK so that it can be published to [PyPI.org](pypi.org). ## Code changes - **`.github/workflows/build-python-wheels.yml`:** create wheels for Linux, macOS, and Windows (AMD64-only). A sdist is also created for other platforms. - **`languages/python/BitwardenClient/__init__.py`:** export functions and classes for autocompletion in IDEs and the interactive Python interpreter - **`languages/python/pyproject.toml`**: replaces `setup.py`, which is no longer officially supported. This uses Maturin to build the Rust shared-object library that will be bundled with the SDK. - **`languages/python/setup.py`**: replaced by `pyproject.toml` ## Before you submit - Please add **unit tests** where it makes sense to do so (encouraged but not required) --------- Co-authored-by: Daniel García --- .github/workflows/build-python-wheels.yml | 122 +++++++++++++++++++++ languages/python/README.md | 45 ++++---- languages/python/bitwarden_sdk/__init__.py | 13 +++ languages/python/example.py | 57 +++++++--- languages/python/pyproject.toml | 29 +++++ languages/python/setup.py | 12 -- 6 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 .github/workflows/build-python-wheels.yml mode change 100644 => 100755 languages/python/example.py create mode 100644 languages/python/pyproject.toml delete mode 100644 languages/python/setup.py diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml new file mode 100644 index 000000000..e69f3eec1 --- /dev/null +++ b/.github/workflows/build-python-wheels.yml @@ -0,0 +1,122 @@ +--- +name: Build Python Wheels + +on: + pull_request: + push: + branches: + - "main" + - "rc" + - "hotfix-rc" + workflow_dispatch: + +defaults: + run: + shell: bash + working-directory: languages/python + +jobs: + generate_schemas: + uses: ./.github/workflows/generate_schemas.yml + + setup: + name: Setup + runs-on: ubuntu-22.04 + outputs: + package_version: ${{ steps.retrieve-version.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Get Package Version + id: retrieve-version + run: | + VERSION="$(grep -o '^version = ".*"' ../../crates/bitwarden-py/Cargo.toml | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+")" + echo "package_version=$VERSION" >> $GITHUB_OUTPUT + + build: + name: Building Python wheel for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} + runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} + needs: + - generate_schemas + - setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + strategy: + fail-fast: false + matrix: + settings: + - os: macos-12 + target: x86_64-apple-darwin + + - os: macos-12 + target: aarch64-apple-darwin + + - os: windows-2022 + target: x86_64-pc-windows-msvc + + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + + - os: ubuntu-22.04 + target: aarch64-unknown-linux-gnu + + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Node + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + with: + node-version: 18 + + - name: Install rust + uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + with: + toolchain: stable + targets: ${{ matrix.settings.target }} + + - name: Cache cargo registry + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + with: + key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} + + - name: Retrieve schemas + uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + with: + name: schemas.py + path: ${{ github.workspace }}/languages/python/bitwarden_sdk + + - name: Build wheels + if: ${{ matrix.settings.target != 'x86_64-unknown-linux-gnu' }} + uses: PyO3/maturin-action@b9e8f88fd4448fdecf5095864cdc7e39a544aa9f # v1.40.7 + with: + target: ${{ matrix.settings.target }} + args: --release --find-interpreter --sdist + sccache: "true" + manylinux: "2_28" # https://github.com/pola-rs/polars/pull/12211 + working-directory: ${{ github.workspace }}/languages/python + + - name: Build wheels (Linux - x86_64) + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + uses: PyO3/maturin-action@b9e8f88fd4448fdecf5095864cdc7e39a544aa9f # v1.40.7 + with: + target: ${{ matrix.settings.target }} + args: --release --find-interpreter --sdist + container: quay.io/pypa/manylinux_2_28_x86_64:2023-11-20-745eb52 + sccache: "true" + manylinux: "2_28" # https://github.com/pola-rs/polars/pull/12211 + working-directory: ${{ github.workspace }}/languages/python + + - name: Upload wheels + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-${{ matrix.settings.target }} + path: ${{ github.workspace }}/target/wheels/bitwarden_sdk*.whl + + - name: Upload sdists + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} # we only need one sdist + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + with: + name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-sdist + path: ${{ github.workspace }}/target/wheels/bitwarden_sdk-*.tar.gz diff --git a/languages/python/README.md b/languages/python/README.md index 871be274f..e77e7a8eb 100644 --- a/languages/python/README.md +++ b/languages/python/README.md @@ -1,31 +1,32 @@ -# Requirements - -- Python3 -- setuptools - ```bash - pip install setuptools - ``` -- setuptools_rust - ```bash - pip install setuptools_rust - ``` -- dateutil - ```bash - pip install python-dateutil - ``` - -# Installation - -From the `languages/python/` directory, +# Build locally +## Requirements +- Python 3 +- `maturin` (install with `pip install maturin[patchelf]`) +- `npm` + +## Build + +From the root of the repository: ```bash -python3 ./setup.py develop +npm run schemas # generate schemas.py + +cd languages/python/ +maturin develop ``` -Rename the the resulting `.so` file to `bitwarden_py.so`, if it isn't already there. +You can now import `BitwardenClient` in your Python code. + +# Use without building locally + +```bash +pip install BitwardenClient +``` # Run +Set the `ORGANIZATION_ID` and `ACCESS_TOKEN` environment variables to your organization ID and access token, respectively. + ```bash -python3 ./login.py +python3 ./example.py ``` diff --git a/languages/python/bitwarden_sdk/__init__.py b/languages/python/bitwarden_sdk/__init__.py index e69de29bb..b2aeffea1 100644 --- a/languages/python/bitwarden_sdk/__init__.py +++ b/languages/python/bitwarden_sdk/__init__.py @@ -0,0 +1,13 @@ +"""The official Bitwarden client library for Python.""" + +__version__ = "0.1.0" + +from .bitwarden_client import * +from .schemas import * + +__doc__ = bitwarden_client.__doc__ +if hasattr(bitwarden_client, "__all__"): + __all__ = bitwarden_client.__all__ + +if hasattr(schemas, "__all__"): + __all__ += schemas.__all__ diff --git a/languages/python/example.py b/languages/python/example.py old mode 100644 new mode 100755 index b3f2ab006..16367a0c5 --- a/languages/python/example.py +++ b/languages/python/example.py @@ -1,29 +1,35 @@ -import json +#!/usr/bin/env python3 import logging -import sys -from bitwarden_sdk.bitwarden_client import BitwardenClient -from bitwarden_sdk.schemas import client_settings_from_dict, DeviceType +import os + +from bitwarden_sdk import BitwardenClient, DeviceType, client_settings_from_dict # Create the BitwardenClient, which is used to interact with the SDK -client = BitwardenClient(client_settings_from_dict({ - "apiUrl": "http://localhost:4000", - "deviceType": DeviceType.SDK, - "identityUrl": "http://localhost:33656", - "userAgent": "Python", -})) +client = BitwardenClient( + client_settings_from_dict( + { + "apiUrl": os.getenv("API_URL", "http://localhost:4000"), + "deviceType": DeviceType.SDK, + "identityUrl": os.getenv("IDENTITY_URL", "http://localhost:33656"), + "userAgent": "Python", + } + ) +) # Add some logging & set the org id logging.basicConfig(level=logging.DEBUG) -organization_id = "org_id_here" +organization_id = os.getenv("ORGANIZATION_ID") # Attempt to authenticate with the Secrets Manager Access Token -client.access_token_login("access_token_here") +client.access_token_login(os.getenv("ACCESS_TOKEN")) # -- Example Project Commands -- project = client.projects().create("ProjectName", organization_id) project2 = client.projects().create("Project - Don't Delete Me!", organization_id) -updated_project = client.projects().update(project.data.id, "Cool New Project Name", organization_id) +updated_project = client.projects().update( + project.data.id, "Cool New Project Name", organization_id +) get_that_project = client.projects().get(project.data.id) input("Press Enter to delete the project...") @@ -33,9 +39,28 @@ # -- Example Secret Commands -- -secret = client.secrets().create("TEST_SECRET", "This is a test secret", organization_id, "Secret1234!", [project2.data.id]) -secret2 = client.secrets().create("Secret - Don't Delete Me!", "This is a test secret that will stay", organization_id, "Secret1234!", [project2.data.id]) -secret_updated = client.secrets().update(secret.data.id, "TEST_SECRET_UPDATED", "This as an updated test secret", organization_id, "Secret1234!_updated", [project2.data.id]) +secret = client.secrets().create( + "TEST_SECRET", + "This is a test secret", + organization_id, + "Secret1234!", + [project2.data.id], +) +secret2 = client.secrets().create( + "Secret - Don't Delete Me!", + "This is a test secret that will stay", + organization_id, + "Secret1234!", + [project2.data.id], +) +secret_updated = client.secrets().update( + secret.data.id, + "TEST_SECRET_UPDATED", + "This as an updated test secret", + organization_id, + "Secret1234!_updated", + [project2.data.id], +) secret_retrieved = client.secrets().get(secret.data.id) input("Press Enter to delete the secret...") diff --git a/languages/python/pyproject.toml b/languages/python/pyproject.toml new file mode 100644 index 000000000..28bb22507 --- /dev/null +++ b/languages/python/pyproject.toml @@ -0,0 +1,29 @@ +[build-system] +build-backend = "maturin" +requires = ["maturin>=1.0,<2.0", "setuptools_rust>=1.8.1"] + +[project] +authors = [{ name = "Bitwarden", email = "support@bitwarden.com" }] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: Other/Proprietary License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Rust", + "Topic :: Security", +] +dependencies = ["dateutils >= 0.6.6"] +description = "A Bitwarden Client for python" +name = "bitwarden_sdk" +readme = "README.md" +requires-python = ">=3.0" +version = "0.1.0" + +[tool.maturin] +bindings = "pyo3" +compatibility = "2_28" +include = [ + { path = "bitwarden_sdk/*.py", format = ["sdist", "wheel"] } +] +manifest-path = "../../crates/bitwarden-py/Cargo.toml" +python-packages = ["bitwarden_sdk"] diff --git a/languages/python/setup.py b/languages/python/setup.py deleted file mode 100644 index b243a4fe8..000000000 --- a/languages/python/setup.py +++ /dev/null @@ -1,12 +0,0 @@ -from setuptools import setup -from setuptools_rust import Binding, RustExtension - -setup( - name="bitwarden_sdk", - description="A Bitwarden Client for python", - version="0.1", - rust_extensions=[RustExtension( - "bitwarden_py", path="../../crates/bitwarden-py/Cargo.toml", binding=Binding.PyO3)], - packages=['bitwarden_sdk'], - zip_safe=False, -) From b174e496a9c4052447abb3d3f2ddd6b62097d629 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 19 Jan 2024 10:36:17 +0100 Subject: [PATCH 204/378] [PM-5692] Extract generators to separate crate (#511) Continuation on #402. This PR extracts the generators to their own crate to establish clear boundaries between the code. There is still some logic in the client to expose generators that we may want to revisit. Also extracts explicit errors for the different generators for better error handling downstream when/if desired. --- .github/workflows/build-rust-crates.yml | 3 +- .github/workflows/publish-rust-crates.yml | 11 + .github/workflows/version-bump.yml | 7 + Cargo.lock | 18 ++ crates/bitwarden-crypto/Cargo.toml | 2 +- crates/bitwarden-crypto/README.md | 6 + crates/bitwarden-generators/Cargo.toml | 33 +++ crates/bitwarden-generators/README.md | 6 + crates/bitwarden-generators/src/lib.rs | 11 + .../src}/passphrase.rs | 29 ++- .../src}/password.rs | 26 ++- .../src}/username.rs | 34 ++- .../src/username_forwarders/addyio.rs | 158 +++++++++++++ .../src}/username_forwarders/duckduckgo.rs | 63 +++--- .../src}/username_forwarders/fastmail.rs | 94 ++++---- .../src}/username_forwarders/firefox.rs | 102 +++++---- .../src/username_forwarders/forwardemail.rs | 209 ++++++++++++++++++ .../src}/username_forwarders/mod.rs | 0 .../src/username_forwarders/simplelogin.rs | 125 +++++++++++ crates/bitwarden-generators/src/util.rs | 10 + crates/bitwarden-uniffi/src/docs.rs | 3 +- crates/bitwarden-uniffi/src/tool/mod.rs | 6 +- crates/bitwarden/Cargo.toml | 2 + crates/bitwarden/src/error.rs | 8 + crates/bitwarden/src/lib.rs | 6 + .../tool/{generators => }/client_generator.rs | 25 +-- crates/bitwarden/src/tool/generators/mod.rs | 10 - .../generators/username_forwarders/addyio.rs | 143 ------------ .../username_forwarders/forwardemail.rs | 193 ---------------- .../username_forwarders/simplelogin.rs | 114 ---------- crates/bitwarden/src/tool/mod.rs | 8 +- crates/bitwarden/src/util.rs | 12 - crates/bw/src/main.rs | 2 +- 33 files changed, 843 insertions(+), 636 deletions(-) create mode 100644 crates/bitwarden-crypto/README.md create mode 100644 crates/bitwarden-generators/Cargo.toml create mode 100644 crates/bitwarden-generators/README.md create mode 100644 crates/bitwarden-generators/src/lib.rs rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/passphrase.rs (90%) rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/password.rs (95%) rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/username.rs (91%) create mode 100644 crates/bitwarden-generators/src/username_forwarders/addyio.rs rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/username_forwarders/duckduckgo.rs (50%) rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/username_forwarders/fastmail.rs (67%) rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/username_forwarders/firefox.rs (50%) create mode 100644 crates/bitwarden-generators/src/username_forwarders/forwardemail.rs rename crates/{bitwarden/src/tool/generators => bitwarden-generators/src}/username_forwarders/mod.rs (100%) create mode 100644 crates/bitwarden-generators/src/username_forwarders/simplelogin.rs create mode 100644 crates/bitwarden-generators/src/util.rs rename crates/bitwarden/src/tool/{generators => }/client_generator.rs (81%) delete mode 100644 crates/bitwarden/src/tool/generators/mod.rs delete mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs delete mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs delete mode 100644 crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 9d575d5d1..5d45b6f95 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -29,9 +29,10 @@ jobs: package: - bitwarden - - bitwarden-crypto - bitwarden-api-api - bitwarden-api-identity + - bitwarden-crypto + - bitwarden-generators steps: - name: Checkout diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index a264815ed..2f3ea6380 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -34,6 +34,11 @@ on: required: true default: true type: boolean + publish_bitwarden-generators: + description: "Publish bitwarden-generators crate" + required: true + default: true + type: boolean defaults: run: @@ -67,6 +72,7 @@ jobs: PUBLISH_BITWARDEN_API_API: ${{ github.event.inputs.publish_bitwarden-api-api }} PUBLISH_BITWARDEN_API_IDENTITY: ${{ github.event.inputs.publish_bitwarden-api-identity }} PUBLISH_BITWARDEN_CRYPTO: ${{ github.event.inputs.publish_bitwarden-crypto }} + PUBLISH_BITWARDEN_GENERATORS: ${{ github.event.inputs.publish_bitwarden-generators }} run: | if [[ "$PUBLISH_BITWARDEN" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_API" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_IDENTITY" == "false" ]]; then echo "===================================" @@ -98,6 +104,11 @@ jobs: PACKAGES_LIST="$PACKAGES_LIST bitwarden-crypto" fi + if [[ "$PUBLISH_BITWARDEN_GENERATORS" == "true" ]]; then + PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-generators" + PACKAGES_LIST="$PACKAGES_LIST bitwarden-generators" + fi + echo "Packages command: " $PACKAGES_COMMAND echo "Packages list: " $PACKAGES_LIST diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index ade4134e1..c3055f097 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -14,6 +14,7 @@ on: - bitwarden-api-api - bitwarden-api-identity - bitwarden-crypto + - bitwarden-generators - bitwarden-json - cli - napi @@ -123,6 +124,12 @@ jobs: if: ${{ inputs.project == 'bitwarden-crypto' }} run: cargo-set-version set-version -p bitwarden-crypto ${{ inputs.version_number }} + ### bitwarden-generators + + - name: Bump bitwarden-generators crate Version + if: ${{ inputs.project == 'bitwarden-generators' }} + run: cargo-set-version set-version -p bitwarden-generators ${{ inputs.version_number }} + ### cli - name: Bump cli Version diff --git a/Cargo.lock b/Cargo.lock index 31a4b4d05..960a7707f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,6 +350,7 @@ dependencies = [ "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", + "bitwarden-generators", "chrono", "data-encoding", "getrandom 0.2.11", @@ -446,6 +447,23 @@ dependencies = [ "uuid", ] +[[package]] +name = "bitwarden-generators" +version = "0.1.0" +dependencies = [ + "bitwarden-crypto", + "rand 0.8.5", + "rand_chacha 0.3.1", + "reqwest", + "schemars", + "serde", + "serde_json", + "thiserror", + "tokio", + "uniffi", + "wiremock", +] + [[package]] name = "bitwarden-json" version = "0.3.0" diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 4b7ac6cc4..ddcaceb06 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -6,7 +6,7 @@ license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" homepage = "https://bitwarden.com" description = """ -Bitwarden Cryptographic primitives +Internal crate for the bitwarden crate. Do not use. """ keywords = ["bitwarden"] edition = "2021" diff --git a/crates/bitwarden-crypto/README.md b/crates/bitwarden-crypto/README.md new file mode 100644 index 000000000..fd697aa3c --- /dev/null +++ b/crates/bitwarden-crypto/README.md @@ -0,0 +1,6 @@ +# Bitwarden Crypto + +This is an internal crate for the Bitwarden SDK do not depend on this directly and use the +[`bitwarden`](https://crates.io/crates/bitwarden) crate instead. + +This crate does not follow semantic versioning and the public interface may change at any time. diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml new file mode 100644 index 000000000..d29c311aa --- /dev/null +++ b/crates/bitwarden-generators/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "bitwarden-generators" +version = "0.1.0" +authors = ["Bitwarden Inc"] +license-file = "LICENSE" +repository = "https://github.com/bitwarden/sdk" +homepage = "https://bitwarden.com" +description = """ +Internal crate for the bitwarden crate. Do not use. +""" +keywords = ["bitwarden"] +edition = "2021" +rust-version = "1.57" + +[features] +mobile = ["uniffi"] # Mobile-specific features + +[dependencies] +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +rand = ">=0.8.5, <0.9" +reqwest = { version = ">=0.11, <0.12", features = [ + "json", +], default-features = false } +schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } +serde = { version = ">=1.0, <2.0", features = ["derive"] } +serde_json = ">=1.0.96, <2.0" +thiserror = ">=1.0.40, <2.0" +uniffi = { version = "=0.25.2", optional = true } + +[dev-dependencies] +rand_chacha = "0.3.1" +tokio = { version = "1.35.1", features = ["rt", "macros"] } +wiremock = "0.5.22" diff --git a/crates/bitwarden-generators/README.md b/crates/bitwarden-generators/README.md new file mode 100644 index 000000000..db70c11df --- /dev/null +++ b/crates/bitwarden-generators/README.md @@ -0,0 +1,6 @@ +# Bitwarden Generators + +This is an internal crate for the Bitwarden SDK do not depend on this directly and use the +[`bitwarden`](https://crates.io/crates/bitwarden) crate instead. + +This crate does not follow semantic versioning and the public interface may change at any time. diff --git a/crates/bitwarden-generators/src/lib.rs b/crates/bitwarden-generators/src/lib.rs new file mode 100644 index 000000000..335ec92b9 --- /dev/null +++ b/crates/bitwarden-generators/src/lib.rs @@ -0,0 +1,11 @@ +mod passphrase; +pub use passphrase::{passphrase, PassphraseError, PassphraseGeneratorRequest}; +mod password; +mod util; +pub use password::{password, PasswordError, PasswordGeneratorRequest}; +mod username; +pub use username::{username, ForwarderServiceType, UsernameError, UsernameGeneratorRequest}; +mod username_forwarders; + +#[cfg(feature = "mobile")] +uniffi::setup_scaffolding!(); diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden-generators/src/passphrase.rs similarity index 90% rename from crates/bitwarden/src/tool/generators/passphrase.rs rename to crates/bitwarden-generators/src/passphrase.rs index f64b39dc2..4094e4b70 100644 --- a/crates/bitwarden/src/tool/generators/passphrase.rs +++ b/crates/bitwarden-generators/src/passphrase.rs @@ -2,8 +2,17 @@ use bitwarden_crypto::EFF_LONG_WORD_LIST; use rand::{seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use thiserror::Error; -use crate::{error::Result, util::capitalize_first_letter}; +use crate::util::capitalize_first_letter; + +#[derive(Debug, Error)] +pub enum PassphraseError { + #[error("'num_words' must be between {} and {}", minimum, maximum)] + InvalidNumWords { minimum: u8, maximum: u8 }, + #[error("'word_separator' cannot be empty")] + EmptyWordSeparator, +} /// Passphrase generator request options. #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -46,16 +55,19 @@ struct ValidPassphraseGeneratorOptions { impl PassphraseGeneratorRequest { /// Validates the request and returns an immutable struct with valid options to use with the passphrase generator. - fn validate_options(self) -> Result { + fn validate_options(self) -> Result { // TODO: Add password generator policy checks if !(MINIMUM_PASSPHRASE_NUM_WORDS..=MAXIMUM_PASSPHRASE_NUM_WORDS).contains(&self.num_words) { - return Err(format!("'num_words' must be between {MINIMUM_PASSPHRASE_NUM_WORDS} and {MAXIMUM_PASSPHRASE_NUM_WORDS}").into()); + return Err(PassphraseError::InvalidNumWords { + minimum: MINIMUM_PASSPHRASE_NUM_WORDS, + maximum: MAXIMUM_PASSPHRASE_NUM_WORDS, + }); } if self.word_separator.chars().next().is_none() { - return Err("'word_separator' cannot be empty".into()); + return Err(PassphraseError::EmptyWordSeparator); }; Ok(ValidPassphraseGeneratorOptions { @@ -67,13 +79,8 @@ impl PassphraseGeneratorRequest { } } -/// Implementation of the random passphrase generator. This is not accessible to the public API. -/// See [`ClientGenerator::passphrase`](crate::ClientGenerator::passphrase) for the API function. -/// -/// # Arguments: -/// * `options`: Valid parameters used to generate the passphrase. To create it, use -/// [`PassphraseGeneratorRequest::validate_options`](PassphraseGeneratorRequest::validate_options). -pub(super) fn passphrase(request: PassphraseGeneratorRequest) -> Result { +/// Implementation of the random passphrase generator. +pub fn passphrase(request: PassphraseGeneratorRequest) -> Result { let options = request.validate_options()?; Ok(passphrase_with_rng(rand::thread_rng(), options)) } diff --git a/crates/bitwarden/src/tool/generators/password.rs b/crates/bitwarden-generators/src/password.rs similarity index 95% rename from crates/bitwarden/src/tool/generators/password.rs rename to crates/bitwarden-generators/src/password.rs index d091d1a45..c7a8fc252 100644 --- a/crates/bitwarden/src/tool/generators/password.rs +++ b/crates/bitwarden-generators/src/password.rs @@ -3,8 +3,15 @@ use std::collections::BTreeSet; use rand::{distributions::Distribution, seq::SliceRandom, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; - -use crate::error::Result; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum PasswordError { + #[error("No character set enabled")] + NoCharacterSetEnabled, + #[error("Invalid password length")] + InvalidLength, +} /// Password generator request options. #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -32,7 +39,7 @@ pub struct PasswordGeneratorRequest { /// When set, the value must be between 1 and 9. This value is ignored is lowercase is false pub min_lowercase: Option, /// The minimum number of uppercase characters in the generated password. - /// When set, the value must be between 1 and 9. This value is ignored is uppercase is false + /// When set, the value must be between 1 and 9. This value is ignored is uppercase is false pub min_uppercase: Option, /// The minimum number of numbers in the generated password. /// When set, the value must be between 1 and 9. This value is ignored is numbers is false @@ -128,16 +135,16 @@ struct PasswordGeneratorOptions { impl PasswordGeneratorRequest { /// Validates the request and returns an immutable struct with valid options to use with the password generator. - fn validate_options(self) -> Result { + fn validate_options(self) -> Result { // TODO: Add password generator policy checks // We always have to have at least one character set enabled if !self.lowercase && !self.uppercase && !self.numbers && !self.special { - return Err("At least one character set must be enabled".into()); + return Err(PasswordError::NoCharacterSetEnabled); } if self.length < 4 { - return Err("A password must be at least 4 characters long".into()); + return Err(PasswordError::InvalidLength); } // Make sure the minimum values are zero when the character @@ -159,7 +166,7 @@ impl PasswordGeneratorRequest { // Check that the minimum lengths aren't larger than the password length let minimum_length = min_lowercase + min_uppercase + min_number + min_special; if minimum_length > length { - return Err("Password length can't be less than the sum of the minimums".into()); + return Err(PasswordError::InvalidLength); } let lower = ( @@ -208,9 +215,8 @@ impl PasswordGeneratorRequest { } } -/// Implementation of the random password generator. This is not accessible to the public API. -/// See [`ClientGenerator::password`](crate::ClientGenerator::password) for the API function. -pub(super) fn password(input: PasswordGeneratorRequest) -> Result { +/// Implementation of the random password generator. +pub fn password(input: PasswordGeneratorRequest) -> Result { let options = input.validate_options()?; Ok(password_with_rng(rand::thread_rng(), options)) } diff --git a/crates/bitwarden/src/tool/generators/username.rs b/crates/bitwarden-generators/src/username.rs similarity index 91% rename from crates/bitwarden/src/tool/generators/username.rs rename to crates/bitwarden-generators/src/username.rs index 20b101fa0..ccb46604b 100644 --- a/crates/bitwarden/src/tool/generators/username.rs +++ b/crates/bitwarden-generators/src/username.rs @@ -1,9 +1,25 @@ use bitwarden_crypto::EFF_LONG_WORD_LIST; use rand::{distributions::Distribution, seq::SliceRandom, Rng, RngCore}; +use reqwest::StatusCode; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use thiserror::Error; -use crate::{error::Result, util::capitalize_first_letter}; +use crate::util::capitalize_first_letter; + +#[derive(Debug, Error)] +pub enum UsernameError { + #[error("Invalid API Key")] + InvalidApiKey, + #[error("Unknown error")] + Unknown, + + #[error("Received error message from server: [{}] {}", .status, .message)] + ResponseContent { status: StatusCode, message: String }, + + #[error(transparent)] + Reqwest(#[from] reqwest::Error), +} #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -85,10 +101,14 @@ pub enum UsernameGeneratorRequest { impl ForwarderServiceType { // Generate a username using the specified email forwarding service // This requires an HTTP client to be passed in, as the service will need to make API calls - pub async fn generate(self, http: &reqwest::Client, website: Option) -> Result { + pub async fn generate( + self, + http: &reqwest::Client, + website: Option, + ) -> Result { use ForwarderServiceType::*; - use crate::tool::generators::username_forwarders::*; + use crate::username_forwarders::*; match self { AddyIo { @@ -107,14 +127,14 @@ impl ForwarderServiceType { } } -/// Implementation of the username generator. This is not accessible to the public API. -/// See [`ClientGenerator::username`](crate::ClientGenerator::username) for the API function. +/// Implementation of the username generator. +/// /// Note: The HTTP client is passed in as a required parameter for convenience, /// as some username generators require making API calls. -pub(super) async fn username( +pub async fn username( input: UsernameGeneratorRequest, http: &reqwest::Client, -) -> Result { +) -> Result { use rand::thread_rng; use UsernameGeneratorRequest::*; match input { diff --git a/crates/bitwarden-generators/src/username_forwarders/addyio.rs b/crates/bitwarden-generators/src/username_forwarders/addyio.rs new file mode 100644 index 000000000..4b75e1c84 --- /dev/null +++ b/crates/bitwarden-generators/src/username_forwarders/addyio.rs @@ -0,0 +1,158 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::username::UsernameError; + +pub async fn generate( + http: &reqwest::Client, + api_token: String, + domain: String, + base_url: String, + website: Option, +) -> Result { + let description = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + domain: String, + description: String, + } + + let response = http + .post(format!("{base_url}/api/v1/aliases")) + .header(CONTENT_TYPE, "application/json") + .bearer_auth(api_token) + .header("X-Requested-With", "XMLHttpRequest") + .json(&Request { + domain, + description, + }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err(UsernameError::InvalidApiKey); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct ResponseData { + email: String, + } + #[derive(serde::Deserialize)] + struct Response { + data: ResponseData, + } + let response: Response = response.json().await?; + + Ok(response.data.email) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use crate::username::UsernameError; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let server = wiremock::MockServer::start().await; + + // Mock the request to the addy.io API, and verify that the correct request is made + server + .register( + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "myemail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "data": { + "id": "50c9e585-e7f5-41c4-9016-9014c15454bc", + "user_id": "ca0a4e09-c266-4f6f-845c-958db5090f09", + "local_part": "50c9e585-e7f5-41c4-9016-9014c15454bc", + "domain": "myemail.com", + "email": "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com", + "active": true + } + }))) + .expect(1), + ) + .await; + // Mock an invalid API token request + server + .register( + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "myemail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ) + .await; + // Mock an invalid domain + server + .register( + Mock::given(matchers::path("/api/v1/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .and(matchers::body_json(json!({ + "domain": "gmail.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(403)) + .expect(1), + ) + .await; + + let address = super::generate( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "myemail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap(); + + let fake_token_error = super::generate( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + "myemail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap_err(); + + assert_eq!( + fake_token_error.to_string(), + UsernameError::InvalidApiKey.to_string() + ); + + let fake_domain_error = super::generate( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "gmail.com".into(), + format!("http://{}", server.address()), + Some("example.com".into()), + ) + .await + .unwrap_err(); + + assert!(fake_domain_error.to_string().contains("403 Forbidden")); + + server.verify().await; + assert_eq!(address, "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com"); + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs b/crates/bitwarden-generators/src/username_forwarders/duckduckgo.rs similarity index 50% rename from crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs rename to crates/bitwarden-generators/src/username_forwarders/duckduckgo.rs index 512db7812..3f21fd3a5 100644 --- a/crates/bitwarden/src/tool/generators/username_forwarders/duckduckgo.rs +++ b/crates/bitwarden-generators/src/username_forwarders/duckduckgo.rs @@ -1,7 +1,8 @@ use reqwest::{header::CONTENT_TYPE, StatusCode}; -use crate::error::Result; -pub async fn generate(http: &reqwest::Client, token: String) -> Result { +use crate::username::UsernameError; + +pub async fn generate(http: &reqwest::Client, token: String) -> Result { generate_with_api_url(http, token, "https://quack.duckduckgo.com".into()).await } @@ -9,7 +10,7 @@ async fn generate_with_api_url( http: &reqwest::Client, token: String, api_url: String, -) -> Result { +) -> Result { let response = http .post(format!("{api_url}/api/email/addresses")) .header(CONTENT_TYPE, "application/json") @@ -18,7 +19,7 @@ async fn generate_with_api_url( .await?; if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid DuckDuckGo API token".into()); + return Err(UsernameError::InvalidApiKey); } // Throw any other errors @@ -36,29 +37,38 @@ async fn generate_with_api_url( #[cfg(test)] mod tests { use serde_json::json; + + use crate::username::UsernameError; #[tokio::test] async fn test_mock_server() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = crate::util::start_mock(vec![ - // Mock the request to the DDG API, and verify that the correct request is made - Mock::given(matchers::path("/api/email/addresses")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_TOKEN")) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "address": "bw7prt" - }))) - .expect(1), - // Mock an invalid token request - Mock::given(matchers::path("/api/email/addresses")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) - .respond_with(ResponseTemplate::new(401)) - .expect(1), - ]) - .await; + let server = wiremock::MockServer::start().await; + + // Mock the request to the DDG API, and verify that the correct request is made + server + .register( + Mock::given(matchers::path("/api/email/addresses")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_TOKEN")) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "address": "bw7prt" + }))) + .expect(1), + ) + .await; + // Mock an invalid token request + server + .register( + Mock::given(matchers::path("/api/email/addresses")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ) + .await; let address = super::generate_with_api_url( &reqwest::Client::new(), @@ -77,9 +87,10 @@ mod tests { .await .unwrap_err(); - assert!(fake_token_error - .to_string() - .contains("Invalid DuckDuckGo API token")); + assert_eq!( + fake_token_error.to_string(), + UsernameError::InvalidApiKey.to_string() + ); server.verify().await; } diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs b/crates/bitwarden-generators/src/username_forwarders/fastmail.rs similarity index 67% rename from crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs rename to crates/bitwarden-generators/src/username_forwarders/fastmail.rs index d2a7554e2..6cc63647a 100644 --- a/crates/bitwarden/src/tool/generators/username_forwarders/fastmail.rs +++ b/crates/bitwarden-generators/src/username_forwarders/fastmail.rs @@ -3,12 +3,13 @@ use std::collections::HashMap; use reqwest::{header::CONTENT_TYPE, StatusCode}; use serde_json::json; -use crate::error::Result; +use crate::username::UsernameError; + pub async fn generate( http: &reqwest::Client, api_token: String, website: Option, -) -> Result { +) -> Result { generate_with_api_url(http, api_token, website, "https://api.fastmail.com".into()).await } @@ -17,7 +18,7 @@ pub async fn generate_with_api_url( api_token: String, website: Option, api_url: String, -) -> Result { +) -> Result { let account_id = get_account_id(http, &api_token, &api_url).await?; let response = http @@ -44,13 +45,14 @@ pub async fn generate_with_api_url( .send() .await?; - if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid Fastmail API token".into()); + let status_code = response.status(); + if status_code == StatusCode::UNAUTHORIZED { + return Err(UsernameError::InvalidApiKey); } - let response: serde_json::Value = response.json().await?; - let Some(r) = response.get("methodResponses").and_then(|r| r.get(0)) else { - return Err("Unknown Fastmail error occurred.".into()); + let response_json: serde_json::Value = response.json().await?; + let Some(r) = response_json.get("methodResponses").and_then(|r| r.get(0)) else { + return Err(UsernameError::Unknown); }; let method_response = r.get(0).and_then(|r| r.as_str()); let response_value = r.get(1); @@ -72,24 +74,30 @@ pub async fn generate_with_api_url( .and_then(|r| r.as_str()) .unwrap_or("Unknown error"); - return Err(format!("Fastmail error: {error_description}").into()); + return Err(UsernameError::ResponseContent { + status: status_code, + message: error_description.to_owned(), + }); } else if method_response == Some("error") { let error_description = response_value .and_then(|r| r.get("description")) .and_then(|r| r.as_str()) .unwrap_or("Unknown error"); - return Err(format!("Fastmail error: {error_description}").into()); + return Err(UsernameError::ResponseContent { + status: status_code, + message: error_description.to_owned(), + }); } - Err("Unknown Fastmail error occurred.".into()) + Err(UsernameError::Unknown) } async fn get_account_id( client: &reqwest::Client, api_token: &str, api_url: &str, -) -> Result { +) -> Result { #[derive(serde::Deserialize)] struct Response { #[serde(rename = "primaryAccounts")] @@ -102,7 +110,7 @@ async fn get_account_id( .await?; if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid Fastmail API token".into()); + return Err(UsernameError::InvalidApiKey); } response.error_for_status_ref()?; @@ -117,13 +125,16 @@ async fn get_account_id( #[cfg(test)] mod tests { use serde_json::json; + + use crate::username::UsernameError; #[tokio::test] async fn test_mock_server() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = crate::util::start_mock(vec![ - // Mock a valid request to FastMail API - Mock::given(matchers::path("/.well-known/jmap")) + let server = wiremock::MockServer::start().await; + + // Mock a valid request to FastMail API + server.register(Mock::given(matchers::path("/.well-known/jmap")) .and(matchers::method("GET")) .and(matchers::header("Authorization", "Bearer MY_TOKEN")) .respond_with(ResponseTemplate::new(201).set_body_json(json!({ @@ -131,9 +142,9 @@ mod tests { "https://www.fastmail.com/dev/maskedemail": "ca0a4e09-c266-4f6f-845c-958db5090f09" } }))) - .expect(1), + .expect(1)).await; - Mock::given(matchers::path("/jmap/api/")) + server.register(Mock::given(matchers::path("/jmap/api/")) .and(matchers::method("POST")) .and(matchers::header("Content-Type", "application/json")) .and(matchers::header("Authorization", "Bearer MY_TOKEN")) @@ -142,23 +153,29 @@ mod tests { ["MaskedEmail/set", {"created": {"new-masked-email": {"email": "9f823dq23d123ds@mydomain.com"}}}] ] }))) - .expect(1), - - // Mock an invalid token request - Mock::given(matchers::path("/.well-known/jmap")) - .and(matchers::method("GET")) - .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) - .respond_with(ResponseTemplate::new(401)) - .expect(1), - - Mock::given(matchers::path("/jmap/api/")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) - .respond_with(ResponseTemplate::new(201)) - .expect(0), - ]) - .await; + .expect(1)).await; + + // Mock an invalid token request + server + .register( + Mock::given(matchers::path("/.well-known/jmap")) + .and(matchers::method("GET")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ) + .await; + + server + .register( + Mock::given(matchers::path("/jmap/api/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) + .respond_with(ResponseTemplate::new(201)) + .expect(0), + ) + .await; let address = super::generate_with_api_url( &reqwest::Client::new(), @@ -179,9 +196,10 @@ mod tests { .await .unwrap_err(); - assert!(fake_token_error - .to_string() - .contains("Invalid Fastmail API token")); + assert_eq!( + fake_token_error.to_string(), + UsernameError::InvalidApiKey.to_string() + ); server.verify().await; } diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs b/crates/bitwarden-generators/src/username_forwarders/firefox.rs similarity index 50% rename from crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs rename to crates/bitwarden-generators/src/username_forwarders/firefox.rs index e53931358..66c2a3a2c 100644 --- a/crates/bitwarden/src/tool/generators/username_forwarders/firefox.rs +++ b/crates/bitwarden-generators/src/username_forwarders/firefox.rs @@ -3,13 +3,13 @@ use reqwest::{ StatusCode, }; -use crate::error::Result; +use crate::username::UsernameError; pub async fn generate( http: &reqwest::Client, api_token: String, website: Option, -) -> Result { +) -> Result { generate_with_api_url(http, api_token, website, "https://relay.firefox.com".into()).await } @@ -18,7 +18,7 @@ async fn generate_with_api_url( api_token: String, website: Option, api_url: String, -) -> Result { +) -> Result { #[derive(serde::Serialize)] struct Request { enabled: bool, @@ -41,7 +41,7 @@ async fn generate_with_api_url( .await?; if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid Firefox Relay API key".into()); + return Err(UsernameError::InvalidApiKey); } // Throw any other errors @@ -60,24 +60,30 @@ async fn generate_with_api_url( mod tests { use serde_json::json; + use crate::username::UsernameError; + #[tokio::test] async fn test_mock_success() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = - crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Token MY_TOKEN")) - .and(matchers::body_json(json!({ - "enabled": true, - "generated_for": "example.com", - "description": "example.com - Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "full_address": "ofuj4d4qw@mozmail.com" - }))) - .expect(1)]) + let server = wiremock::MockServer::start().await; + + server + .register( + Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "generated_for": "example.com", + "description": "example.com - Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "full_address": "ofuj4d4qw@mozmail.com" + }))) + .expect(1), + ) .await; let address = super::generate_with_api_url( @@ -97,19 +103,23 @@ mod tests { async fn test_mock_without_website() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = - crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Token MY_OTHER_TOKEN")) - .and(matchers::body_json(json!({ - "enabled": true, - "description": "Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "full_address": "856f7765@mozmail.com" - }))) - .expect(1)]) + let server = wiremock::MockServer::start().await; + + server + .register( + Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_OTHER_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "description": "Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "full_address": "856f7765@mozmail.com" + }))) + .expect(1), + ) .await; let address = super::generate_with_api_url( @@ -129,18 +139,22 @@ mod tests { async fn test_mock_invalid_token() { use wiremock::{matchers, Mock, ResponseTemplate}; - let (server, _client) = - crate::util::start_mock(vec![Mock::given(matchers::path("/api/v1/relayaddresses/")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Token MY_FAKE_TOKEN")) - .and(matchers::body_json(json!({ - "enabled": true, - "generated_for": "example.com", - "description": "example.com - Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(401)) - .expect(1)]) + let server = wiremock::MockServer::start().await; + + server + .register( + Mock::given(matchers::path("/api/v1/relayaddresses/")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Token MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "enabled": true, + "generated_for": "example.com", + "description": "example.com - Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ) .await; let error = super::generate_with_api_url( @@ -152,7 +166,7 @@ mod tests { .await .unwrap_err(); - assert!(error.to_string().contains("Invalid Firefox Relay API key")); + assert_eq!(error.to_string(), UsernameError::InvalidApiKey.to_string()); server.verify().await; } diff --git a/crates/bitwarden-generators/src/username_forwarders/forwardemail.rs b/crates/bitwarden-generators/src/username_forwarders/forwardemail.rs new file mode 100644 index 000000000..1cec22882 --- /dev/null +++ b/crates/bitwarden-generators/src/username_forwarders/forwardemail.rs @@ -0,0 +1,209 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::username::UsernameError; + +pub async fn generate( + http: &reqwest::Client, + api_token: String, + domain: String, + website: Option, +) -> Result { + generate_with_api_url( + http, + api_token, + domain, + website, + "https://api.forwardemail.net".into(), + ) + .await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + api_token: String, + domain: String, + website: Option, + api_url: String, +) -> Result { + let description = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + labels: Option, + description: String, + } + + let response = http + .post(format!("{api_url}/v1/domains/{domain}/aliases")) + .header(CONTENT_TYPE, "application/json") + .basic_auth(api_token, None::) + .json(&Request { + description, + labels: website, + }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err(UsernameError::InvalidApiKey); + } + + #[derive(serde::Deserialize)] + struct ResponseDomain { + name: Option, + } + #[derive(serde::Deserialize)] + struct Response { + name: Option, + domain: Option, + + message: Option, + error: Option, + } + let status = response.status(); + let response: Response = response.json().await?; + + if status.is_success() { + if let Some(name) = response.name { + if let Some(response_domain) = response.domain { + return Ok(format!( + "{}@{}", + name, + response_domain.name.unwrap_or(domain) + )); + } + } + } + + if let Some(message) = response.message { + return Err(UsernameError::ResponseContent { status, message }); + } + if let Some(message) = response.error { + return Err(UsernameError::ResponseContent { status, message }); + } + + Err(UsernameError::Unknown) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use crate::username::UsernameError; + + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let server = wiremock::MockServer::start().await; + + // Mock the request to the ForwardEmail API, and verify that the correct request is made + server + .register( + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authorization", "Basic TVlfVE9LRU46")) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "name": "wertg8ad", + "domain": { + "name": "mydomain.com" + } + }))) + .expect(1), + ) + .await; + + // Mock an invalid API token request + server + .register( + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header( + "Authorization", + "Basic TVlfRkFLRV9UT0tFTjo=", + )) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401).set_body_json(json!({ + "statusCode": 401, + "error": "Unauthorized", + "message": "Invalid API token." + }))) + .expect(1), + ) + .await; + + // Mock a free API token request + server + .register( + Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) + .and(matchers::method("POST")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header( + "Authorization", + "Basic TVlfRlJFRV9UT0tFTjo=", + )) + .and(matchers::body_json(json!({ + "labels": "example.com", + "description": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(402).set_body_json(json!({ + "statusCode": 402, + "error": "Payment required", + "message": "Please upgrade to a paid plan to unlock this feature." + }))) + .expect(1), + ) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "wertg8ad@mydomain.com"); + + let invalid_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert_eq!( + invalid_token_error.to_string(), + UsernameError::InvalidApiKey.to_string() + ); + + let free_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FREE_TOKEN".into(), + "mydomain.com".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert!(free_token_error + .to_string() + .contains("Please upgrade to a paid plan")); + + server.verify().await; + } +} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/mod.rs b/crates/bitwarden-generators/src/username_forwarders/mod.rs similarity index 100% rename from crates/bitwarden/src/tool/generators/username_forwarders/mod.rs rename to crates/bitwarden-generators/src/username_forwarders/mod.rs diff --git a/crates/bitwarden-generators/src/username_forwarders/simplelogin.rs b/crates/bitwarden-generators/src/username_forwarders/simplelogin.rs new file mode 100644 index 000000000..fa9342267 --- /dev/null +++ b/crates/bitwarden-generators/src/username_forwarders/simplelogin.rs @@ -0,0 +1,125 @@ +use reqwest::{header::CONTENT_TYPE, StatusCode}; + +use crate::username::UsernameError; + +pub async fn generate( + http: &reqwest::Client, + api_key: String, + website: Option, +) -> Result { + generate_with_api_url(http, api_key, website, "https://app.simplelogin.io".into()).await +} + +async fn generate_with_api_url( + http: &reqwest::Client, + api_key: String, + website: Option, + api_url: String, +) -> Result { + let query = website + .as_ref() + .map(|w| format!("?hostname={}", w)) + .unwrap_or_default(); + + let note = super::format_description(&website); + + #[derive(serde::Serialize)] + struct Request { + note: String, + } + + let response = http + .post(format!("{api_url}/api/alias/random/new{query}")) + .header(CONTENT_TYPE, "application/json") + .header("Authentication", api_key) + .json(&Request { note }) + .send() + .await?; + + if response.status() == StatusCode::UNAUTHORIZED { + return Err(UsernameError::InvalidApiKey); + } + + // Throw any other errors + response.error_for_status_ref()?; + + #[derive(serde::Deserialize)] + struct Response { + alias: String, + } + let response: Response = response.json().await?; + + Ok(response.alias) +} + +#[cfg(test)] +mod tests { + use serde_json::json; + + use crate::username::UsernameError; + #[tokio::test] + async fn test_mock_server() { + use wiremock::{matchers, Mock, ResponseTemplate}; + + let server = wiremock::MockServer::start().await; + + // Mock the request to the SimpleLogin API, and verify that the correct request is made + server + .register( + Mock::given(matchers::path("/api/alias/random/new")) + .and(matchers::method("POST")) + .and(matchers::query_param("hostname", "example.com")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authentication", "MY_TOKEN")) + .and(matchers::body_json(json!({ + "note": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(201).set_body_json(json!({ + "alias": "simplelogin.yut3g8@aleeas.com", + }))) + .expect(1), + ) + .await; + // Mock an invalid token request + server + .register( + Mock::given(matchers::path("/api/alias/random/new")) + .and(matchers::method("POST")) + .and(matchers::query_param("hostname", "example.com")) + .and(matchers::header("Content-Type", "application/json")) + .and(matchers::header("Authentication", "MY_FAKE_TOKEN")) + .and(matchers::body_json(json!({ + "note": "Website: example.com. Generated by Bitwarden." + }))) + .respond_with(ResponseTemplate::new(401)) + .expect(1), + ) + .await; + + let address = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap(); + assert_eq!(address, "simplelogin.yut3g8@aleeas.com"); + + let fake_token_error = super::generate_with_api_url( + &reqwest::Client::new(), + "MY_FAKE_TOKEN".into(), + Some("example.com".into()), + format!("http://{}", server.address()), + ) + .await + .unwrap_err(); + + assert_eq!( + fake_token_error.to_string(), + UsernameError::InvalidApiKey.to_string() + ); + + server.verify().await; + } +} diff --git a/crates/bitwarden-generators/src/util.rs b/crates/bitwarden-generators/src/util.rs new file mode 100644 index 000000000..e434500ea --- /dev/null +++ b/crates/bitwarden-generators/src/util.rs @@ -0,0 +1,10 @@ +pub(crate) fn capitalize_first_letter(s: &str) -> String { + // Unicode case conversion can change the length of the string, so we can't capitalize in place. + // Instead we extract the first character and convert it to uppercase. This returns + // an iterator which we collect into a string, and then append the rest of the input. + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index 3ba0e061b..55d81beec 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,8 +1,9 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, + generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest}, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, platform::FingerprintRequest, - tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, + tool::ExportFormat, vault::{ Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView, TotpResponse, diff --git a/crates/bitwarden-uniffi/src/tool/mod.rs b/crates/bitwarden-uniffi/src/tool/mod.rs index 6b443618c..4a4ea2401 100644 --- a/crates/bitwarden-uniffi/src/tool/mod.rs +++ b/crates/bitwarden-uniffi/src/tool/mod.rs @@ -1,10 +1,8 @@ use std::sync::Arc; use bitwarden::{ - tool::{ - ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest, - UsernameGeneratorRequest, - }, + generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest}, + tool::ExportFormat, vault::{Cipher, Collection, Folder}, }; diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index d69279881..22ee6eaef 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -21,6 +21,7 @@ mobile = [ "uniffi", "internal", "bitwarden-crypto/mobile", + "bitwarden-generators/mobile", ] # Mobile-specific features wasm-bindgen = ["chrono/wasmbind"] @@ -30,6 +31,7 @@ base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-generators = { path = "../bitwarden-generators", version = "0.1.0" } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 627e92e78..173557b04 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, fmt::Debug}; use bitwarden_api_api::apis::Error as ApiError; use bitwarden_api_identity::apis::Error as IdentityError; +use bitwarden_generators::{PassphraseError, PasswordError, UsernameError}; use reqwest::StatusCode; use thiserror::Error; @@ -49,6 +50,13 @@ pub enum Error { #[error("The state file could not be read")] InvalidStateFile, + #[error(transparent)] + UsernameError(#[from] UsernameError), + #[error(transparent)] + PassphraseError(#[from] PassphraseError), + #[error(transparent)] + PasswordError(#[from] PasswordError), + #[error("Internal error: {0}")] Internal(Cow<'static, str>), } diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index a0a1c1b95..5468be855 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -75,3 +75,9 @@ pub use client::Client; // Ensure the readme docs compile #[doc = include_str!("../README.md")] mod readme {} + +pub mod generators { + pub use bitwarden_generators::{ + PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest, + }; +} diff --git a/crates/bitwarden/src/tool/generators/client_generator.rs b/crates/bitwarden/src/tool/client_generator.rs similarity index 81% rename from crates/bitwarden/src/tool/generators/client_generator.rs rename to crates/bitwarden/src/tool/client_generator.rs index 301383635..bf7c66ef3 100644 --- a/crates/bitwarden/src/tool/generators/client_generator.rs +++ b/crates/bitwarden/src/tool/client_generator.rs @@ -1,13 +1,10 @@ -use crate::{ - error::Result, - tool::generators::{ - passphrase::{passphrase, PassphraseGeneratorRequest}, - password::{password, PasswordGeneratorRequest}, - username::{username, UsernameGeneratorRequest}, - }, - Client, +use bitwarden_generators::{ + passphrase, password, username, PassphraseGeneratorRequest, PasswordGeneratorRequest, + UsernameGeneratorRequest, }; +use crate::{error::Result, Client}; + pub struct ClientGenerator<'a> { pub(crate) client: &'a crate::Client, } @@ -20,7 +17,7 @@ impl<'a> ClientGenerator<'a> { /// # Examples /// /// ``` - /// use bitwarden::{Client, tool::PasswordGeneratorRequest, error::Result}; + /// use bitwarden::{Client, generators::PasswordGeneratorRequest, error::Result}; /// async fn test() -> Result<()> { /// let input = PasswordGeneratorRequest { /// lowercase: true, @@ -35,7 +32,7 @@ impl<'a> ClientGenerator<'a> { /// } /// ``` pub async fn password(&self, input: PasswordGeneratorRequest) -> Result { - password(input) + Ok(password(input)?) } /// Generates a random passphrase. @@ -48,7 +45,7 @@ impl<'a> ClientGenerator<'a> { /// # Examples /// /// ``` - /// use bitwarden::{Client, tool::PassphraseGeneratorRequest, error::Result}; + /// use bitwarden::{Client, generators::PassphraseGeneratorRequest, error::Result}; /// async fn test() -> Result<()> { /// let input = PassphraseGeneratorRequest { /// num_words: 4, @@ -60,7 +57,7 @@ impl<'a> ClientGenerator<'a> { /// } /// ``` pub async fn passphrase(&self, input: PassphraseGeneratorRequest) -> Result { - passphrase(input) + Ok(passphrase(input)?) } /// Generates a random username. @@ -70,7 +67,7 @@ impl<'a> ClientGenerator<'a> { /// services, which may require a specific setup or API key. /// /// ``` - /// use bitwarden::{Client, tool::{UsernameGeneratorRequest}, error::Result}; + /// use bitwarden::{Client, generators::{UsernameGeneratorRequest}, error::Result}; /// async fn test() -> Result<()> { /// let input = UsernameGeneratorRequest::Word { /// capitalize: true, @@ -82,7 +79,7 @@ impl<'a> ClientGenerator<'a> { /// } /// ``` pub async fn username(&self, input: UsernameGeneratorRequest) -> Result { - username(input, self.client.get_http_client()).await + Ok(username(input, self.client.get_http_client()).await?) } } diff --git a/crates/bitwarden/src/tool/generators/mod.rs b/crates/bitwarden/src/tool/generators/mod.rs deleted file mode 100644 index 7966c58a9..000000000 --- a/crates/bitwarden/src/tool/generators/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod client_generator; -mod passphrase; -mod password; -mod username; -mod username_forwarders; - -pub use client_generator::ClientGenerator; -pub use passphrase::PassphraseGeneratorRequest; -pub use password::PasswordGeneratorRequest; -pub use username::{AppendType, ForwarderServiceType, UsernameGeneratorRequest}; diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs b/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs deleted file mode 100644 index 0fc5937f6..000000000 --- a/crates/bitwarden/src/tool/generators/username_forwarders/addyio.rs +++ /dev/null @@ -1,143 +0,0 @@ -use reqwest::{header::CONTENT_TYPE, StatusCode}; - -use crate::error::Result; -pub async fn generate( - http: &reqwest::Client, - api_token: String, - domain: String, - base_url: String, - website: Option, -) -> Result { - let description = super::format_description(&website); - - #[derive(serde::Serialize)] - struct Request { - domain: String, - description: String, - } - - let response = http - .post(format!("{base_url}/api/v1/aliases")) - .header(CONTENT_TYPE, "application/json") - .bearer_auth(api_token) - .header("X-Requested-With", "XMLHttpRequest") - .json(&Request { - domain, - description, - }) - .send() - .await?; - - if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid addy.io API token.".into()); - } - - // Throw any other errors - response.error_for_status_ref()?; - - #[derive(serde::Deserialize)] - struct ResponseData { - email: String, - } - #[derive(serde::Deserialize)] - struct Response { - data: ResponseData, - } - let response: Response = response.json().await?; - - Ok(response.data.email) -} - -#[cfg(test)] -mod tests { - use serde_json::json; - #[tokio::test] - async fn test_mock_server() { - use wiremock::{matchers, Mock, ResponseTemplate}; - - let (server, _client) = crate::util::start_mock(vec![ - // Mock the request to the addy.io API, and verify that the correct request is made - Mock::given(matchers::path("/api/v1/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_TOKEN")) - .and(matchers::body_json(json!({ - "domain": "myemail.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "data": { - "id": "50c9e585-e7f5-41c4-9016-9014c15454bc", - "user_id": "ca0a4e09-c266-4f6f-845c-958db5090f09", - "local_part": "50c9e585-e7f5-41c4-9016-9014c15454bc", - "domain": "myemail.com", - "email": "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com", - "active": true - } - }))) - .expect(1), - // Mock an invalid API token request - Mock::given(matchers::path("/api/v1/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_FAKE_TOKEN")) - .and(matchers::body_json(json!({ - "domain": "myemail.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(401)) - .expect(1), - // Mock an invalid domain - Mock::given(matchers::path("/api/v1/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Bearer MY_TOKEN")) - .and(matchers::body_json(json!({ - "domain": "gmail.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(403)) - .expect(1), - ]) - .await; - - let address = super::generate( - &reqwest::Client::new(), - "MY_TOKEN".into(), - "myemail.com".into(), - format!("http://{}", server.address()), - Some("example.com".into()), - ) - .await - .unwrap(); - - let fake_token_error = super::generate( - &reqwest::Client::new(), - "MY_FAKE_TOKEN".into(), - "myemail.com".into(), - format!("http://{}", server.address()), - Some("example.com".into()), - ) - .await - .unwrap_err(); - - assert!(fake_token_error - .to_string() - .contains("Invalid addy.io API token.")); - - let fake_domain_error = super::generate( - &reqwest::Client::new(), - "MY_TOKEN".into(), - "gmail.com".into(), - format!("http://{}", server.address()), - Some("example.com".into()), - ) - .await - .unwrap_err(); - - assert!(fake_domain_error.to_string().contains("403 Forbidden")); - - server.verify().await; - assert_eq!(address, "50c9e585-e7f5-41c4-9016-9014c15454bc@myemail.com"); - } -} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs b/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs deleted file mode 100644 index f4ba6ced6..000000000 --- a/crates/bitwarden/src/tool/generators/username_forwarders/forwardemail.rs +++ /dev/null @@ -1,193 +0,0 @@ -use reqwest::{header::CONTENT_TYPE, StatusCode}; - -use crate::error::{Error, Result}; - -pub async fn generate( - http: &reqwest::Client, - api_token: String, - domain: String, - website: Option, -) -> Result { - generate_with_api_url( - http, - api_token, - domain, - website, - "https://api.forwardemail.net".into(), - ) - .await -} - -async fn generate_with_api_url( - http: &reqwest::Client, - api_token: String, - domain: String, - website: Option, - api_url: String, -) -> Result { - let description = super::format_description(&website); - - #[derive(serde::Serialize)] - struct Request { - labels: Option, - description: String, - } - - let response = http - .post(format!("{api_url}/v1/domains/{domain}/aliases")) - .header(CONTENT_TYPE, "application/json") - .basic_auth(api_token, None::) - .json(&Request { - description, - labels: website, - }) - .send() - .await?; - - if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid Forward Email API key.".into()); - } - - #[derive(serde::Deserialize)] - struct ResponseDomain { - name: Option, - } - #[derive(serde::Deserialize)] - struct Response { - name: Option, - domain: Option, - - message: Option, - error: Option, - } - let status = response.status(); - let response: Response = response.json().await?; - - if status.is_success() { - if let Some(name) = response.name { - if let Some(response_domain) = response.domain { - return Ok(format!( - "{}@{}", - name, - response_domain.name.unwrap_or(domain) - )); - } - } - } - - if let Some(message) = response.message { - return Err(Error::ResponseContent { status, message }); - } - if let Some(message) = response.error { - return Err(Error::ResponseContent { status, message }); - } - - Err("Unknown ForwardEmail error.".into()) -} - -#[cfg(test)] -mod tests { - use serde_json::json; - - #[tokio::test] - async fn test_mock_server() { - use wiremock::{matchers, Mock, ResponseTemplate}; - - let (server, _client) = crate::util::start_mock(vec![ - // Mock the request to the ForwardEmail API, and verify that the correct request is made - Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authorization", "Basic TVlfVE9LRU46")) - .and(matchers::body_json(json!({ - "labels": "example.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "name": "wertg8ad", - "domain": { - "name": "mydomain.com" - } - }))) - .expect(1), - // Mock an invalid API token request - Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header( - "Authorization", - "Basic TVlfRkFLRV9UT0tFTjo=", - )) - .and(matchers::body_json(json!({ - "labels": "example.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(401).set_body_json(json!({ - "statusCode": 401, - "error": "Unauthorized", - "message": "Invalid API token." - }))) - .expect(1), - // Mock a free API token request - Mock::given(matchers::path("/v1/domains/mydomain.com/aliases")) - .and(matchers::method("POST")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header( - "Authorization", - "Basic TVlfRlJFRV9UT0tFTjo=", - )) - .and(matchers::body_json(json!({ - "labels": "example.com", - "description": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(402).set_body_json(json!({ - "statusCode": 402, - "error": "Payment required", - "message": "Please upgrade to a paid plan to unlock this feature." - }))) - .expect(1), - ]) - .await; - - let address = super::generate_with_api_url( - &reqwest::Client::new(), - "MY_TOKEN".into(), - "mydomain.com".into(), - Some("example.com".into()), - format!("http://{}", server.address()), - ) - .await - .unwrap(); - assert_eq!(address, "wertg8ad@mydomain.com"); - - let invalid_token_error = super::generate_with_api_url( - &reqwest::Client::new(), - "MY_FAKE_TOKEN".into(), - "mydomain.com".into(), - Some("example.com".into()), - format!("http://{}", server.address()), - ) - .await - .unwrap_err(); - - assert!(invalid_token_error - .to_string() - .contains("Invalid Forward Email API key.")); - - let free_token_error = super::generate_with_api_url( - &reqwest::Client::new(), - "MY_FREE_TOKEN".into(), - "mydomain.com".into(), - Some("example.com".into()), - format!("http://{}", server.address()), - ) - .await - .unwrap_err(); - - assert!(free_token_error - .to_string() - .contains("Please upgrade to a paid plan")); - - server.verify().await; - } -} diff --git a/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs b/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs deleted file mode 100644 index 6c4f9dab4..000000000 --- a/crates/bitwarden/src/tool/generators/username_forwarders/simplelogin.rs +++ /dev/null @@ -1,114 +0,0 @@ -use reqwest::{header::CONTENT_TYPE, StatusCode}; - -use crate::error::Result; - -pub async fn generate( - http: &reqwest::Client, - api_key: String, - website: Option, -) -> Result { - generate_with_api_url(http, api_key, website, "https://app.simplelogin.io".into()).await -} - -async fn generate_with_api_url( - http: &reqwest::Client, - api_key: String, - website: Option, - api_url: String, -) -> Result { - let query = website - .as_ref() - .map(|w| format!("?hostname={}", w)) - .unwrap_or_default(); - - let note = super::format_description(&website); - - #[derive(serde::Serialize)] - struct Request { - note: String, - } - - let response = http - .post(format!("{api_url}/api/alias/random/new{query}")) - .header(CONTENT_TYPE, "application/json") - .header("Authentication", api_key) - .json(&Request { note }) - .send() - .await?; - - if response.status() == StatusCode::UNAUTHORIZED { - return Err("Invalid SimpleLogin API key.".into()); - } - - // Throw any other errors - response.error_for_status_ref()?; - - #[derive(serde::Deserialize)] - struct Response { - alias: String, - } - let response: Response = response.json().await?; - - Ok(response.alias) -} - -#[cfg(test)] -mod tests { - use serde_json::json; - #[tokio::test] - async fn test_mock_server() { - use wiremock::{matchers, Mock, ResponseTemplate}; - - let (server, _client) = crate::util::start_mock(vec![ - // Mock the request to the SimpleLogin API, and verify that the correct request is made - Mock::given(matchers::path("/api/alias/random/new")) - .and(matchers::method("POST")) - .and(matchers::query_param("hostname", "example.com")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authentication", "MY_TOKEN")) - .and(matchers::body_json(json!({ - "note": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(201).set_body_json(json!({ - "alias": "simplelogin.yut3g8@aleeas.com", - }))) - .expect(1), - // Mock an invalid token request - Mock::given(matchers::path("/api/alias/random/new")) - .and(matchers::method("POST")) - .and(matchers::query_param("hostname", "example.com")) - .and(matchers::header("Content-Type", "application/json")) - .and(matchers::header("Authentication", "MY_FAKE_TOKEN")) - .and(matchers::body_json(json!({ - "note": "Website: example.com. Generated by Bitwarden." - }))) - .respond_with(ResponseTemplate::new(401)) - .expect(1), - ]) - .await; - - let address = super::generate_with_api_url( - &reqwest::Client::new(), - "MY_TOKEN".into(), - Some("example.com".into()), - format!("http://{}", server.address()), - ) - .await - .unwrap(); - assert_eq!(address, "simplelogin.yut3g8@aleeas.com"); - - let fake_token_error = super::generate_with_api_url( - &reqwest::Client::new(), - "MY_FAKE_TOKEN".into(), - Some("example.com".into()), - format!("http://{}", server.address()), - ) - .await - .unwrap_err(); - assert!(fake_token_error - .to_string() - .contains("Invalid SimpleLogin API key.")); - - server.verify().await; - } -} diff --git a/crates/bitwarden/src/tool/mod.rs b/crates/bitwarden/src/tool/mod.rs index fe41b68db..a94528163 100644 --- a/crates/bitwarden/src/tool/mod.rs +++ b/crates/bitwarden/src/tool/mod.rs @@ -1,8 +1,4 @@ mod exporters; -mod generators; - pub use exporters::{ClientExporters, ExportFormat}; -pub use generators::{ - AppendType, ClientGenerator, ForwarderServiceType, PassphraseGeneratorRequest, - PasswordGeneratorRequest, UsernameGeneratorRequest, -}; +mod client_generator; +pub use client_generator::ClientGenerator; diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index 038c3d7ee..f6568986d 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -27,18 +27,6 @@ const INDIFFERENT: GeneralPurposeConfig = pub const STANDARD_INDIFFERENT: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, INDIFFERENT); -#[cfg(feature = "mobile")] -pub(crate) fn capitalize_first_letter(s: &str) -> String { - // Unicode case conversion can change the length of the string, so we can't capitalize in place. - // Instead we extract the first character and convert it to uppercase. This returns - // an iterator which we collect into a string, and then append the rest of the input. - let mut c = s.chars(); - match c.next() { - None => String::new(), - Some(f) => f.to_uppercase().collect::() + c.as_str(), - } -} - #[cfg(test)] pub async fn start_mock(mocks: Vec) -> (wiremock::MockServer, crate::Client) { let server = wiremock::MockServer::start().await; diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index 236aef22d..0e7cd975e 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -1,7 +1,7 @@ use bitwarden::{ auth::RegisterRequest, client::client_settings::ClientSettings, - tool::{PassphraseGeneratorRequest, PasswordGeneratorRequest}, + generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest}, }; use bitwarden_cli::{install_color_eyre, text_prompt_when_none, Color}; use clap::{command, Args, CommandFactory, Parser, Subcommand}; From 3689f590faae6da232b6ce9161ef9efd48d1ed2c Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 19 Jan 2024 16:28:48 +0100 Subject: [PATCH 205/378] Update mac handling in decrypting vault items to discard invalid items (#516) Tweaks the decryption logic to discard bad data rather than returning an error. We should re-evaluate this in the future and potentially include some metadata about the failure so that the applications can show a warning about corrupt data. --- crates/bitwarden/src/vault/cipher/card.rs | 12 +++---- crates/bitwarden/src/vault/cipher/cipher.rs | 24 ++++++------- crates/bitwarden/src/vault/cipher/field.rs | 4 +-- crates/bitwarden/src/vault/cipher/identity.rs | 36 +++++++++---------- crates/bitwarden/src/vault/cipher/login.rs | 8 ++--- crates/bitwarden/src/vault/collection.rs | 2 +- crates/bitwarden/src/vault/folder.rs | 2 +- .../bitwarden/src/vault/password_history.rs | 2 +- crates/bitwarden/src/vault/send.rs | 8 ++--- 9 files changed, 49 insertions(+), 49 deletions(-) diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 05c3aa631..cd61a17d8 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -47,12 +47,12 @@ impl KeyEncryptable for CardView { impl KeyDecryptable for Card { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { - cardholder_name: self.cardholder_name.decrypt_with_key(key)?, - exp_month: self.exp_month.decrypt_with_key(key)?, - exp_year: self.exp_year.decrypt_with_key(key)?, - code: self.code.decrypt_with_key(key)?, - brand: self.brand.decrypt_with_key(key)?, - number: self.number.decrypt_with_key(key)?, + cardholder_name: self.cardholder_name.decrypt_with_key(key).ok().flatten(), + exp_month: self.exp_month.decrypt_with_key(key).ok().flatten(), + exp_year: self.exp_year.decrypt_with_key(key).ok().flatten(), + code: self.code.decrypt_with_key(key).ok().flatten(), + brand: self.brand.decrypt_with_key(key).ok().flatten(), + number: self.number.decrypt_with_key(key).ok().flatten(), }) } } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 010f3cd8a..9552c83c1 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -182,22 +182,22 @@ impl KeyDecryptable for Cipher { folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), key: self.key.clone(), - name: self.name.decrypt_with_key(key)?, - notes: self.notes.decrypt_with_key(key)?, + name: self.name.decrypt_with_key(key).ok().unwrap_or_default(), + notes: self.notes.decrypt_with_key(key).ok().flatten(), r#type: self.r#type, - login: self.login.decrypt_with_key(key)?, - identity: self.identity.decrypt_with_key(key)?, - card: self.card.decrypt_with_key(key)?, - secure_note: self.secure_note.decrypt_with_key(key)?, + login: self.login.decrypt_with_key(key).ok().flatten(), + identity: self.identity.decrypt_with_key(key).ok().flatten(), + card: self.card.decrypt_with_key(key).ok().flatten(), + secure_note: self.secure_note.decrypt_with_key(key).ok().flatten(), favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, edit: self.edit, view_password: self.view_password, - local_data: self.local_data.decrypt_with_key(key)?, - attachments: self.attachments.decrypt_with_key(key)?, - fields: self.fields.decrypt_with_key(key)?, - password_history: self.password_history.decrypt_with_key(key)?, + local_data: self.local_data.decrypt_with_key(key).ok().flatten(), + attachments: self.attachments.decrypt_with_key(key).ok().flatten(), + fields: self.fields.decrypt_with_key(key).ok().flatten(), + password_history: self.password_history.decrypt_with_key(key).ok().flatten(), creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, @@ -298,8 +298,8 @@ impl KeyDecryptable for Cipher { organization_id: self.organization_id, folder_id: self.folder_id, collection_ids: self.collection_ids.clone(), - name: self.name.decrypt_with_key(key)?, - sub_title: self.get_decrypted_subtitle(key)?, + name: self.name.decrypt_with_key(key).ok().unwrap_or_default(), + sub_title: self.get_decrypted_subtitle(key).ok().unwrap_or_default(), r#type: self.r#type, favorite: self.favorite, reprompt: self.reprompt, diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 6bb106c32..db896474f 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -55,8 +55,8 @@ impl KeyEncryptable for FieldView { impl KeyDecryptable for Field { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { - name: self.name.decrypt_with_key(key)?, - value: self.value.decrypt_with_key(key)?, + name: self.name.decrypt_with_key(key).ok().flatten(), + value: self.value.decrypt_with_key(key).ok().flatten(), r#type: self.r#type, linked_id: self.linked_id, }) diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index c4154aeba..f59166eec 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -83,24 +83,24 @@ impl KeyEncryptable for IdentityView { impl KeyDecryptable for Identity { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { - title: self.title.decrypt_with_key(key)?, - first_name: self.first_name.decrypt_with_key(key)?, - middle_name: self.middle_name.decrypt_with_key(key)?, - last_name: self.last_name.decrypt_with_key(key)?, - address1: self.address1.decrypt_with_key(key)?, - address2: self.address2.decrypt_with_key(key)?, - address3: self.address3.decrypt_with_key(key)?, - city: self.city.decrypt_with_key(key)?, - state: self.state.decrypt_with_key(key)?, - postal_code: self.postal_code.decrypt_with_key(key)?, - country: self.country.decrypt_with_key(key)?, - company: self.company.decrypt_with_key(key)?, - email: self.email.decrypt_with_key(key)?, - phone: self.phone.decrypt_with_key(key)?, - ssn: self.ssn.decrypt_with_key(key)?, - username: self.username.decrypt_with_key(key)?, - passport_number: self.passport_number.decrypt_with_key(key)?, - license_number: self.license_number.decrypt_with_key(key)?, + title: self.title.decrypt_with_key(key).ok().flatten(), + first_name: self.first_name.decrypt_with_key(key).ok().flatten(), + middle_name: self.middle_name.decrypt_with_key(key).ok().flatten(), + last_name: self.last_name.decrypt_with_key(key).ok().flatten(), + address1: self.address1.decrypt_with_key(key).ok().flatten(), + address2: self.address2.decrypt_with_key(key).ok().flatten(), + address3: self.address3.decrypt_with_key(key).ok().flatten(), + city: self.city.decrypt_with_key(key).ok().flatten(), + state: self.state.decrypt_with_key(key).ok().flatten(), + postal_code: self.postal_code.decrypt_with_key(key).ok().flatten(), + country: self.country.decrypt_with_key(key).ok().flatten(), + company: self.company.decrypt_with_key(key).ok().flatten(), + email: self.email.decrypt_with_key(key).ok().flatten(), + phone: self.phone.decrypt_with_key(key).ok().flatten(), + ssn: self.ssn.decrypt_with_key(key).ok().flatten(), + username: self.username.decrypt_with_key(key).ok().flatten(), + passport_number: self.passport_number.decrypt_with_key(key).ok().flatten(), + license_number: self.license_number.decrypt_with_key(key).ok().flatten(), }) } } diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 139750d51..ea5b1f357 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -98,11 +98,11 @@ impl KeyDecryptable for LoginUri { impl KeyDecryptable for Login { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { - username: self.username.decrypt_with_key(key)?, - password: self.password.decrypt_with_key(key)?, + username: self.username.decrypt_with_key(key).ok().flatten(), + password: self.password.decrypt_with_key(key).ok().flatten(), password_revision_date: self.password_revision_date, - uris: self.uris.decrypt_with_key(key)?, - totp: self.totp.decrypt_with_key(key)?, + uris: self.uris.decrypt_with_key(key).ok().flatten(), + totp: self.totp.decrypt_with_key(key).ok().flatten(), autofill_on_page_load: self.autofill_on_page_load, }) } diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index a78209fc9..d20e5d729 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -51,7 +51,7 @@ impl KeyDecryptable for Collection { id: self.id, organization_id: self.organization_id, - name: self.name.decrypt_with_key(key)?, + name: self.name.decrypt_with_key(key).ok().unwrap_or_default(), external_id: self.external_id.clone(), hide_passwords: self.hide_passwords, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index a6b9790bc..17d1d40aa 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -43,7 +43,7 @@ impl KeyDecryptable for Folder { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, - name: self.name.decrypt_with_key(key)?, + name: self.name.decrypt_with_key(key).ok().unwrap_or_default(), revision_date: self.revision_date, }) } diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 333420b6a..2ec20116b 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -41,7 +41,7 @@ impl KeyDecryptable for PasswordHistory key: &SymmetricCryptoKey, ) -> Result { Ok(PasswordHistoryView { - password: self.password.decrypt_with_key(key)?, + password: self.password.decrypt_with_key(key).ok().unwrap_or_default(), last_used_date: self.last_used_date, }) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 8ed405b4c..b062ff9db 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -206,15 +206,15 @@ impl KeyDecryptable for Send { id: self.id, access_id: self.access_id.clone(), - name: self.name.decrypt_with_key(&key)?, - notes: self.notes.decrypt_with_key(&key)?, + name: self.name.decrypt_with_key(&key).ok().unwrap_or_default(), + notes: self.notes.decrypt_with_key(&key).ok().flatten(), key: Some(URL_SAFE_NO_PAD.encode(k)), new_password: None, has_password: self.password.is_some(), r#type: self.r#type, - file: self.file.decrypt_with_key(&key)?, - text: self.text.decrypt_with_key(&key)?, + file: self.file.decrypt_with_key(&key).ok().flatten(), + text: self.text.decrypt_with_key(&key).ok().flatten(), max_access_count: self.max_access_count, access_count: self.access_count, From ef09397f1cb9c7a436339a503bf2ae2433495e7f Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 19 Jan 2024 16:50:00 +0100 Subject: [PATCH 206/378] Add uniffi config for generators (#517) Add uniffi config --- crates/bitwarden-generators/uniffi.toml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 crates/bitwarden-generators/uniffi.toml diff --git a/crates/bitwarden-generators/uniffi.toml b/crates/bitwarden-generators/uniffi.toml new file mode 100644 index 000000000..923dd5e17 --- /dev/null +++ b/crates/bitwarden-generators/uniffi.toml @@ -0,0 +1,8 @@ +[bindings.kotlin] +package_name = "com.bitwarden.generators" +generate_immutable_records = true + +[bindings.swift] +ffi_module_name = "BitwardenGeneratorsFFI" +module_name = "BitwardenGenerators" +generate_immutable_records = true From b5b2c5c529f6fb3e51d7c7b02470ef793bde74cd Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 19 Jan 2024 19:52:01 +0100 Subject: [PATCH 207/378] Fix android not working properly (#518) It seems for uniffi to properly parse the uniffi.toml files it has to be a direct dependency and not transient like generators previously were. --- Cargo.lock | 1 + crates/bitwarden-uniffi/Cargo.toml | 3 +++ crates/bitwarden/src/tool/client_generator.rs | 7 ++++--- .../java/com/bitwarden/myapplication/MainActivity.kt | 2 +- languages/swift/build.sh | 10 +++------- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 960a7707f..75e6d8c0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -506,6 +506,7 @@ dependencies = [ "async-lock", "bitwarden", "bitwarden-crypto", + "bitwarden-generators", "chrono", "env_logger", "schemars", diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index eadaaf8d2..6dc940062 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -25,6 +25,9 @@ bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0", features = [ "mobile", ] } +bitwarden-generators = { path = "../bitwarden-generators", version = "=0.1.0", features = [ + "mobile", +] } [build-dependencies] uniffi = { version = "=0.25.2", features = ["build"] } diff --git a/crates/bitwarden/src/tool/client_generator.rs b/crates/bitwarden/src/tool/client_generator.rs index bf7c66ef3..c21eeb929 100644 --- a/crates/bitwarden/src/tool/client_generator.rs +++ b/crates/bitwarden/src/tool/client_generator.rs @@ -1,6 +1,7 @@ -use bitwarden_generators::{ - passphrase, password, username, PassphraseGeneratorRequest, PasswordGeneratorRequest, - UsernameGeneratorRequest, +use bitwarden_generators::{passphrase, password, username}; + +use crate::generators::{ + PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest, }; use crate::{error::Result, Client}; diff --git a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt index dd79ff870..f51d0309e 100644 --- a/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt +++ b/languages/kotlin/app/src/main/java/com/bitwarden/myapplication/MainActivity.kt @@ -27,9 +27,9 @@ import com.bitwarden.core.Folder import com.bitwarden.core.InitOrgCryptoRequest import com.bitwarden.core.InitUserCryptoMethod import com.bitwarden.core.InitUserCryptoRequest -import com.bitwarden.core.Kdf import com.bitwarden.core.Uuid import com.bitwarden.crypto.HashPurpose +import com.bitwarden.crypto.Kdf import com.bitwarden.myapplication.ui.theme.MyApplicationTheme import com.bitwarden.sdk.Client import io.ktor.client.HttpClient diff --git a/languages/swift/build.sh b/languages/swift/build.sh index 87f9cecdb..69bc9a881 100755 --- a/languages/swift/build.sh +++ b/languages/swift/build.sh @@ -28,16 +28,12 @@ cargo run -p uniffi-bindgen generate \ --out-dir tmp/bindings # Move generated swift bindings -mv ./tmp/bindings/BitwardenCore.swift ./Sources/BitwardenSdk/ -mv ./tmp/bindings/BitwardenCrypto.swift ./Sources/BitwardenSdk/ -mv ./tmp/bindings/BitwardenSDK.swift ./Sources/BitwardenSdk/ +mv ./tmp/bindings/*.swift ./Sources/BitwardenSdk/ # Massage the generated files to fit xcframework mkdir tmp/Headers -mv ./tmp/bindings/BitwardenCoreFFI.h ./tmp/Headers/ -mv ./tmp/bindings/BitwardenCryptoFFI.h ./tmp/Headers/ -mv ./tmp/bindings/BitwardenFFI.h ./tmp/Headers/ -cat ./tmp/bindings/BitwardenFFI.modulemap ./tmp/bindings/BitwardenCoreFFI.modulemap ./tmp/bindings/BitwardenCryptoFFI.modulemap > ./tmp/Headers/module.modulemap +mv ./tmp/bindings/*.h ./tmp/Headers/ +cat ./tmp/bindings/*.modulemap > ./tmp/Headers/module.modulemap # Build xcframework xcodebuild -create-xcframework \ From d6dd979ba1f8fef99852a41e93e498a44d16a023 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:29:13 +0100 Subject: [PATCH 208/378] [deps]: Update @types/node to v18.19.8 (#521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.7` -> `18.19.8`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.7/18.19.8) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.7/18.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.7/18.19.8?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 144a79f64..f5447f5fe 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.7.tgz", - "integrity": "sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==", + "version": "18.19.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.8.tgz", + "integrity": "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 716060355717e4da602ed5ad250c2d93c9a4ef0b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:29:37 +0100 Subject: [PATCH 209/378] [deps]: Update @openapitools/openapi-generator-cli to v2.9.0 (#526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@openapitools/openapi-generator-cli](https://togithub.com/OpenAPITools/openapi-generator-cli) | [`2.7.0` -> `2.9.0`](https://renovatebot.com/diffs/npm/@openapitools%2fopenapi-generator-cli/2.7.0/2.9.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@openapitools%2fopenapi-generator-cli/2.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@openapitools%2fopenapi-generator-cli/2.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@openapitools%2fopenapi-generator-cli/2.7.0/2.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@openapitools%2fopenapi-generator-cli/2.7.0/2.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
OpenAPITools/openapi-generator-cli (@​openapitools/openapi-generator-cli) ### [`v2.9.0`](https://togithub.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.9.0) [Compare Source](https://togithub.com/OpenAPITools/openapi-generator-cli/compare/v2.8.2...v2.9.0) ##### Features - **release:** trigger a release ([720b405](https://togithub.com/OpenAPITools/openapi-generator-cli/commit/720b405fd0984b6e9b510358418ea1b80ea3113b)) ### [`v2.8.2`](https://togithub.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.8.2) [Compare Source](https://togithub.com/OpenAPITools/openapi-generator-cli/compare/v2.8.1...v2.8.2) ##### Bug Fixes - **deps:** update dependency reflect-metadata to v0.2.1 ([#​739](https://togithub.com/OpenAPITools/openapi-generator-cli/issues/739)) ([ab79be5](https://togithub.com/OpenAPITools/openapi-generator-cli/commit/ab79be553de9eb555131db636b2e03801ce8021b)) ### [`v2.8.1`](https://togithub.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.8.1) [Compare Source](https://togithub.com/OpenAPITools/openapi-generator-cli/compare/v2.8.0...v2.8.1) ##### Bug Fixes - **deps:** update dependency inquirer to v8.2.6 ([#​733](https://togithub.com/OpenAPITools/openapi-generator-cli/issues/733)) ([ef2f694](https://togithub.com/OpenAPITools/openapi-generator-cli/commit/ef2f6948a4d8848317dfc22ea15162d484ce8081)) - **deps:** update dependency rxjs to v7.8.1 ([#​734](https://togithub.com/OpenAPITools/openapi-generator-cli/issues/734)) ([7a5c806](https://togithub.com/OpenAPITools/openapi-generator-cli/commit/7a5c8067401b27665eb828d03ae4e0f40a9f5c5b)) ### [`v2.8.0`](https://togithub.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.8.0) [Compare Source](https://togithub.com/OpenAPITools/openapi-generator-cli/compare/v2.7.0...v2.8.0) ##### Features - **release:** trigger a release ([7cc735e](https://togithub.com/OpenAPITools/openapi-generator-cli/commit/7cc735e8e2cd1e47beae51b292815c117f03592b))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 252 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 126 insertions(+), 128 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3e47d00a0..2535af9bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "license": "SEE LICENSE IN LICENSE", "devDependencies": { - "@openapitools/openapi-generator-cli": "2.7.0", + "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", "prettier": "3.2.2", "quicktype-core": "23.0.81", @@ -178,45 +178,93 @@ "node": ">=8" } }, - "node_modules/@nestjs/axios": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.1.0.tgz", - "integrity": "sha512-b2TT2X6BFbnNoeteiaxCIiHaFcSbVW+S5yygYqiIq5i6H77yIU3IVuLdpQkHq8/EqOWFwMopLN8jdkUT71Am9w==", + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", "dev": true, "dependencies": { - "axios": "0.27.2" + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@openapitools/openapi-generator-cli": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.9.0.tgz", + "integrity": "sha512-KQpftKeiMoH5aEI/amOVLFGkGeT3DyA7Atj7v7l8xT3O9xnIUpoDmMg0WBTEh+NHxEwEAITQNDzr+JLjkXVaKw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nestjs/axios": "3.0.1", + "@nestjs/common": "10.3.0", + "@nestjs/core": "10.3.0", + "@nuxtjs/opencollective": "0.3.2", + "axios": "1.6.5", + "chalk": "4.1.2", + "commander": "8.3.0", + "compare-versions": "4.1.4", + "concurrently": "6.5.1", + "console.table": "0.10.0", + "fs-extra": "10.1.0", + "glob": "7.2.3", + "inquirer": "8.2.6", + "lodash": "4.17.21", + "reflect-metadata": "0.1.13", + "rxjs": "7.8.1", + "tslib": "2.6.2" + }, + "bin": { + "openapi-generator-cli": "main.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openapi_generator" + } + }, + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.1.tgz", + "integrity": "sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ==", + "dev": true, "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0", + "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "axios": "^1.3.1", "reflect-metadata": "^0.1.12", "rxjs": "^6.0.0 || ^7.0.0" } }, - "node_modules/@nestjs/common": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-9.3.11.tgz", - "integrity": "sha512-IFZ2G/5UKWC2Uo7tJ4SxGed2+aiA+sJyWeWsGTogKVDhq90oxVBToh+uCDeI31HNUpqYGoWmkletfty42zUd8A==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.0.tgz", + "integrity": "sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==", "dev": true, "dependencies": { "iterare": "1.2.1", - "tslib": "2.5.0", - "uid": "2.0.1" + "tslib": "2.6.2", + "uid": "2.0.2" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/nest" }, "peerDependencies": { - "cache-manager": "<=5", "class-transformer": "*", "class-validator": "*", "reflect-metadata": "^0.1.12", "rxjs": "^7.1.0" }, "peerDependenciesMeta": { - "cache-manager": { - "optional": true - }, "class-transformer": { "optional": true }, @@ -225,16 +273,10 @@ } } }, - "node_modules/@nestjs/common/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "node_modules/@nestjs/core": { - "version": "9.3.11", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-9.3.11.tgz", - "integrity": "sha512-CI27a2JFd5rvvbgkalWqsiwQNhcP4EAG5BUK8usjp29wVp1kx30ghfBT8FLqIgmkRVo65A0IcEnWsxeXMntkxQ==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.0.tgz", + "integrity": "sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -242,18 +284,18 @@ "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", "path-to-regexp": "3.2.0", - "tslib": "2.5.0", - "uid": "2.0.1" + "tslib": "2.6.2", + "uid": "2.0.2" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@nestjs/common": "^9.0.0", - "@nestjs/microservices": "^9.0.0", - "@nestjs/platform-express": "^9.0.0", - "@nestjs/websockets": "^9.0.0", + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", "reflect-metadata": "^0.1.12", "rxjs": "^7.1.0" }, @@ -269,63 +311,27 @@ } } }, - "node_modules/@nestjs/core/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/axios": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dev": true, "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.7.0.tgz", - "integrity": "sha512-ieEpHTA/KsDz7ANw03lLPYyjdedDEXYEyYoGBRWdduqXWSX65CJtttjqa8ZaB1mNmIjMtchUHwAYQmTLVQ8HYg==", + "node_modules/@openapitools/openapi-generator-cli/node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@nestjs/axios": "0.1.0", - "@nestjs/common": "9.3.11", - "@nestjs/core": "9.3.11", - "@nuxtjs/opencollective": "0.3.2", - "chalk": "4.1.2", - "commander": "8.3.0", - "compare-versions": "4.1.4", - "concurrently": "6.5.1", - "console.table": "0.10.0", - "fs-extra": "10.1.0", - "glob": "7.1.6", - "inquirer": "8.2.5", - "lodash": "4.17.21", - "reflect-metadata": "0.1.13", - "rxjs": "7.8.0", - "tslib": "2.0.3" - }, - "bin": { - "openapi-generator-cli": "main.js" + "@lukeed/csprng": "^1.0.0" }, "engines": { - "node": ">=10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openapi_generator" + "node": ">=8" } }, "node_modules/@pkgjs/parseargs": { @@ -462,16 +468,6 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, - "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -922,9 +918,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -1013,15 +1009,15 @@ } }, "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -1117,9 +1113,9 @@ "dev": true }, "node_modules/inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", @@ -1136,12 +1132,26 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" + "wrap-ansi": "^6.0.1" }, "engines": { "node": ">=12.0.0" } }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1493,6 +1503,12 @@ "node": ">= 0.6.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/quicktype-core": { "version": "23.0.81", "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-23.0.81.tgz", @@ -1678,20 +1694,14 @@ } }, "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, "dependencies": { "tslib": "^2.1.0" } }, - "node_modules/rxjs/node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "dev": true - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1918,9 +1928,9 @@ } }, "node_modules/tslib": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", - "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/type-fest": { @@ -1961,18 +1971,6 @@ "node": ">=0.8.0" } }, - "node_modules/uid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.1.tgz", - "integrity": "sha512-PF+1AnZgycpAIEmNtjxGBVmKbZAQguaa4pBUq6KNaGEcpzZ2klCNZLM34tsjp76maN00TttiiUf6zkIBpJQm2A==", - "dev": true, - "dependencies": { - "@lukeed/csprng": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", diff --git a/package.json b/package.json index 2becd41f2..e233b8170 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "devDependencies": { - "@openapitools/openapi-generator-cli": "2.7.0", + "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", "prettier": "3.2.2", "quicktype-core": "23.0.81", From e294e806257884afc82262e1928240f7fbd9eb4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:29:59 +0100 Subject: [PATCH 210/378] [deps]: Update @napi-rs/cli to v2.18.0 (#527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@napi-rs/cli](https://togithub.com/napi-rs/napi-rs) | [`2.17.0` -> `2.18.0`](https://renovatebot.com/diffs/npm/@napi-rs%2fcli/2.17.0/2.18.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@napi-rs%2fcli/2.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@napi-rs%2fcli/2.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@napi-rs%2fcli/2.17.0/2.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@napi-rs%2fcli/2.17.0/2.18.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
napi-rs/napi-rs (@​napi-rs/cli) ### [`v2.18.0`](https://togithub.com/napi-rs/napi-rs/releases/tag/%40napi-rs/cli%402.18.0) [Compare Source](https://togithub.com/napi-rs/napi-rs/compare/@napi-rs/cli@2.17.0...@napi-rs/cli@2.18.0) #### What's Changed - chore: upgrade cli deps [@​Brooooooklyn](https://togithub.com/Brooooooklyn) https://github.com/napi-rs/napi-rs/commit/60c326e8eb4276134daabf41604168fafceb02bf - feat: update ci.yml and binding template [@​Brooooooklyn](https://togithub.com/Brooooooklyn) https://github.com/napi-rs/napi-rs/commit/f720c2d0346130f006f6de986fb37c41545f3666 **Full Changelog**: https://github.com/napi-rs/napi-rs/compare/[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).17.0...[@​napi-rs/cli](https://togithub.com/napi-rs/cli)[@​2](https://togithub.com/2).18.0
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-napi/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index e10a23742..27e945f60 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -55,9 +55,9 @@ } }, "node_modules/@napi-rs/cli": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.17.0.tgz", - "integrity": "sha512-/M7MZ3dIqyFs6c0Bxtk+SOobPq6vYWYqBLYCOKx3dYWqoyJNBEgmDKUTrxIZu9eHw9Ill3WyEoHPqS9P99cd8A==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.18.0.tgz", + "integrity": "sha512-lfSRT7cs3iC4L+kv9suGYQEezn5Nii7Kpu+THsYVI0tA1Vh59LH45p4QADaD7hvIkmOz79eEGtoKQ9nAkAPkzA==", "dev": true, "bin": { "napi": "scripts/index.js" From 25daa574e6fb78f7e5f69fe915a8993bdfbecf72 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 12:27:06 +0100 Subject: [PATCH 211/378] [deps]: Update Rust crate clap to 4.4.18 (#522) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap](https://togithub.com/clap-rs/clap) | dependencies | patch | `4.4.16` -> `4.4.18` | --- ### Release Notes
clap-rs/clap (clap) ### [`v4.4.18`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4418---2024-01-16) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.4.17...v4.4.18) ##### Fixes - *(error)* When lacking `usage` feature, ensure the list of required arguments is unique ### [`v4.4.17`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4417---2024-01-15) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.4.16...v4.4.17) ##### Fixes - Fix `panic!` when mixing `args_conflicts_with_subcommands` with `ArgGroup` (which is implicit with `derive`) introduced in 4.4.15
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75e6d8c0b..dc00dc15b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -725,9 +725,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.16" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58e54881c004cec7895b0068a0a954cd5d62da01aef83fa35b1e594497bf5445" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", "clap_derive", @@ -735,9 +735,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.16" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59cb82d7f531603d2fd1f507441cdd35184fa81beff7bd489570de7f773460bb" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 702232730..bded30904 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.57" [dependencies] -clap = { version = "4.4.16", features = ["derive"] } +clap = { version = "4.4.18", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "2.1.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 0ea4877f4..210a6b80a 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.16", features = ["derive", "env"] } +clap = { version = "4.4.18", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.10.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index c334d9c01..38568c539 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.31", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.16", features = ["derive", "env", "string"] } +clap = { version = "4.4.18", features = ["derive", "env", "string"] } clap_complete = "4.4.6" color-eyre = "0.6" comfy-table = "^7.1.0" From 0f07c2a59819f5ec7a6a3185af0242aa03053841 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 12:55:44 +0100 Subject: [PATCH 212/378] [deps]: Update Rust crate clap_complete to 4.4.8 (#523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap_complete](https://togithub.com/clap-rs/clap) ([source](https://togithub.com/clap-rs/clap/tree/HEAD/clap_complete)) | dependencies | patch | `4.4.6` -> `4.4.8` | --- ### Release Notes
clap-rs/clap (clap_complete) ### [`v4.4.8`](https://togithub.com/clap-rs/clap/blob/HEAD/clap_complete/CHANGELOG.md#448---2024-01-19) [Compare Source](https://togithub.com/clap-rs/clap/compare/clap_complete-v4.4.7...clap_complete-v4.4.8) ##### Fixes - *(bash)* be consistent in identifiers when custom bin names are used ### [`v4.4.7`](https://togithub.com/clap-rs/clap/blob/HEAD/clap_complete/CHANGELOG.md#447---2024-01-15) [Compare Source](https://togithub.com/clap-rs/clap/compare/clap_complete-v4.4.6...clap_complete-v4.4.7) ##### Fixes - *(unstable)* Don't have dynamic completions pollute the parent command's help output
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc00dc15b..f01b93b30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,9 +747,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.6" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" +checksum = "eaf7dcb7c21d8ca1a2482ee0f1d341f437c9a7af6ca6da359dc5e1b164e98215" dependencies = [ "clap", ] diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 38568c539..c2530af63 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.31", features = [ "std", ], default-features = false } clap = { version = "4.4.18", features = ["derive", "env", "string"] } -clap_complete = "4.4.6" +clap_complete = "4.4.8" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" From 57133cf3618571b08c8e9b0b5d155bcde947d327 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 22 Jan 2024 13:49:23 +0100 Subject: [PATCH 213/378] Swap out base32 decoding with custom implementation for totp (#528) Change base32 decoding for totp to use the same method as our other clients. --- Cargo.lock | 7 --- crates/bitwarden/Cargo.toml | 1 - crates/bitwarden/src/vault/totp.rs | 74 +++++++++++++++++------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f01b93b30..218a21ed5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,7 +352,6 @@ dependencies = [ "bitwarden-crypto", "bitwarden-generators", "chrono", - "data-encoding", "getrandom 0.2.11", "hmac", "log", @@ -1042,12 +1041,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "data-encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" - [[package]] name = "deadpool" version = "0.9.5" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 22ee6eaef..51c892ae1 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -37,7 +37,6 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -data-encoding = ">=2.5.0, <3.0" # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } hmac = ">=0.12.1, <0.13" diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 223c8c504..e99cbfabd 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -1,7 +1,6 @@ use std::{collections::HashMap, str::FromStr}; use chrono::{DateTime, Utc}; -use data_encoding::BASE32_NOPAD; use hmac::{Hmac, Mac}; use reqwest::Url; use schemars::JsonSchema; @@ -129,19 +128,6 @@ impl FromStr for Totp { /// - OTP Auth URI /// - Steam URI fn from_str(key: &str) -> Result { - fn decode_secret(secret: &str) -> Result> { - // Sanitize the secret to only contain allowed characters - let secret = secret - .to_uppercase() - .chars() - .filter(|c| BASE32_CHARS.contains(*c)) - .collect::(); - - BASE32_NOPAD - .decode(secret.as_bytes()) - .map_err(|e| e.to_string().into()) - } - let params = if key.starts_with("otpauth://") { let url = Url::parse(key).map_err(|_| "Unable to parse URL")?; let parts: HashMap<_, _> = url.query_pairs().collect(); @@ -166,26 +152,26 @@ impl FromStr for Totp { .and_then(|v| v.parse().ok()) .map(|v: u32| v.max(1)) .unwrap_or(DEFAULT_PERIOD), - secret: decode_secret( + secret: decode_b32( &parts .get("secret") .map(|v| v.to_string()) .ok_or("Missing secret in otpauth URI")?, - )?, + ), } } else if let Some(secret) = key.strip_prefix("steam://") { Totp { algorithm: Algorithm::Steam, digits: 5, period: DEFAULT_PERIOD, - secret: decode_secret(secret)?, + secret: decode_b32(secret), } } else { Totp { algorithm: DEFAULT_ALGORITHM, digits: DEFAULT_DIGITS, period: DEFAULT_PERIOD, - secret: decode_secret(key)?, + secret: decode_b32(key), } }; @@ -220,12 +206,42 @@ fn derive_binary(hash: Vec) -> u32 { | hash[offset + 3] as u32 } +/// This code is migrated from our javascript implementation and is not technically a correct base32 decoder since we filter out various characters, and use exact chunking. +fn decode_b32(s: &str) -> Vec { + let s = s.to_uppercase(); + + let mut bits = String::new(); + for c in s.chars() { + if let Some(i) = BASE32_CHARS.find(c) { + bits.push_str(&format!("{:05b}", i)); + } + } + let mut bytes = Vec::new(); + + for chunk in bits.as_bytes().chunks_exact(8) { + let byte_str = std::str::from_utf8(chunk).unwrap(); + let byte = u8::from_str_radix(byte_str, 2).unwrap(); + bytes.push(byte); + } + + bytes +} + #[cfg(test)] mod tests { use chrono::Utc; use super::*; + #[test] + fn test_decode_b32() { + let res = decode_b32("WQIQ25BRKZYCJVYP"); + assert_eq!(res, vec![180, 17, 13, 116, 49, 86, 112, 36, 215, 15]); + + let res = decode_b32("ABCD123"); + assert_eq!(res, vec![0, 68, 61]); + } + #[test] fn test_generate_totp() { let cases = vec![ @@ -234,6 +250,14 @@ mod tests { ("PIUDISEQYA", "829846"), // non padded ("PIUDISEQYA======", "829846"), // padded ("PIUD1IS!EQYA=", "829846"), // sanitized + // Steam + ("steam://HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", "7W6CJ"), + ("steam://ABCD123", "N26DF"), + // Various weird lengths + ("ddfdf", "932653"), + ("HJSGFJHDFDJDJKSDFD", "000034"), + ("xvdsfasdfasdasdghsgsdfg", "403786"), + ("KAKFJWOSFJ12NWL", "093430"), ]; let time = Some( @@ -277,18 +301,4 @@ mod tests { assert_eq!(response.code, "730364".to_string()); assert_eq!(response.period, 60); } - - #[test] - fn test_generate_steam() { - let key = "steam://HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ".to_string(); - let time = Some( - DateTime::parse_from_rfc3339("2023-01-01T00:00:00.000Z") - .unwrap() - .with_timezone(&Utc), - ); - let response = generate_totp(key, time).unwrap(); - - assert_eq!(response.code, "7W6CJ".to_string()); - assert_eq!(response.period, 30); - } } From 785e7c459a13ed336699c8c1a38a630e21eb3472 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:49:42 +0100 Subject: [PATCH 214/378] [deps]: Update prettier to v3.2.4 (#525) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`3.2.2` -> `3.2.4`](https://renovatebot.com/diffs/npm/prettier/3.2.2/3.2.4) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.2.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.2.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.2.2/3.2.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.2.2/3.2.4?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prettier/prettier (prettier) ### [`v3.2.4`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#324) [Compare Source](https://togithub.com/prettier/prettier/compare/3.2.3...3.2.4) [diff](https://togithub.com/prettier/prettier/compare/3.2.3...3.2.4) ##### Fix incorrect parser inference ([#​15947](https://togithub.com/prettier/prettier/pull/15947) by [@​fisker](https://togithub.com/fisker)) Files like `.eslintrc.json` were incorrectly formatted as JSONC files. ```jsx // Input prettier --file-info .eslintrc.json { "ignored": false, "inferredParser": "jsonc" } // Prettier 3.2.4 prettier --file-info .eslintrc.json { "ignored": false, "inferredParser": "json" } ``` ### [`v3.2.3`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#323) [Compare Source](https://togithub.com/prettier/prettier/compare/3.2.2...3.2.3) [diff](https://togithub.com/prettier/prettier/compare/3.2.2...3.2.3) ##### Throw errors for invalid code ([#​15881](https://togithub.com/prettier/prettier/pull/15881) by [@​fisker](https://togithub.com/fisker), [@​Josh-Cena](https://togithub.com/Josh-Cena), [@​auvred](https://togithub.com/auvred)) ```ts // Input 1++; // Prettier 3.2.2 1++; // Prettier 3.2.3 SyntaxError: Invalid left-hand side expression in unary operation (1:1) > 1 | 1++; | ^ ``` ```ts // Input try {} catch (error = 1){} // Prettier 3.2.2 try { } catch (error) {} // Prettier 3.2.3 SyntaxError: Catch clause variable cannot have an initializer. (1:23) > 1 | try {} catch (error = 1){} | ^ ``` ##### Fix parser inference ([#​15927](https://togithub.com/prettier/prettier/pull/15927) by [@​fisker](https://togithub.com/fisker)) ```console // Prettier 3.2.2 prettier --file-info tsconfig.json { "ignored": false, "inferredParser": "json" } // Prettier 3.2.3 prettier --file-info tsconfig.json { "ignored": false, "inferredParser": "jsonc" } ```
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Hinton --- crates/bitwarden-napi/tsconfig.json | 4 ++-- package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden-napi/tsconfig.json b/crates/bitwarden-napi/tsconfig.json index f977e0759..8ec7e00d4 100644 --- a/crates/bitwarden-napi/tsconfig.json +++ b/crates/bitwarden-napi/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, "noImplicitAny": true, "esModuleInterop": true, - "declaration": true + "declaration": true, }, - "include": ["src-ts", "src-ts/bitwarden_client", "src-ts/index.ts"] + "include": ["src-ts", "src-ts/bitwarden_client", "src-ts/index.ts"], } diff --git a/package-lock.json b/package-lock.json index 2535af9bd..07b2080f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", - "prettier": "3.2.2", + "prettier": "3.2.4", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", @@ -1480,9 +1480,9 @@ } }, "node_modules/prettier": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz", - "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index e233b8170..14b5692a0 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", - "prettier": "3.2.2", + "prettier": "3.2.4", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", From 0e9b64fb849b1a14afcc5ef327d28ca2f956629b Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 22 Jan 2024 15:32:13 +0100 Subject: [PATCH 215/378] Wrap rust comments (#512) Add a `rustfmt.toml` config with the following options: - comment_width: 100 - wrap_comments: true - group_imports: "StdExternalCrate" - imports_granularity: "Crate" This sorts and groups imports. And wraps long comments. Unfortunately all of these configs are "unstable" and we need nightly cargo-fmt in order to run them. --- .github/workflows/lint.yml | 7 ++++++- .../src/apis/access_policies_api.rs | 9 ++++++--- .../src/apis/collections_api.rs | 6 ++++-- .../bitwarden-api-api/src/apis/groups_api.rs | 3 ++- .../src/apis/organization_connections_api.rs | 6 ++++-- .../src/apis/organization_sponsorships_api.rs | 12 +++++++---- .../src/apis/organization_users_api.rs | 9 ++++++--- ...lf_hosted_organization_sponsorships_api.rs | 9 ++++++--- .../src/models/sso_configuration_data.rs | 5 ++++- crates/bitwarden-crypto/src/aes.rs | 3 ++- .../src/enc_string/asymmetric.rs | 17 ++++++++-------- .../src/enc_string/symmetric.rs | 6 +++--- .../src/keys/shareable_key.rs | 3 ++- crates/bitwarden-generators/src/passphrase.rs | 12 +++++++---- crates/bitwarden-generators/src/password.rs | 9 ++++++--- crates/bitwarden-json/src/command.rs | 20 ++----------------- crates/bitwarden-napi/src/client.rs | 3 ++- crates/bitwarden-uniffi/src/crypto.rs | 14 ++++++++----- crates/bitwarden-uniffi/src/error.rs | 3 ++- crates/bitwarden-wasm/src/client.rs | 4 ++-- crates/bitwarden/src/admin_console/policy.rs | 14 +++++++------ crates/bitwarden/src/auth/login/password.rs | 6 ++++-- crates/bitwarden/src/client/access_token.rs | 3 ++- .../bitwarden/src/client/client_settings.rs | 4 ++-- .../src/client/encryption_settings.rs | 10 ++++++---- crates/bitwarden/src/lib.rs | 1 - crates/bitwarden/src/mobile/crypto.rs | 3 ++- .../bitwarden/src/mobile/vault/client_totp.rs | 1 - .../platform/secret_verification_request.rs | 9 +++++---- crates/bitwarden/src/platform/sync.rs | 3 ++- crates/bitwarden/src/tool/client_generator.rs | 15 +++++++------- .../bitwarden/src/vault/cipher/attachment.rs | 7 +++---- crates/bitwarden/src/vault/cipher/cipher.rs | 3 ++- crates/bitwarden/src/vault/send.rs | 15 ++++++++------ crates/bitwarden/src/vault/totp.rs | 3 ++- crates/bws/src/render.rs | 6 ++++-- crates/sdk-schemas/src/main.rs | 8 +++++--- rustfmt.toml | 7 +++++++ 38 files changed, 164 insertions(+), 114 deletions(-) create mode 100644 rustfmt.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index dbf357d3b..2f8989f91 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -24,11 +24,16 @@ jobs: with: toolchain: stable + - name: Install rust nightly + run: | + rustup toolchain install nightly + rustup component add rustfmt --toolchain nightly-x86_64-unknown-linux-gnu + - name: Cache cargo registry uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Cargo fmt - run: cargo fmt --check + run: cargo +nightly fmt --check - name: Set up Node uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 diff --git a/crates/bitwarden-api-api/src/apis/access_policies_api.rs b/crates/bitwarden-api-api/src/apis/access_policies_api.rs index 7e538c0b4..9eb40719d 100644 --- a/crates/bitwarden-api-api/src/apis/access_policies_api.rs +++ b/crates/bitwarden-api-api/src/apis/access_policies_api.rs @@ -27,21 +27,24 @@ pub enum AccessPoliciesIdPutError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_id_access_policies_people_potential_grantees_get`] +/// struct for typed errors of method +/// [`organizations_id_access_policies_people_potential_grantees_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsIdAccessPoliciesPeoplePotentialGranteesGetError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_id_access_policies_projects_potential_grantees_get`] +/// struct for typed errors of method +/// [`organizations_id_access_policies_projects_potential_grantees_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsIdAccessPoliciesProjectsPotentialGranteesGetError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_id_access_policies_service_accounts_potential_grantees_get`] +/// struct for typed errors of method +/// [`organizations_id_access_policies_service_accounts_potential_grantees_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsIdAccessPoliciesServiceAccountsPotentialGranteesGetError { diff --git a/crates/bitwarden-api-api/src/apis/collections_api.rs b/crates/bitwarden-api-api/src/apis/collections_api.rs index 02ac6eb16..c95ac5529 100644 --- a/crates/bitwarden-api-api/src/apis/collections_api.rs +++ b/crates/bitwarden-api-api/src/apis/collections_api.rs @@ -62,7 +62,8 @@ pub enum OrganizationsOrgIdCollectionsIdDeletePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_collections_id_delete_user_org_user_id_post`] +/// struct for typed errors of method +/// [`organizations_org_id_collections_id_delete_user_org_user_id_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdCollectionsIdDeleteUserOrgUserIdPostError { @@ -97,7 +98,8 @@ pub enum OrganizationsOrgIdCollectionsIdPutError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_collections_id_user_org_user_id_delete`] +/// struct for typed errors of method +/// [`organizations_org_id_collections_id_user_org_user_id_delete`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdCollectionsIdUserOrgUserIdDeleteError { diff --git a/crates/bitwarden-api-api/src/apis/groups_api.rs b/crates/bitwarden-api-api/src/apis/groups_api.rs index 46ed9afa5..d52fcd200 100644 --- a/crates/bitwarden-api-api/src/apis/groups_api.rs +++ b/crates/bitwarden-api-api/src/apis/groups_api.rs @@ -48,7 +48,8 @@ pub enum OrganizationsOrgIdGroupsIdDeletePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_groups_id_delete_user_org_user_id_post`] +/// struct for typed errors of method +/// [`organizations_org_id_groups_id_delete_user_org_user_id_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdGroupsIdDeleteUserOrgUserIdPostError { diff --git a/crates/bitwarden-api-api/src/apis/organization_connections_api.rs b/crates/bitwarden-api-api/src/apis/organization_connections_api.rs index 8bf41ffd1..ee75716dc 100644 --- a/crates/bitwarden-api-api/src/apis/organization_connections_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_connections_api.rs @@ -20,14 +20,16 @@ pub enum OrganizationsConnectionsEnabledGetError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_connections_organization_connection_id_delete`] +/// struct for typed errors of method +/// [`organizations_connections_organization_connection_id_delete`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsConnectionsOrganizationConnectionIdDeleteError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_connections_organization_connection_id_delete_post`] +/// struct for typed errors of method +/// [`organizations_connections_organization_connection_id_delete_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsConnectionsOrganizationConnectionIdDeletePostError { diff --git a/crates/bitwarden-api-api/src/apis/organization_sponsorships_api.rs b/crates/bitwarden-api-api/src/apis/organization_sponsorships_api.rs index 203174fdf..e3f1ccf24 100644 --- a/crates/bitwarden-api-api/src/apis/organization_sponsorships_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_sponsorships_api.rs @@ -27,21 +27,24 @@ pub enum OrganizationSponsorshipSponsoredSponsoredOrgIdDeleteError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_sponsored_sponsored_org_id_remove_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_sponsored_sponsored_org_id_remove_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSponsoredSponsoredOrgIdRemovePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_sponsoring_org_id_families_for_enterprise_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_sponsoring_org_id_families_for_enterprise_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSponsoringOrgIdFamiliesForEnterprisePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_sponsoring_org_id_families_for_enterprise_resend_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_sponsoring_org_id_families_for_enterprise_resend_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSponsoringOrgIdFamiliesForEnterpriseResendPostError { @@ -62,7 +65,8 @@ pub enum OrganizationSponsorshipSponsoringOrganizationIdDeleteError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_sponsoring_organization_id_delete_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_sponsoring_organization_id_delete_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSponsoringOrganizationIdDeletePostError { diff --git a/crates/bitwarden-api-api/src/apis/organization_users_api.rs b/crates/bitwarden-api-api/src/apis/organization_users_api.rs index 5a8e99916..804a29019 100644 --- a/crates/bitwarden-api-api/src/apis/organization_users_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_users_api.rs @@ -174,14 +174,16 @@ pub enum OrganizationsOrgIdUsersInvitePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_users_organization_user_id_accept_init_post`] +/// struct for typed errors of method +/// [`organizations_org_id_users_organization_user_id_accept_init_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdUsersOrganizationUserIdAcceptInitPostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_users_organization_user_id_accept_post`] +/// struct for typed errors of method +/// [`organizations_org_id_users_organization_user_id_accept_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdUsersOrganizationUserIdAcceptPostError { @@ -230,7 +232,8 @@ pub enum OrganizationsOrgIdUsersRevokePutError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organizations_org_id_users_user_id_reset_password_enrollment_put`] +/// struct for typed errors of method +/// [`organizations_org_id_users_user_id_reset_password_enrollment_put`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationsOrgIdUsersUserIdResetPasswordEnrollmentPutError { diff --git a/crates/bitwarden-api-api/src/apis/self_hosted_organization_sponsorships_api.rs b/crates/bitwarden-api-api/src/apis/self_hosted_organization_sponsorships_api.rs index dc2da4103..60b8a6d28 100644 --- a/crates/bitwarden-api-api/src/apis/self_hosted_organization_sponsorships_api.rs +++ b/crates/bitwarden-api-api/src/apis/self_hosted_organization_sponsorships_api.rs @@ -13,21 +13,24 @@ use reqwest; use super::{configuration, Error}; use crate::apis::ResponseContent; -/// struct for typed errors of method [`organization_sponsorship_self_hosted_sponsoring_org_id_delete`] +/// struct for typed errors of method +/// [`organization_sponsorship_self_hosted_sponsoring_org_id_delete`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSelfHostedSponsoringOrgIdDeleteError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_self_hosted_sponsoring_org_id_delete_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_self_hosted_sponsoring_org_id_delete_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSelfHostedSponsoringOrgIdDeletePostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`organization_sponsorship_self_hosted_sponsoring_org_id_families_for_enterprise_post`] +/// struct for typed errors of method +/// [`organization_sponsorship_self_hosted_sponsoring_org_id_families_for_enterprise_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum OrganizationSponsorshipSelfHostedSponsoringOrgIdFamiliesForEnterprisePostError { diff --git a/crates/bitwarden-api-api/src/models/sso_configuration_data.rs b/crates/bitwarden-api-api/src/models/sso_configuration_data.rs index 0e2890ad9..2d898488e 100644 --- a/crates/bitwarden-api-api/src/models/sso_configuration_data.rs +++ b/crates/bitwarden-api-api/src/models/sso_configuration_data.rs @@ -17,7 +17,10 @@ pub struct SsoConfigurationData { skip_serializing_if = "Option::is_none" )] pub member_decryption_type: Option, - /// Legacy property to determine if KeyConnector was enabled. Kept for backwards compatibility with old configs that will not have the new Bit.Core.Auth.Models.Data.SsoConfigurationData.MemberDecryptionType when deserialized from the database. + /// Legacy property to determine if KeyConnector was enabled. Kept for backwards compatibility + /// with old configs that will not have the new + /// Bit.Core.Auth.Models.Data.SsoConfigurationData.MemberDecryptionType when deserialized from + /// the database. #[serde( rename = "keyConnectorEnabled", skip_serializing_if = "Option::is_none" diff --git a/crates/bitwarden-crypto/src/aes.rs b/crates/bitwarden-crypto/src/aes.rs index cb4bf3102..e948fdc18 100644 --- a/crates/bitwarden-crypto/src/aes.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -32,7 +32,8 @@ pub(crate) fn decrypt_aes256( .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; - // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, we truncate to the subslice length + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, + // we truncate to the subslice length let decrypted_len = decrypted_key_slice.len(); data.truncate(decrypted_len); diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 4c1dc3c8c..81ac81a5b 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -12,12 +12,12 @@ use crate::{ /// # Encrypted string primitive /// -/// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. -/// They are used together with the KeyDecryptable and KeyEncryptable traits to encrypt and decrypt data using -/// [AsymmetricCryptoKey]s. +/// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically +/// encrypted string. They are used together with the KeyDecryptable and KeyEncryptable traits to +/// encrypt and decrypt data using [AsymmetricCryptoKey]s. /// -/// The flexibility of the [AsymmetricEncString] type allows for different encryption algorithms to be used -/// which is represented by the different variants of the enum. +/// The flexibility of the [AsymmetricEncString] type allows for different encryption algorithms to +/// be used which is represented by the different variants of the enum. /// /// ## Note /// @@ -30,8 +30,8 @@ use crate::{ /// /// ## Serialization /// -/// [AsymmetricEncString] implements [Display] and [FromStr] to allow for easy serialization and uses a -/// custom scheme to represent the different variants. +/// [AsymmetricEncString] implements [Display] and [FromStr] to allow for easy serialization and +/// uses a custom scheme to represent the different variants. /// /// The scheme is one of the following schemes: /// - `[type].[data]` @@ -54,7 +54,8 @@ pub enum AsymmetricEncString { Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec, mac: Vec }, } -/// To avoid printing sensitive information, [AsymmetricEncString] debug prints to `AsymmetricEncString`. +/// To avoid printing sensitive information, [AsymmetricEncString] debug prints to +/// `AsymmetricEncString`. impl std::fmt::Debug for AsymmetricEncString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("AsymmetricEncString").finish() diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index d6dd44374..25a0a8280 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -12,9 +12,9 @@ use crate::{ /// # Encrypted string primitive /// -/// [EncString] is a Bitwarden specific primitive that represents a symmetrically encrypted string. They are -/// are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and decrypt -/// data using [SymmetricCryptoKey]s. +/// [EncString] is a Bitwarden specific primitive that represents a symmetrically encrypted string. +/// They are are used together with the [KeyDecryptable] and [KeyEncryptable] traits to encrypt and +/// decrypt data using [SymmetricCryptoKey]s. /// /// The flexibility of the [EncString] type allows for different encryption algorithms to be used /// which is represented by the different variants of the enum. diff --git a/crates/bitwarden-crypto/src/keys/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs index a13f17155..eb5353401 100644 --- a/crates/bitwarden-crypto/src/keys/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -14,7 +14,8 @@ pub fn derive_shareable_key( ) -> SymmetricCryptoKey { // Because all inputs are fixed size, we can unwrap all errors here without issue - // TODO: Are these the final `key` and `info` parameters or should we change them? I followed the pattern used for sends + // TODO: Are these the final `key` and `info` parameters or should we change them? I followed + // the pattern used for sends let res = Hmac::::new_from_slice(format!("bitwarden-{}", name).as_bytes()) .unwrap() .chain_update(secret) diff --git a/crates/bitwarden-generators/src/passphrase.rs b/crates/bitwarden-generators/src/passphrase.rs index 4094e4b70..f8329a80c 100644 --- a/crates/bitwarden-generators/src/passphrase.rs +++ b/crates/bitwarden-generators/src/passphrase.rs @@ -26,7 +26,8 @@ pub struct PassphraseGeneratorRequest { pub word_separator: String, /// When set to true, capitalize the first letter of each word in the generated passphrase. pub capitalize: bool, - /// When set to true, include a number at the end of one of the words in the generated passphrase. + /// When set to true, include a number at the end of one of the words in the generated + /// passphrase. pub include_number: bool, } @@ -45,7 +46,8 @@ const MINIMUM_PASSPHRASE_NUM_WORDS: u8 = 3; const MAXIMUM_PASSPHRASE_NUM_WORDS: u8 = 20; /// Represents a set of valid options to generate a passhprase with. -/// To get an instance of it, use [`PassphraseGeneratorRequest::validate_options`](PassphraseGeneratorRequest::validate_options) +/// To get an instance of it, use +/// [`PassphraseGeneratorRequest::validate_options`](PassphraseGeneratorRequest::validate_options) struct ValidPassphraseGeneratorOptions { pub(super) num_words: u8, pub(super) word_separator: String, @@ -54,7 +56,8 @@ struct ValidPassphraseGeneratorOptions { } impl PassphraseGeneratorRequest { - /// Validates the request and returns an immutable struct with valid options to use with the passphrase generator. + /// Validates the request and returns an immutable struct with valid options to use with the + /// passphrase generator. fn validate_options(self) -> Result { // TODO: Add password generator policy checks @@ -173,7 +176,8 @@ mod tests { let input = PassphraseGeneratorRequest { num_words: 4, - word_separator: "👨🏻‍❤️‍💋‍👨🏻".into(), // This emoji is 35 bytes long, but represented as a single character + word_separator: "👨🏻‍❤️‍💋‍👨🏻".into(), /* This emoji is 35 bytes long, but represented + * as a single character */ capitalize: false, include_number: true, } diff --git a/crates/bitwarden-generators/src/password.rs b/crates/bitwarden-generators/src/password.rs index c7a8fc252..6cab6dd65 100644 --- a/crates/bitwarden-generators/src/password.rs +++ b/crates/bitwarden-generators/src/password.rs @@ -85,7 +85,8 @@ impl CharSet { self.include_if(true, other) } - /// Includes the given characters in the set if the predicate is true. Any duplicate items will be ignored + /// Includes the given characters in the set if the predicate is true. Any duplicate items will + /// be ignored pub fn include_if(mut self, predicate: bool, other: impl IntoIterator) -> Self { if predicate { self.0.extend(other); @@ -122,7 +123,8 @@ impl Distribution for CharSet { } /// Represents a set of valid options to generate a password with. -/// To get an instance of it, use [`PasswordGeneratorRequest::validate_options`](PasswordGeneratorRequest::validate_options) +/// To get an instance of it, use +/// [`PasswordGeneratorRequest::validate_options`](PasswordGeneratorRequest::validate_options) struct PasswordGeneratorOptions { pub(super) lower: (CharSet, usize), pub(super) upper: (CharSet, usize), @@ -134,7 +136,8 @@ struct PasswordGeneratorOptions { } impl PasswordGeneratorRequest { - /// Validates the request and returns an immutable struct with valid options to use with the password generator. + /// Validates the request and returns an immutable struct with valid options to use with the + /// password generator. fn validate_options(self) -> Result { // TODO: Add password generator policy checks diff --git a/crates/bitwarden-json/src/command.rs b/crates/bitwarden-json/src/command.rs index 855a30399..8da5e8cbd 100644 --- a/crates/bitwarden-json/src/command.rs +++ b/crates/bitwarden-json/src/command.rs @@ -33,7 +33,6 @@ pub enum Command { /// This command is not capable of handling authentication requiring 2fa or captcha. /// /// Returns: [PasswordLoginResponse](bitwarden::auth::login::PasswordLoginResponse) - /// PasswordLogin(PasswordLoginRequest), #[cfg(feature = "internal")] @@ -42,7 +41,6 @@ pub enum Command { /// This command is for initiating an authentication handshake with Bitwarden. /// /// Returns: [ApiKeyLoginResponse](bitwarden::auth::login::ApiKeyLoginResponse) - /// ApiKeyLogin(ApiKeyLoginRequest), #[cfg(feature = "secrets")] @@ -51,7 +49,6 @@ pub enum Command { /// This command is for initiating an authentication handshake with Bitwarden. /// /// Returns: [ApiKeyLoginResponse](bitwarden::auth::login::ApiKeyLoginResponse) - /// AccessTokenLogin(AccessTokenLoginRequest), #[cfg(feature = "internal")] @@ -59,14 +56,12 @@ pub enum Command { /// Get the API key of the currently authenticated user /// /// Returns: [UserApiKeyResponse](bitwarden::platform::UserApiKeyResponse) - /// GetUserApiKey(SecretVerificationRequest), #[cfg(feature = "internal")] /// Get the user's passphrase /// /// Returns: String - /// Fingerprint(FingerprintRequest), #[cfg(feature = "internal")] @@ -74,7 +69,6 @@ pub enum Command { /// Retrieve all user data, ciphers and organizations the user is a part of /// /// Returns: [SyncResponse](bitwarden::platform::SyncResponse) - /// Sync(SyncRequest), #[cfg(feature = "secrets")] @@ -92,7 +86,6 @@ pub enum SecretsCommand { /// Retrieve a secret by the provided identifier /// /// Returns: [SecretResponse](bitwarden::secrets_manager::secrets::SecretResponse) - /// Get(SecretGetRequest), /// > Requires Authentication @@ -100,7 +93,6 @@ pub enum SecretsCommand { /// Retrieve secrets by the provided identifiers /// /// Returns: [SecretsResponse](bitwarden::secrets_manager::secrets::SecretsResponse) - /// GetByIds(SecretsGetRequest), /// > Requires Authentication @@ -108,15 +100,14 @@ pub enum SecretsCommand { /// Creates a new secret in the provided organization using the given data /// /// Returns: [SecretResponse](bitwarden::secrets_manager::secrets::SecretResponse) - /// Create(SecretCreateRequest), /// > Requires Authentication /// > Requires using an Access Token for login or calling Sync at least once - /// Lists all secret identifiers of the given organization, to then retrieve each secret, use `CreateSecret` + /// Lists all secret identifiers of the given organization, to then retrieve each secret, use + /// `CreateSecret` /// /// Returns: [SecretIdentifiersResponse](bitwarden::secrets_manager::secrets::SecretIdentifiersResponse) - /// List(SecretIdentifiersRequest), /// > Requires Authentication @@ -124,7 +115,6 @@ pub enum SecretsCommand { /// Updates an existing secret with the provided ID using the given data /// /// Returns: [SecretResponse](bitwarden::secrets_manager::secrets::SecretResponse) - /// Update(SecretPutRequest), /// > Requires Authentication @@ -132,7 +122,6 @@ pub enum SecretsCommand { /// Deletes all the secrets whose IDs match the provided ones /// /// Returns: [SecretsDeleteResponse](bitwarden::secrets_manager::secrets::SecretsDeleteResponse) - /// Delete(SecretsDeleteRequest), } @@ -145,7 +134,6 @@ pub enum ProjectsCommand { /// Retrieve a project by the provided identifier /// /// Returns: [ProjectResponse](bitwarden::secrets_manager::projects::ProjectResponse) - /// Get(ProjectGetRequest), /// > Requires Authentication @@ -153,7 +141,6 @@ pub enum ProjectsCommand { /// Creates a new project in the provided organization using the given data /// /// Returns: [ProjectResponse](bitwarden::secrets_manager::projects::ProjectResponse) - /// Create(ProjectCreateRequest), /// > Requires Authentication @@ -161,7 +148,6 @@ pub enum ProjectsCommand { /// Lists all projects of the given organization /// /// Returns: [ProjectsResponse](bitwarden::secrets_manager::projects::ProjectsResponse) - /// List(ProjectsListRequest), /// > Requires Authentication @@ -169,7 +155,6 @@ pub enum ProjectsCommand { /// Updates an existing project with the provided ID using the given data /// /// Returns: [ProjectResponse](bitwarden::secrets_manager::projects::ProjectResponse) - /// Update(ProjectPutRequest), /// > Requires Authentication @@ -177,6 +162,5 @@ pub enum ProjectsCommand { /// Deletes all the projects whose IDs match the provided ones /// /// Returns: [ProjectsDeleteResponse](bitwarden::secrets_manager::projects::ProjectsDeleteResponse) - /// Delete(ProjectsDeleteRequest), } diff --git a/crates/bitwarden-napi/src/client.rs b/crates/bitwarden-napi/src/client.rs index d794b18f4..712cd4ffd 100644 --- a/crates/bitwarden-napi/src/client.rs +++ b/crates/bitwarden-napi/src/client.rs @@ -29,7 +29,8 @@ pub struct BitwardenClient(JsonClient); impl BitwardenClient { #[napi(constructor)] pub fn new(settings_input: Option, log_level: Option) -> Self { - // This will only fail if another logger was already initialized, so we can ignore the result + // This will only fail if another logger was already initialized, so we can ignore the + // result let _ = env_logger::Builder::from_default_env() .filter_level(convert_level(log_level.unwrap_or(LogLevel::Info))) .try_init(); diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index e54aae435..92afcbb87 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -12,7 +12,8 @@ pub struct ClientCrypto(pub(crate) Arc); #[uniffi::export(async_runtime = "tokio")] impl ClientCrypto { - /// Initialization method for the user crypto. Needs to be called before any other crypto operations. + /// Initialization method for the user crypto. Needs to be called before any other crypto + /// operations. pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> { Ok(self .0 @@ -24,7 +25,8 @@ impl ClientCrypto { .await?) } - /// Initialization method for the organization crypto. Needs to be called after `initialize_user_crypto` but before any other crypto operations. + /// Initialization method for the organization crypto. Needs to be called after + /// `initialize_user_crypto` but before any other crypto operations. pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> { Ok(self .0 @@ -49,13 +51,15 @@ impl ClientCrypto { .await?) } - /// Generates a PIN protected user key from the provided PIN. The result can be stored and later used - /// to initialize another client instance by using the PIN and the PIN key with `initialize_user_crypto`. + /// Generates a PIN protected user key from the provided PIN. The result can be stored and later + /// used to initialize another client instance by using the PIN and the PIN key with + /// `initialize_user_crypto`. pub async fn derive_pin_key(&self, pin: String) -> Result { Ok(self.0 .0.write().await.crypto().derive_pin_key(pin).await?) } - /// Derives the pin protected user key from encrypted pin. Used when pin requires master password on first unlock. + /// Derives the pin protected user key from encrypted pin. Used when pin requires master + /// password on first unlock. pub async fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result { Ok(self .0 diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index b6175eb3b..5eef9bbd5 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -1,6 +1,7 @@ use std::fmt::{Display, Formatter}; -// Name is converted from *Error to *Exception, so we can't just name the enum Error because Exception already exists +// Name is converted from *Error to *Exception, so we can't just name the enum Error because +// Exception already exists #[derive(uniffi::Error, Debug)] #[uniffi(flat_error)] pub enum BitwardenError { diff --git a/crates/bitwarden-wasm/src/client.rs b/crates/bitwarden-wasm/src/client.rs index 7d3d991db..b9f6723a6 100644 --- a/crates/bitwarden-wasm/src/client.rs +++ b/crates/bitwarden-wasm/src/client.rs @@ -26,8 +26,8 @@ fn convert_level(level: LogLevel) -> Level { } } -// Rc> is to avoid needing to take ownership of the Client during our async run_command function -// https://github.com/rustwasm/wasm-bindgen/issues/2195#issuecomment-799588401 +// Rc> is to avoid needing to take ownership of the Client during our async run_command +// function https://github.com/rustwasm/wasm-bindgen/issues/2195#issuecomment-799588401 #[wasm_bindgen] pub struct BitwardenClient(Rc>); diff --git a/crates/bitwarden/src/admin_console/policy.rs b/crates/bitwarden/src/admin_console/policy.rs index 1b4acc310..9a4b0d16f 100644 --- a/crates/bitwarden/src/admin_console/policy.rs +++ b/crates/bitwarden/src/admin_console/policy.rs @@ -20,18 +20,20 @@ pub struct Policy { #[derive(Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] pub enum PolicyType { - TwoFactorAuthentication = 0, // Requires users to have 2fa enabled - MasterPassword = 1, // Sets minimum requirements for master password complexity - PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases + TwoFactorAuthentication = 0, // Requires users to have 2fa enabled + MasterPassword = 1, // Sets minimum requirements for master password complexity + PasswordGenerator = 2, /* Sets minimum requirements/default type for generated + * passwords/passphrases */ SingleOrg = 3, // Allows users to only be apart of one organization RequireSso = 4, // Requires users to authenticate with SSO PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends - ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow - MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout + ResetPassword = 8, /* Allows orgs to use reset password : also can enable + * auto-enrollment during invite flow */ + MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout DisablePersonalVaultExport = 10, // Disable personal vault export - ActivateAutofill = 11, // Activates autofill with page load on the browser extension + ActivateAutofill = 11, // Activates autofill with page load on the browser extension } impl TryFrom for Policy { diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index e5d579aa2..f873ace97 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -94,9 +94,11 @@ pub struct PasswordLoginResponse { pub reset_master_password: bool, /// Whether or not the user is required to update their master password pub force_password_reset: bool, - /// The available two factor authentication options. Present only when authentication fails due to requiring a second authentication factor. + /// The available two factor authentication options. Present only when authentication fails due + /// to requiring a second authentication factor. pub two_factor: Option, - /// The information required to present the user with a captcha challenge. Only present when authentication fails due to requiring validation of a captcha challenge. + /// The information required to present the user with a captcha challenge. Only present when + /// authentication fails due to requiring validation of a captcha challenge. pub captcha: Option, } diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index 4a6d5ed8c..d7cad2fca 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -88,7 +88,8 @@ mod tests { use crate::client::AccessToken; - // Encryption key without base64 padding, we generate it with padding but ignore it when decoding + // Encryption key without base64 padding, we generate it with padding but ignore it when + // decoding let t = "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ"; assert!(AccessToken::from_str(t).is_ok()); diff --git a/crates/bitwarden/src/client/client_settings.rs b/crates/bitwarden/src/client/client_settings.rs index 172baf733..2f0637b4a 100644 --- a/crates/bitwarden/src/client/client_settings.rs +++ b/crates/bitwarden/src/client/client_settings.rs @@ -1,8 +1,8 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -/// Basic client behavior settings. These settings specify the various targets and behavior of the Bitwarden Client. -/// They are optional and uneditable once the client is initialized. +/// Basic client behavior settings. These settings specify the various targets and behavior of the +/// Bitwarden Client. They are optional and uneditable once the client is initialized. /// /// Defaults to /// diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index c8126b4fe..8b4c5197e 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -45,9 +45,10 @@ impl EncryptionSettings { } } - /// Initialize the encryption settings with the decrypted user key and the encrypted user private key - /// This should only be used when unlocking the vault via biometrics or when the vault is set to lock: "never" - /// Otherwise handling the decrypted user key is dangerous and discouraged + /// Initialize the encryption settings with the decrypted user key and the encrypted user + /// private key This should only be used when unlocking the vault via biometrics or when the + /// vault is set to lock: "never" Otherwise handling the decrypted user key is dangerous and + /// discouraged #[cfg(feature = "internal")] pub(crate) fn new_decrypted_key( user_key: SymmetricCryptoKey, @@ -105,7 +106,8 @@ impl EncryptionSettings { } pub(crate) fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { - // If we don't have a private key set (to decode multiple org keys), we just use the main user key + // If we don't have a private key set (to decode multiple org keys), we just use the main + // user key if self.private_key.is_none() { return Some(&self.user_key); } diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index 5468be855..28eb521de 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -46,7 +46,6 @@ //! Ok(()) //! } //! ``` -//! #[cfg(feature = "mobile")] uniffi::setup_scaffolding!(); diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index c32a1d1d8..f88b3d3e6 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -47,7 +47,8 @@ pub enum InitUserCryptoMethod { Pin { /// The user's PIN pin: String, - /// The user's symmetric crypto key, encrypted with the PIN. Use `derive_pin_key` to obtain this. + /// The user's symmetric crypto key, encrypted with the PIN. Use `derive_pin_key` to obtain + /// this. pin_protected_user_key: EncString, }, } diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs index 1d4ffd486..3d3b80f98 100644 --- a/crates/bitwarden/src/mobile/vault/client_totp.rs +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -13,7 +13,6 @@ impl<'a> ClientVault<'a> { /// - A base32 encoded string /// - OTP Auth URI /// - Steam URI - /// pub fn generate_totp( &'a self, key: String, diff --git a/crates/bitwarden/src/platform/secret_verification_request.rs b/crates/bitwarden/src/platform/secret_verification_request.rs index b501d0181..e05926620 100644 --- a/crates/bitwarden/src/platform/secret_verification_request.rs +++ b/crates/bitwarden/src/platform/secret_verification_request.rs @@ -4,10 +4,11 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct SecretVerificationRequest { - /// The user's master password to use for user verification. If supplied, this will be used for verification - /// purposes. + /// The user's master password to use for user verification. If supplied, this will be used for + /// verification purposes. pub master_password: Option, - /// Alternate user verification method through OTP. This is provided for users who have no master password due to - /// use of Customer Managed Encryption. Must be present and valid if master_password is absent. + /// Alternate user verification method through OTP. This is provided for users who have no + /// master password due to use of Customer Managed Encryption. Must be present and valid if + /// master_password is absent. pub otp: Option, } diff --git a/crates/bitwarden/src/platform/sync.rs b/crates/bitwarden/src/platform/sync.rs index 870b88ab9..c1a039137 100644 --- a/crates/bitwarden/src/platform/sync.rs +++ b/crates/bitwarden/src/platform/sync.rs @@ -69,7 +69,8 @@ pub struct DomainResponse { #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct SyncResponse { - /// Data about the user, including their encryption keys and the organizations they are a part of + /// Data about the user, including their encryption keys and the organizations they are a part + /// of pub profile: ProfileResponse, pub folders: Vec, pub collections: Vec, diff --git a/crates/bitwarden/src/tool/client_generator.rs b/crates/bitwarden/src/tool/client_generator.rs index c21eeb929..16c786f9b 100644 --- a/crates/bitwarden/src/tool/client_generator.rs +++ b/crates/bitwarden/src/tool/client_generator.rs @@ -1,11 +1,11 @@ use bitwarden_generators::{passphrase, password, username}; -use crate::generators::{ - PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest, +use crate::{ + error::Result, + generators::{PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest}, + Client, }; -use crate::{error::Result, Client}; - pub struct ClientGenerator<'a> { pub(crate) client: &'a crate::Client, } @@ -62,10 +62,11 @@ impl<'a> ClientGenerator<'a> { } /// Generates a random username. - /// There are different username generation strategies, which can be customized using the `input` parameter. + /// There are different username generation strategies, which can be customized using the + /// `input` parameter. /// - /// Note that most generation strategies will be executed on the client side, but `Forwarded` will use third-party - /// services, which may require a specific setup or API key. + /// Note that most generation strategies will be executed on the client side, but `Forwarded` + /// will use third-party services, which may require a specific setup or API key. /// /// ``` /// use bitwarden::{Client, generators::{UsernameGeneratorRequest}, error::Result}; diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 3e1e47025..40f32dcfb 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -4,9 +4,8 @@ use bitwarden_crypto::{ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::error::{Error, Result}; - use super::Cipher; +use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -63,7 +62,8 @@ impl<'a> KeyEncryptable for Attachm let mut attachment = self.attachment; - // Because this is a new attachment, we have to generate a key for it, encrypt the contents with it, and then encrypt the key with the cipher key + // Because this is a new attachment, we have to generate a key for it, encrypt the contents + // with it, and then encrypt the key with the cipher key let attachment_key = SymmetricCryptoKey::generate(rand::thread_rng()); let encrypted_contents = self.contents.encrypt_with_key(&attachment_key)?; attachment.key = Some(attachment_key.to_vec().encrypt_with_key(ciphers_key)?); @@ -136,7 +136,6 @@ impl TryFrom for Attachment #[cfg(test)] mod tests { use base64::{engine::general_purpose::STANDARD, Engine}; - use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; use crate::vault::{ diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 9552c83c1..34f01ca60 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -46,7 +46,8 @@ pub struct Cipher { pub folder_id: Option, pub collection_ids: Vec, - /// More recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher. + /// More recent ciphers uses individual encryption keys to encrypt the other fields of the + /// Cipher. pub key: Option, pub name: EncString, diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index b062ff9db..aba67e00c 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -197,8 +197,9 @@ impl KeyEncryptable for SendFileView { impl LocateKey for Send {} impl KeyDecryptable for Send { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { - // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + // For sends, we first decrypt the send key with the user key, and stretch it to it's full + // size For the rest of the fields, we ignore the provided SymmetricCryptoKey and + // the stretched key let k: Vec = self.key.decrypt_with_key(key)?; let key = Send::derive_shareable_key(&k)?; @@ -230,8 +231,9 @@ impl KeyDecryptable for Send { impl KeyDecryptable for Send { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { - // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + // For sends, we first decrypt the send key with the user key, and stretch it to it's full + // size For the rest of the fields, we ignore the provided SymmetricCryptoKey and + // the stretched key let key = Send::get_key(&self.key, key)?; Ok(SendListView { @@ -253,8 +255,9 @@ impl KeyDecryptable for Send { impl LocateKey for SendView {} impl KeyEncryptable for SendView { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { - // For sends, we first decrypt the send key with the user key, and stretch it to it's full size - // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key + // For sends, we first decrypt the send key with the user key, and stretch it to it's full + // size For the rest of the fields, we ignore the provided SymmetricCryptoKey and + // the stretched key let k = match (self.key, self.id) { // Existing send, decrypt key (Some(k), _) => URL_SAFE_NO_PAD diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index e99cbfabd..6ba754034 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -206,7 +206,8 @@ fn derive_binary(hash: Vec) -> u32 { | hash[offset + 3] as u32 } -/// This code is migrated from our javascript implementation and is not technically a correct base32 decoder since we filter out various characters, and use exact chunking. +/// This code is migrated from our javascript implementation and is not technically a correct base32 +/// decoder since we filter out various characters, and use exact chunking. fn decode_b32(s: &str) -> Vec { let s = s.to_uppercase(); diff --git a/crates/bws/src/render.rs b/crates/bws/src/render.rs index 83c5cd532..f9563c81b 100644 --- a/crates/bws/src/render.rs +++ b/crates/bws/src/render.rs @@ -42,7 +42,8 @@ pub(crate) fn serialize_response, const N: usiz match output { Output::JSON => { let mut text = serde_json::to_string_pretty(&data).unwrap(); - // Yaml/table/tsv serializations add a newline at the end, so we do the same here for consistency + // Yaml/table/tsv serializations add a newline at the end, so we do the same here for + // consistency text.push('\n'); pretty_print("json", &text, color); } @@ -110,7 +111,8 @@ fn pretty_print(language: &str, data: &str, color: bool) { } } -// We're using const generics for the array lengths to make sure the header count and value count match +// We're using const generics for the array lengths to make sure the header count and value count +// match pub(crate) trait TableSerialize: Sized { fn get_headers() -> [&'static str; N]; fn get_values(&self) -> Vec<[String; N]>; diff --git a/crates/sdk-schemas/src/main.rs b/crates/sdk-schemas/src/main.rs index 0cfc045a0..f9f074485 100644 --- a/crates/sdk-schemas/src/main.rs +++ b/crates/sdk-schemas/src/main.rs @@ -3,8 +3,9 @@ use std::{fs::File, io::Write}; use anyhow::Result; use schemars::{schema::RootSchema, schema_for, JsonSchema}; -/// Creates a json schema file for any type passed in using Schemars. The filename and path of the generated -/// schema file is derived from the namespace passed into the macro or supplied as the first argument. +/// Creates a json schema file for any type passed in using Schemars. The filename and path of the +/// generated schema file is derived from the namespace passed into the macro or supplied as the +/// first argument. /// /// The schema filename is given by the last namespace element and trims off any `>` characters. /// This means the filename will represent the last _generic_ type of the type given. @@ -30,7 +31,8 @@ use schemars::{schema::RootSchema, schema_for, JsonSchema}; /// ``` /// write_schema_for!(response::two_factor_login_response::two_factor_providers::TwoFactorProviders); /// ``` -/// will generate `TwoFactorProviders.json` at `{{pwd}}/response/two_factor_login_response/TwoFactorProviders.json` +/// will generate `TwoFactorProviders.json` at +/// `{{pwd}}/response/two_factor_login_response/TwoFactorProviders.json` /// /// ## Path specified /// diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 000000000..bb3baeccd --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,7 @@ +# Wrap comments and increase the width of comments to 100 +comment_width = 100 +wrap_comments = true + +# Sort and group imports +group_imports = "StdExternalCrate" +imports_granularity = "Crate" From 3f1239365ded550c5cc3409ee783a689df2b2f74 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:29:14 -0500 Subject: [PATCH 216/378] [deps]: Update dtolnay/rust-toolchain digest to be73d79 (#520) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-python-wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index e69f3eec1..db72e60a1 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -71,7 +71,7 @@ jobs: node-version: 18 - name: Install rust - uses: dtolnay/rust-toolchain@439cf607258077187679211f12aa6f19af4a0af7 # stable + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} From ae32c8d20e537be02526df7bedd2894dba39b1cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:29:39 -0500 Subject: [PATCH 217/378] [deps]: Update PyO3/maturin-action digest to 683eb33 (#519) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-python-wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index db72e60a1..17cad7c55 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -89,7 +89,7 @@ jobs: - name: Build wheels if: ${{ matrix.settings.target != 'x86_64-unknown-linux-gnu' }} - uses: PyO3/maturin-action@b9e8f88fd4448fdecf5095864cdc7e39a544aa9f # v1.40.7 + uses: PyO3/maturin-action@683eb33e2cda131da55757dbac7628b2ef22df2f # v1.40.7 with: target: ${{ matrix.settings.target }} args: --release --find-interpreter --sdist @@ -99,7 +99,7 @@ jobs: - name: Build wheels (Linux - x86_64) if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - uses: PyO3/maturin-action@b9e8f88fd4448fdecf5095864cdc7e39a544aa9f # v1.40.7 + uses: PyO3/maturin-action@683eb33e2cda131da55757dbac7628b2ef22df2f # v1.40.7 with: target: ${{ matrix.settings.target }} args: --release --find-interpreter --sdist From 43a97febf83f872a7e6fd047d34cf8eca01d3685 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 23 Jan 2024 16:25:44 +0100 Subject: [PATCH 218/378] Trusted Device Encryption (#497) Implement trusted device encryption. Verified backwards compatibility with existing device keys from desktop. --- .../src/enc_string/asymmetric.rs | 9 ++ crates/bitwarden-crypto/src/error.rs | 2 + .../src/keys/asymmetric_crypto_key.rs | 9 ++ .../bitwarden-crypto/src/keys/device_key.rs | 126 ++++++++++++++++++ crates/bitwarden-crypto/src/keys/mod.rs | 6 +- crates/bitwarden-crypto/src/rsa.rs | 18 ++- crates/bitwarden/src/auth/client_auth.rs | 19 ++- 7 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 crates/bitwarden-crypto/src/keys/device_key.rs diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 81ac81a5b..953b3d28f 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -7,6 +7,7 @@ use serde::Deserialize; use super::{from_b64_vec, split_enc_string}; use crate::{ error::{CryptoError, EncStringParseError, Result}, + rsa::encrypt_rsa2048_oaep_sha1, AsymmetricCryptoKey, KeyDecryptable, }; @@ -137,6 +138,14 @@ impl serde::Serialize for AsymmetricEncString { } impl AsymmetricEncString { + pub(crate) fn encrypt_rsa2048_oaep_sha1( + data_dec: &[u8], + key: &AsymmetricCryptoKey, + ) -> Result { + let enc = encrypt_rsa2048_oaep_sha1(&key.key, data_dec)?; + Ok(AsymmetricEncString::Rsa2048_OaepSha1_B64 { data: enc }) + } + /// The numerical representation of the encryption type of the [AsymmetricEncString]. const fn enc_type(&self) -> u8 { match self { diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index 059cc88f1..cf9a9b048 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -52,6 +52,8 @@ pub enum RsaError { CreatePublicKey, #[error("Unable to create private key")] CreatePrivateKey, + #[error("Rsa error, {0}")] + Rsa(#[from] rsa::Error), } /// Alias for `Result`. diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index a3e06800b..142013d4e 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -9,6 +9,15 @@ pub struct AsymmetricCryptoKey { } impl AsymmetricCryptoKey { + /// Generate a random AsymmetricCryptoKey (RSA-2048) + pub fn generate(rng: &mut R) -> Self { + let bits = 2048; + + Self { + key: RsaPrivateKey::new(rng, bits).expect("failed to generate a key"), + } + } + pub fn from_pem(pem: &str) -> Result { use rsa::pkcs8::DecodePrivateKey; Ok(Self { diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs new file mode 100644 index 000000000..6588944fe --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -0,0 +1,126 @@ +use crate::{ + error::Result, AsymmetricCryptoKey, AsymmetricEncString, EncString, KeyDecryptable, + KeyEncryptable, SymmetricCryptoKey, UserKey, +}; + +/// Device Key +/// +/// Encrypts the DevicePrivateKey +/// Allows the device to decrypt the UserKey, via the DevicePrivateKey. +#[derive(Debug)] +pub struct DeviceKey(SymmetricCryptoKey); + +#[derive(Debug)] +pub struct TrustDeviceResponse { + pub device_key: DeviceKey, + /// UserKey encrypted with DevicePublicKey + pub protected_user_key: AsymmetricEncString, + /// DevicePrivateKey encrypted with [DeviceKey] + pub protected_device_private_key: EncString, + /// DevicePublicKey encrypted with [UserKey](super::UserKey) + pub protected_device_public_key: EncString, +} + +impl DeviceKey { + /// Generate a new device key + /// + /// Note: Input has to be a SymmetricCryptoKey instead of UserKey because that's what we get + /// from EncSettings. + pub fn trust_device(user_key: &SymmetricCryptoKey) -> Result { + let mut rng = rand::thread_rng(); + let device_key = DeviceKey(SymmetricCryptoKey::generate(&mut rng)); + + let device_private_key = AsymmetricCryptoKey::generate(&mut rng); + + // Encrypt both the key and mac_key of the user key + let data = user_key.to_vec(); + + let protected_user_key = + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(&data, &device_private_key)?; + + let protected_device_public_key = device_private_key + .to_public_der()? + .encrypt_with_key(user_key)?; + + let protected_device_private_key = device_private_key + .to_der()? + .encrypt_with_key(&device_key.0)?; + + Ok(TrustDeviceResponse { + device_key, + protected_user_key, + protected_device_private_key, + protected_device_public_key, + }) + } + + /// Decrypt the user key using the device key + pub fn decrypt_user_key( + &self, + protected_device_private_key: EncString, + protected_user_key: AsymmetricEncString, + ) -> Result { + let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; + let device_private_key = AsymmetricCryptoKey::from_der(device_private_key.as_slice())?; + + let dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; + let user_key: SymmetricCryptoKey = dec.as_slice().try_into()?; + + Ok(UserKey(user_key)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::derive_symmetric_key; + + #[test] + fn test_trust_device() { + let key = derive_symmetric_key("test"); + + let result = DeviceKey::trust_device(&key).unwrap(); + + let decrypted = result + .device_key + .decrypt_user_key( + result.protected_device_private_key, + result.protected_user_key, + ) + .unwrap(); + + assert_eq!(key.key, decrypted.0.key); + assert_eq!(key.mac_key, decrypted.0.mac_key); + } + + #[test] + fn test_decrypt_user_key() { + // Example keys from desktop app + let user_key: &[u8] = &[ + 109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216, 212, + 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91, 215, 21, + 128, 91, 226, 222, 165, 67, 251, 34, 83, 81, 77, 147, 225, 76, 13, 41, 102, 45, 183, + 218, 106, 89, 254, 208, 251, 101, 130, 10, + ]; + let user_key = SymmetricCryptoKey::try_from(user_key).unwrap(); + + let key_data: &[u8] = &[ + 114, 235, 60, 115, 172, 156, 203, 145, 195, 130, 215, 250, 88, 146, 215, 230, 12, 109, + 245, 222, 54, 217, 255, 211, 221, 105, 230, 236, 65, 52, 209, 133, 76, 208, 113, 254, + 194, 216, 156, 19, 230, 62, 32, 93, 87, 7, 144, 156, 117, 142, 250, 32, 182, 118, 187, + 8, 247, 7, 203, 201, 65, 147, 206, 247, + ]; + let device_key = DeviceKey(key_data.try_into().unwrap()); + + let protected_user_key: AsymmetricEncString = "4.f+VbbacRhO2q4MOUSdt1AIjQ2FuLAvg4aDxJMXAh3VxvbmUADj8Ct/R7XEpPUqApmbRS566jS0eRVy8Sk08ogoCdj1IFN9VsIky2i2X1WHK1fUnr3UBmXE3tl2NPBbx56U+h73S2jNTSyet2W18Jg2q7/w8KIhR3J41QrG9aGoOTN93to3hb5W4z6rdrSI0e7GkizbwcIA0NH7Z1JyAhrjPm9+tjRjg060YbEbGaWTAOkZWfgbLjr8bY455DteO2xxG139cOx7EBo66N+YhjsLi0ozkeUyPQkoWBdKMcQllS7jCfB4fDyJA05ALTbk74syKkvqFxqwmQbg+aVn+dcw==".parse().unwrap(); + + let protected_device_private_key: EncString = "2.GyQfUYWW6Byy4UV5icFLxg==|EMiU7OTF79N6tfv3+YUs5zJhBAgqv6sa5YCoPl6yAETh7Tfk+JmbeizxXFPj5Q1X/tcVpDZl/3fGcxtnIxg1YtvDFn7j8uPnoApOWhCKmwcvJSIkt+qvX3lELNBwZXozSiy7PbQ0JbCMe2d4MkimR5k8+lE9FB3208yYK7nOJhlrsUCnOekCYEU9/4NCMA8tz8SpITx/MN4JJ1TQ/KjPJYLt+3JNUxK47QlgREWQvyVzCRt7ZGtcgIJ/U1qycAWMpEg9NkuV8j5QRA1S7VBsA6qliJwys5+dmTuIOmOMwdKFZDc4ZvWoRkPp2TSJBu7L8sSAgU6mmDWac8iQ+9Ka/drdfwYLrH8GAZvURk79tSpRrT7+PAFe2QdUtliUIyiqkh8iJVjZube4hRnEsRuX9V9b+UdtAr6zAj7mugO/VAu5T9J38V79V2ohG3NtXysDeKLXpAlkhjllWXeq/wret2fD4WiwqEDj0G2A/PY3F3OziIgp0UKc00AfqrPq8OVK3A+aowwVqdYadgxyoVCKWJ8unJeAXG7MrMQ9tHpzF6COoaEy7Wwoc17qko33zazwLZbfAjB4oc8Ea26jRKnJZP56sVZAjOSQQMziAsA08MRaa/DQhgRea1+Ygba0gMft8Dww8anN2gQBveTZRBWyqXYgN3U0Ity5gNauT8RnFk9faqVFt2Qxnp0JgJ+PsqEt5Hn4avBRZQQ7o8VvPnxYLDKFe3I2m6HFYFWRhOGeDYxexIuaiF2iIAYFVUmnDuWpgnUiL4XJ3KHDsjkPzcV3z4D2Knr/El2VVXve8jhDjETfovmmN28+i2e29PXvKIymTskMFpFCQPc7wBY/Id7pmgb3SujKYNpkAS2sByDoRir0my49DDGfta0dENssJhFd3x+87fZbEj3cMiikg2pBwpTLgmfIUa5cVZU2s8JZ9wu7gaioYzvX+elHa3EHLcnEUoJTtSf9kjb+Nbq4ktMgYAO2wIC96t1LvmqK4Qn2cOdw5QNlRqALhqe5V31kyIcwRMK0AyIoOPhnSqtpYdFiR3LDTvZA8dU0vSsuchCwHNMeRUtKvdzN/tk+oeznyY/mpakUESN501lEKd/QFLtJZsDZTtNlcA8fU3kDtws4ZIMR0O5+PFmgQFSU8OMobf9ClUzy/wHTvYGyDuSwbOoPeS955QKkUKXCNMj33yrPr+ioHQ1BNwLX3VmMF4bNRBY/vr+CG0/EZi0Gwl0kyHGl0yWEtpQuu+/PaROJeOraWy5D1UoZZhY4n0zJZBt1eg3FZ2rhKv4gdUc50nZpeNWE8pIqZ6RQ7qPJuqfF1Z+G73iOSnLYCHDiiFmhD5ivf9IGkTAcWcBsQ/2wcSj9bFJr4DrKfsbQ4CkSWICWVn/W+InKkO6BTsBbYmvte5SvbaN+UOtiUSkHLBCCr8273VNgcB/hgtbUires3noxYZJxoczr+i7vdlEgQnWEKrpo0CifsFxGwYS3Yy2K79iwvDMaLPDf73zLSbuoUl6602F2Mzcjnals67f+gSpaDvWt7Kg9c/ZfGjq8oNxVaXJnX3gSDsO+fhwVAtnDApL+tL8cFfxGerW4KGi9/74woH+C3MMIViBtNnrpEuvxUW97Dg5nd40oGDeyi/q+8HdcxkneyFY=|JYdol19Yi+n1r7M+06EwK5JCi2s/CWqKui2Cy6hEb3k=".parse().unwrap(); + + let decrypted = device_key + .decrypt_user_key(protected_device_private_key, protected_user_key) + .unwrap(); + + assert_eq!(decrypted.0.key, user_key.key); + assert_eq!(decrypted.0.mac_key, user_key.mac_key); + } +} diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 4f53456ef..561fd8436 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -1,18 +1,16 @@ mod key_encryptable; pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; - mod master_key; pub use master_key::{HashPurpose, Kdf, MasterKey}; - mod shareable_key; pub use shareable_key::derive_shareable_key; - mod symmetric_crypto_key; #[cfg(test)] pub use symmetric_crypto_key::derive_symmetric_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod asymmetric_crypto_key; pub use asymmetric_crypto_key::AsymmetricCryptoKey; - mod user_key; pub use user_key::UserKey; +mod device_key; +pub use device_key::{DeviceKey, TrustDeviceResponse}; diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index ff665c247..52dd572aa 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -1,12 +1,13 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use rsa::{ pkcs8::{EncodePrivateKey, EncodePublicKey}, - RsaPrivateKey, RsaPublicKey, + Oaep, RsaPrivateKey, RsaPublicKey, }; +use sha1::Sha1; use crate::{ error::{Result, RsaError}, - EncString, SymmetricCryptoKey, + CryptoError, EncString, SymmetricCryptoKey, }; /// RSA Key Pair @@ -42,3 +43,16 @@ pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { private: protected, }) } + +pub(super) fn encrypt_rsa2048_oaep_sha1( + private_key: &RsaPrivateKey, + data: &[u8], +) -> Result> { + let mut rng = rand::thread_rng(); + + let padding = Oaep::new::(); + private_key + .to_public_key() + .encrypt(&mut rng, padding, data) + .map_err(|e| CryptoError::RsaError(e.into())) +} diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index d4379d1eb..c0a5e7aa3 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "internal")] +use bitwarden_crypto::{DeviceKey, TrustDeviceResponse}; + #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; use crate::{auth::renew::renew_token, error::Result, Client}; @@ -16,6 +19,7 @@ use crate::{ RegisterKeyResponse, RegisterRequest, }, client::Kdf, + error::Error, }; pub struct ClientAuth<'a> { @@ -97,6 +101,19 @@ impl<'a> ClientAuth<'a> { pub async fn validate_password(&self, password: String, password_hash: String) -> Result { validate_password(self.client, password, password_hash).await } + + pub async fn trust_device(&self) -> Result { + trust_device(self.client) + } +} + +#[cfg(feature = "internal")] +fn trust_device(client: &Client) -> Result { + let enc = client.get_encryption_settings()?; + + let user_key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + + Ok(DeviceKey::trust_device(user_key)?) } impl<'a> Client { @@ -172,7 +189,7 @@ mod tests { .login_access_token(&AccessTokenLoginRequest { access_token: "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ==".into(), state_file: None, - },) + }) .await .unwrap(); assert!(res.authenticated); From 646e4a79bbdf1dc38ea3dc27904231e18a669f58 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 23 Jan 2024 11:04:00 -0500 Subject: [PATCH 219/378] Update Renovate config (#531) --- .github/renovate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json b/.github/renovate.json index 42f5f93f2..ae4ad0e9d 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -2,6 +2,7 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base", + "github>bitwarden/renovate-config:pin-actions", ":combinePatchMinorReleases", ":dependencyDashboard", ":maintainLockFilesWeekly", From 5958061feac7f121fd7c1b1bd98169b41db5ba9a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 11:07:54 -0500 Subject: [PATCH 220/378] [deps]: Update gh minor (#524) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-cli.yml | 6 +++--- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-python-wheels.yml | 10 +++++----- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/generate_schemas.yml | 14 +++++++------- .github/workflows/publish-ruby.yml | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 361769ef9..9b1b1c952 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -46,7 +46,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index abcbcbedf..70922b786 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -99,7 +99,7 @@ jobs: run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip @@ -142,7 +142,7 @@ jobs: run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws - name: Upload artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip path: ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip @@ -177,7 +177,7 @@ jobs: sed -i.bak 's/\$NAME\$/Bitwarden Secrets Manager CLI/g' THIRDPARTY.html - name: Upload artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: THIRDPARTY.html path: ./crates/bws/THIRDPARTY.html diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 568683a58..232efee9d 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -71,7 +71,7 @@ jobs: working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: Bitwarden.Sdk.0.0.1.nupkg path: | diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 1581a8d66..40e6ffaef 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -84,7 +84,7 @@ jobs: run: ${{ matrix.settings.build }} - name: Upload artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: sdk-bitwarden-napi-${{ matrix.settings.target }} path: ${{ github.workspace }}/crates/bitwarden-napi/sdk-napi.*.node diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index 17cad7c55..dace2d047 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -66,7 +66,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0 + uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 with: node-version: 18 @@ -77,19 +77,19 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 with: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110 # v4.1.0 + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk - name: Build wheels if: ${{ matrix.settings.target != 'x86_64-unknown-linux-gnu' }} - uses: PyO3/maturin-action@683eb33e2cda131da55757dbac7628b2ef22df2f # v1.40.7 + uses: PyO3/maturin-action@a3013db91b2ef2e51420cfe99ee619c8e72a17e6 # v1.40.8 with: target: ${{ matrix.settings.target }} args: --release --find-interpreter --sdist @@ -99,7 +99,7 @@ jobs: - name: Build wheels (Linux - x86_64) if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - uses: PyO3/maturin-action@683eb33e2cda131da55757dbac7628b2ef22df2f # v1.40.7 + uses: PyO3/maturin-action@a3013db91b2ef2e51420cfe99ee619c8e72a17e6 # v1.40.8 with: target: ${{ matrix.settings.target }} args: --release --find-interpreter --sdist diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 52c44abeb..7495457df 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -41,7 +41,7 @@ jobs: run: cargo build --target ${{ matrix.settings.target }} --release - name: Upload Artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: libbitwarden_c_files-${{ matrix.settings.target }} path: | diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 55c9c07d9..a18b4910a 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -37,48 +37,48 @@ jobs: run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: schemas.ts path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: schemas.cs path: ${{ github.workspace }}/languages/csharp/Bitwarden.Sdk/schemas.cs if-no-files-found: error - name: Upload python schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0 + uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 545e43f76..291834022 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@b203567269b5bbc256dbc1c84f7495913f977353 # v1.167.0 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 with: ruby-version: 3.2 From 8f314413da63492e5d2ab2095ae606fb21f7478a Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 24 Jan 2024 18:33:43 +0100 Subject: [PATCH 221/378] Login with device (#529) Login with device and approve device. --- .../src/enc_string/asymmetric.rs | 9 +- .../src/keys/asymmetric_crypto_key.rs | 104 ++++++++++++- crates/bitwarden-crypto/src/keys/mod.rs | 5 +- crates/bitwarden-crypto/src/rsa.rs | 8 +- crates/bitwarden-uniffi/src/auth/mod.rs | 22 ++- crates/bitwarden-uniffi/src/uniffi_support.rs | 3 +- crates/bitwarden/src/auth/auth_request.rs | 137 ++++++++++++++++++ crates/bitwarden/src/auth/client_auth.rs | 13 +- crates/bitwarden/src/auth/mod.rs | 7 +- crates/bitwarden/src/mobile/crypto.rs | 15 ++ languages/kotlin/doc.md | 48 ++++++ 11 files changed, 349 insertions(+), 22 deletions(-) create mode 100644 crates/bitwarden/src/auth/auth_request.rs diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 953b3d28f..ea969f4f9 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -8,7 +8,7 @@ use super::{from_b64_vec, split_enc_string}; use crate::{ error::{CryptoError, EncStringParseError, Result}, rsa::encrypt_rsa2048_oaep_sha1, - AsymmetricCryptoKey, KeyDecryptable, + AsymmetricCryptoKey, AsymmetricEncryptable, KeyDecryptable, }; /// # Encrypted string primitive @@ -138,11 +138,12 @@ impl serde::Serialize for AsymmetricEncString { } impl AsymmetricEncString { - pub(crate) fn encrypt_rsa2048_oaep_sha1( + /// Encrypt and produce a [AsymmetricEncString::Rsa2048_OaepSha1_B64] variant. + pub fn encrypt_rsa2048_oaep_sha1( data_dec: &[u8], - key: &AsymmetricCryptoKey, + key: &dyn AsymmetricEncryptable, ) -> Result { - let enc = encrypt_rsa2048_oaep_sha1(&key.key, data_dec)?; + let enc = encrypt_rsa2048_oaep_sha1(key.to_public_key(), data_dec)?; Ok(AsymmetricEncString::Rsa2048_OaepSha1_B64 { data: enc }) } diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index 142013d4e..560e7e4cc 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -1,15 +1,45 @@ -use rsa::RsaPrivateKey; +use rsa::{pkcs8::DecodePublicKey, RsaPrivateKey, RsaPublicKey}; use super::key_encryptable::CryptoKey; use crate::error::{CryptoError, Result}; -/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) +/// Trait to allow both [`AsymmetricCryptoKey`] and [`AsymmetricPublicCryptoKey`] to be used to +/// encrypt [AsymmetricEncString](crate::AsymmetricEncString). +pub trait AsymmetricEncryptable { + fn to_public_key(&self) -> &RsaPublicKey; +} + +/// An asymmetric public encryption key. Can only encrypt +/// [AsymmetricEncString](crate::AsymmetricEncString), usually accompanied by a +/// [AsymmetricCryptoKey] +pub struct AsymmetricPublicCryptoKey { + pub(crate) key: RsaPublicKey, +} + +impl AsymmetricPublicCryptoKey { + /// Build a public key from the SubjectPublicKeyInfo DER. + pub fn from_der(der: &[u8]) -> Result { + Ok(Self { + key: rsa::RsaPublicKey::from_public_key_der(der) + .map_err(|_| CryptoError::InvalidKey)?, + }) + } +} + +impl AsymmetricEncryptable for AsymmetricPublicCryptoKey { + fn to_public_key(&self) -> &RsaPublicKey { + &self.key + } +} + +/// An asymmetric encryption key. Contains both the public and private key. Can be used to both +/// encrypt and decrypt [`AsymmetricEncString`](crate::AsymmetricEncString). pub struct AsymmetricCryptoKey { pub(crate) key: RsaPrivateKey, } impl AsymmetricCryptoKey { - /// Generate a random AsymmetricCryptoKey (RSA-2048) + /// Generate a random AsymmetricCryptoKey (RSA-2048). pub fn generate(rng: &mut R) -> Self { let bits = 2048; @@ -45,7 +75,6 @@ impl AsymmetricCryptoKey { pub fn to_public_der(&self) -> Result> { use rsa::pkcs8::EncodePublicKey; Ok(self - .key .to_public_key() .to_public_key_der() .map_err(|_| CryptoError::InvalidKey)? @@ -54,6 +83,12 @@ impl AsymmetricCryptoKey { } } +impl AsymmetricEncryptable for AsymmetricCryptoKey { + fn to_public_key(&self) -> &RsaPublicKey { + self.key.as_ref() + } +} + impl CryptoKey for AsymmetricCryptoKey {} // We manually implement these to make sure we don't print any sensitive data @@ -67,7 +102,9 @@ impl std::fmt::Debug for AsymmetricCryptoKey { mod tests { use base64::{engine::general_purpose::STANDARD, Engine}; - use super::AsymmetricCryptoKey; + use crate::{ + AsymmetricCryptoKey, AsymmetricEncString, AsymmetricPublicCryptoKey, KeyDecryptable, + }; #[test] fn test_asymmetric_crypto_key() { @@ -111,4 +148,61 @@ DnqOsltgPomWZ7xVfMkm9niL2OA= assert_eq!(der_key.to_der().unwrap(), der_key_vec); assert_eq!(pem_key.to_der().unwrap(), der_key_vec); } + + #[test] + fn test_encrypt_public_decrypt_private() { + let private_key = STANDARD + .decode(concat!( + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCu9xd+vmkIPoqH", + "NejsFZzkd1xuCn1TqGTT7ANhAEnbI/yaVt3caI30kwUC2WIToFpNgu7Ej0x2TteY", + "OgrLrdcC4jy1SifmKYv/v3ZZxrd/eqttmH2k588panseRwHK3LVk7xA+URhQ/bjL", + "gPM59V0uR1l+z1fmooeJPFz5WSXNObc9Jqnh45FND+U/UYHXTLSomTn7jgZFxJBK", + "veS7q6Lat7wAnYZCF2dnPmhZoJv+SKPltA8HAGsgQGWBF1p5qxV1HrAUk8kBBnG2", + "paj0w8p5UM6RpDdCuvKH7j1LiuWffn3b9Z4dgzmE7jsMmvzoQtypzIKaSxhqzvFO", + "od9V8dJdAgMBAAECggEAGGIYjOIB1rOKkDHP4ljXutI0mCRPl3FMDemiBeppoIfZ", + "G/Q3qpAKmndDt0Quwh/yfcNdvZhf1kwCCTWri/uPz5fSUIyDV3TaTRu0ZWoHaBVj", + "Hxylg+4HRZUQj+Vi50/PWr/jQmAAVMcrMfcoTl82q2ynmP/R1vM3EsXOCjTliv5B", + "XlMPRjj/9PDBH0dnnVcAPDOpflzOTL2f4HTFEMlmg9/tZBnd96J/cmfhjAv9XpFL", + "FBAFZzs5pz0rwCNSR8QZNonnK7pngVUlGDLORK58y84tGmxZhGdne3CtCWey/sJ4", + "7QF0Pe8YqWBU56926IY6DcSVBuQGZ6vMCNlU7J8D2QKBgQDXyh3t2TicM/n1QBLk", + "zLoGmVUmxUGziHgl2dnJiGDtyOAU3+yCorPgFaCie29s5qm4b0YEGxUxPIrRrEro", + "h0FfKn9xmr8CdmTPTcjJW1+M7bxxq7oBoU/QzKXgIHlpeCjjnvPJt0PcNkNTjCXv", + "shsrINh2rENoe/x79eEfM/N5eQKBgQDPkYSmYyALoNq8zq0A4BdR+F5lb5Fj5jBH", + "Jk68l6Uti+0hRbJ2d1tQTLkU+eCPQLGBl6fuc1i4K5FV7v14jWtRPdD7wxrkRi3j", + "ilqQwLBOU6Bj3FK4DvlLF+iYTuBWj2/KcxflXECmsjitKHLK6H7kFEiuJql+NAHU", + "U9EFXepLBQKBgQDQ+HCnZ1bFHiiP8m7Zl9EGlvK5SwlnPV9s+F1KJ4IGhCNM09UM", + "ZVfgR9F5yCONyIrPiyK40ylgtwqQJlOcf281I8irUXpsfg7+Gou5Q31y0r9NLUpC", + "Td8niyePtqMdGjouxD2+OHXFCd+FRxFt4IMi7vnxYr0csAVAXkqWlw7PsQKBgH/G", + "/PnQm7GM3BrOwAGB8dksJDAddkshMScblezTDYP0V43b8firkTLliCo5iNum357/", + "VQmdSEhXyag07yR/Kklg3H2fpbZQ3X7tdMMXW3FcWagfwWw9C4oGtdDM/Z1Lv23J", + "XDR9je8QV4OBGul+Jl8RfYx3kG94ZIfo8Qt0vP5hAoGARjAzdCGYz42NwaUk8n94", + "W2RuKHtTV9vtjaAbfPFbZoGkT7sXNJVlrA0C+9f+H9rOTM3mX59KrjmLVzde4Vhs", + "avWMShuK4vpAiDQLU7GyABvi5CR6Ld+AT+LSzxHhVe0ASOQPNCA2SOz3RQvgPi7R", + "GDgRMUB6cL3IRVzcR0dC6cY=", + )) + .unwrap(); + + let public_key = STANDARD + .decode(concat!( + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvcXfr5pCD6KhzXo7BWc", + "5Hdcbgp9U6hk0+wDYQBJ2yP8mlbd3GiN9JMFAtliE6BaTYLuxI9Mdk7XmDoKy63X", + "AuI8tUon5imL/792Wca3f3qrbZh9pOfPKWp7HkcByty1ZO8QPlEYUP24y4DzOfVd", + "LkdZfs9X5qKHiTxc+VklzTm3PSap4eORTQ/lP1GB10y0qJk5+44GRcSQSr3ku6ui", + "2re8AJ2GQhdnZz5oWaCb/kij5bQPBwBrIEBlgRdaeasVdR6wFJPJAQZxtqWo9MPK", + "eVDOkaQ3Qrryh+49S4rln3592/WeHYM5hO47DJr86ELcqcyCmksYas7xTqHfVfHS", + "XQIDAQAB", + )) + .unwrap(); + + let private_key = AsymmetricCryptoKey::from_der(&private_key).unwrap(); + let public_key = AsymmetricPublicCryptoKey::from_der(&public_key).unwrap(); + + let plaintext = "Hello, world!"; + let encrypted = + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(plaintext.as_bytes(), &public_key) + .unwrap(); + let decrypted: String = encrypted.decrypt_with_key(&private_key).unwrap(); + + assert_eq!(plaintext, decrypted); + } } diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 561fd8436..285e58b55 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -9,7 +9,10 @@ mod symmetric_crypto_key; pub use symmetric_crypto_key::derive_symmetric_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod asymmetric_crypto_key; -pub use asymmetric_crypto_key::AsymmetricCryptoKey; +pub use asymmetric_crypto_key::{ + AsymmetricCryptoKey, AsymmetricEncryptable, AsymmetricPublicCryptoKey, +}; + mod user_key; pub use user_key::UserKey; mod device_key; diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index 52dd572aa..bee88a655 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -44,15 +44,11 @@ pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { }) } -pub(super) fn encrypt_rsa2048_oaep_sha1( - private_key: &RsaPrivateKey, - data: &[u8], -) -> Result> { +pub(super) fn encrypt_rsa2048_oaep_sha1(public_key: &RsaPublicKey, data: &[u8]) -> Result> { let mut rng = rand::thread_rng(); let padding = Oaep::new::(); - private_key - .to_public_key() + public_key .encrypt(&mut rng, padding, data) .map_err(|e| CryptoError::RsaError(e.into())) } diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index f67aa3a02..62c791967 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -1,7 +1,9 @@ use std::sync::Arc; -use bitwarden::auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}; -use bitwarden_crypto::{HashPurpose, Kdf}; +use bitwarden::auth::{ + password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, +}; +use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf}; use crate::{error::Result, Client}; @@ -91,4 +93,20 @@ impl ClientAuth { .validate_password(password, password_hash.to_string()) .await?) } + + /// Initialize a new auth request + pub async fn new_auth_request(&self, email: String) -> Result { + Ok(self.0 .0.write().await.auth().new_auth_request(&email)?) + } + + /// Approve an auth request + pub async fn approve_auth_request(&self, public_key: String) -> Result { + Ok(self + .0 + .0 + .write() + .await + .auth() + .approve_auth_request(public_key)?) + } } diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index a91e3de5f..663d5c41e 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,6 +1,7 @@ -use bitwarden_crypto::EncString; +use bitwarden_crypto::{AsymmetricEncString, EncString}; // Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden::UniFfiTag, crate::UniFfiTag); +uniffi::ffi_converter_forward!(AsymmetricEncString, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden/src/auth/auth_request.rs b/crates/bitwarden/src/auth/auth_request.rs new file mode 100644 index 000000000..facdc8f82 --- /dev/null +++ b/crates/bitwarden/src/auth/auth_request.rs @@ -0,0 +1,137 @@ +use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::{ + fingerprint, AsymmetricCryptoKey, AsymmetricEncString, AsymmetricPublicCryptoKey, +}; +#[cfg(feature = "mobile")] +use bitwarden_crypto::{KeyDecryptable, SymmetricCryptoKey}; +use bitwarden_generators::{password, PasswordGeneratorRequest}; + +use crate::{error::Error, Client}; + +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct AuthRequestResponse { + /// Base64 encoded private key + /// This key is temporarily passed back and will most likely not be available in the future + pub private_key: String, + /// Base64 encoded public key + pub public_key: String, + /// Fingerprint of the public key + pub fingerprint: String, + /// Access code + pub access_code: String, +} + +/// Initiate a new auth request. +/// +/// Generates a private key and access code. The pulic key is uploaded to the server and transmitted +/// to another device. Where the user confirms the validity by confirming the fingerprint. The user +/// key is then encrypted using the public key and returned to the initiating device. +pub(crate) fn new_auth_request(email: &str) -> Result { + let mut rng = rand::thread_rng(); + + let key = AsymmetricCryptoKey::generate(&mut rng); + + let spki = key.to_public_der()?; + + let fingerprint = fingerprint(email, &spki)?; + let b64 = STANDARD.encode(&spki); + + Ok(AuthRequestResponse { + private_key: STANDARD.encode(key.to_der()?), + public_key: b64, + fingerprint, + access_code: password(PasswordGeneratorRequest { + length: 25, + lowercase: true, + uppercase: true, + numbers: true, + special: false, + ..Default::default() + })?, + }) +} + +/// Decrypt the user key using the private key generated previously. +#[cfg(feature = "mobile")] +pub(crate) fn auth_request_decrypt_user_key( + private_key: String, + user_key: AsymmetricEncString, +) -> Result { + let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?; + let key: String = user_key.decrypt_with_key(&key)?; + + Ok(key.parse()?) +} + +/// Approve an auth request. +/// +/// Encrypts the user key with a public key. +pub(crate) fn approve_auth_request( + client: &mut Client, + public_key: String, +) -> Result { + let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(public_key)?)?; + + let enc = client.get_encryption_settings()?; + let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + + Ok(AsymmetricEncString::encrypt_rsa2048_oaep_sha1( + &key.to_vec(), + &public_key, + )?) +} + +#[test] +fn test_auth_request() { + let request = new_auth_request("test@bitwarden.com").unwrap(); + + let secret = + "w2LO+nwV4oxwswVYCxlOfRUseXfvU03VzvKQHrqeklPgiMZrspUe6sOBToCnDn9Ay0tuCBn8ykVVRb7PWhub2Q=="; + + let private_key = + AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap()).unwrap(); + + let encrypted = + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(secret.as_bytes(), &private_key).unwrap(); + + let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap(); + + assert_eq!(decrypted.to_base64(), secret); +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroU32; + + use bitwarden_crypto::Kdf; + + use super::*; + use crate::client::{LoginMethod, UserLoginMethod}; + + #[test] + fn test_approve() { + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "123".to_owned(), + email: "test@bitwarden.com".to_owned(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + })); + + let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); + let private_key ="2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap(); + client + .initialize_user_crypto("asdfasdfasdf", user_key, private_key) + .unwrap(); + + let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnRtpYLp9QLaEUkdPkWZX6TrMUKFoSaFamBKDL0NlS6xwtETTqYIxRVsvnHii3Dhz+fh3aHQVyBa1rBXogeH3MLERzNADwZhpWtBT9wKCXY5o0fIWYdZV/Nf0Y+0ZoKdImrGPLPmyHGfCqrvrK7g09q8+3kXUlkdAImlQqc5TiYwiHBfUQVTBq/Ae7a0FEpajx1NUM4h3edpCYxbvnpSTuzMgbmbUUS4gdCaheA2ibYxy/zkLzsaLygoibMyGNl9Y8J5n7dDrVXpUKZTihVfXwHfEZwtKNunWsmmt8rEJWVpguUDEDVSUogoxQcNaCi7KHn9ioSip76hg1jLpypO3WwIDAQAB"; + + // Verify fingerprint + let pbkey = STANDARD.decode(public_key).unwrap(); + let fingerprint = fingerprint("test@bitwarden.com", &pbkey).unwrap(); + assert_eq!(fingerprint, "spill-applaud-sweep-habitable-shrunk"); + + approve_auth_request(&mut client, public_key.to_owned()).unwrap(); + } +} diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index c0a5e7aa3..aaa387741 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,5 +1,5 @@ #[cfg(feature = "internal")] -use bitwarden_crypto::{DeviceKey, TrustDeviceResponse}; +use bitwarden_crypto::{AsymmetricEncString, DeviceKey, TrustDeviceResponse}; #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; @@ -7,6 +7,7 @@ use crate::{auth::renew::renew_token, error::Result, Client}; #[cfg(feature = "internal")] use crate::{ auth::{ + auth_request::{approve_auth_request, new_auth_request}, login::{ login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, @@ -16,7 +17,7 @@ use crate::{ password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, }, register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, + AuthRequestResponse, RegisterKeyResponse, RegisterRequest, }, client::Kdf, error::Error, @@ -102,6 +103,14 @@ impl<'a> ClientAuth<'a> { validate_password(self.client, password, password_hash).await } + pub fn new_auth_request(&self, email: &str) -> Result { + new_auth_request(email) + } + + pub fn approve_auth_request(&mut self, public_key: String) -> Result { + approve_auth_request(self.client, public_key) + } + pub async fn trust_device(&self) -> Result { trust_device(self.client) } diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index e80ab28cf..23b64eaf9 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -6,13 +6,18 @@ pub mod login; pub mod password; pub mod renew; pub use jwt_token::JWTToken; - #[cfg(feature = "internal")] mod register; #[cfg(feature = "internal")] use bitwarden_crypto::{HashPurpose, MasterKey}; #[cfg(feature = "internal")] pub use register::{RegisterKeyResponse, RegisterRequest}; +#[cfg(feature = "internal")] +mod auth_request; +#[cfg(feature = "mobile")] +pub(crate) use auth_request::auth_request_decrypt_user_key; +#[cfg(feature = "internal")] +pub use auth_request::AuthRequestResponse; #[cfg(feature = "internal")] use crate::{client::Kdf, error::Result}; diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index f88b3d3e6..bd71af2be 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -51,10 +51,18 @@ pub enum InitUserCryptoMethod { /// this. pin_protected_user_key: EncString, }, + AuthRequest { + /// Private Key generated by the `crate::auth::new_auth_request`. + request_private_key: String, + /// User Key protected by the private key provided in `AuthRequestResponse`. + protected_user_key: AsymmetricEncString, + }, } #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { + use crate::auth::auth_request_decrypt_user_key; + let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), email: req.email, @@ -79,6 +87,13 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ } => { client.initialize_user_crypto_pin(&pin, pin_protected_user_key, private_key)?; } + InitUserCryptoMethod::AuthRequest { + request_private_key, + protected_user_key, + } => { + let user_key = auth_request_decrypt_user_key(request_private_key, protected_user_key)?; + client.initialize_user_crypto_decrypted_key(user_key, private_key)?; + } } Ok(()) diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index ccf193301..fd98e463e 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -138,6 +138,28 @@ password, use the email OTP. **Output**: std::result::Result<,BitwardenError> +### `new_auth_request` + +Initialize a new auth request + +**Arguments**: + +- self: +- email: String + +**Output**: std::result::Result + +### `approve_auth_request` + +Approve an auth request + +**Arguments**: + +- self: +- public_key: String + +**Output**: std::result::Result + ## ClientAttachments ### `encrypt_buffer` @@ -1227,6 +1249,32 @@ implementations.
+ + authRequest + object + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescription
request_private_keystringPrivate Key generated by the `crate::auth::new_auth_request`.
protected_user_keyUser Key protected by the private key provided in `AuthRequestResponse`.
+ + ## `InitUserCryptoRequest` From ee04e226a78626ed4c356a3b19deceb60ef98005 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 25 Jan 2024 13:51:01 +0100 Subject: [PATCH 222/378] Upgrade cross to a newer untagged release (#537) The lockfile bump in #464 requires a newer rust version to build correctly. Unfortunately the latest released version of cross doesn't support newer rust versions for android To resolve this we target a newer revision. --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 9b1b1c952..ce08322be 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -30,7 +30,7 @@ jobs: - name: Install rust uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable with: - toolchain: 1.67.0 # https://github.com/cross-rs/cross/issues/1222 + toolchain: stable - name: Cache cargo registry uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 @@ -38,7 +38,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo - name: Install Cross - run: cargo install cross --locked + run: cargo install cross --locked --git https://github.com/cross-rs/cross.git --rev 185398b1b885820515a212de720a306b08e2c8c9 - name: Build env: diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 70922b786..1e8ad2896 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -75,7 +75,7 @@ jobs: - name: Install Cross (aarch64-unknown-linux-gnu) if: ${{ matrix.settings.target == 'aarch64-unknown-linux-gnu' }} - run: cargo install cross --locked + run: cargo install cross --locked --git https://github.com/cross-rs/cross.git --rev 185398b1b885820515a212de720a306b08e2c8c9 - name: Build if: ${{ matrix.settings.target != 'aarch64-unknown-linux-gnu' }} From af880e67895bc5f9a6211e6f8a96c6b3a43d706f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:24:26 +0100 Subject: [PATCH 223/378] [deps]: Lock file maintenance (#464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 427 +++++++++------------- crates/bitwarden-napi/package-lock.json | 18 +- languages/js/sdk-client/package-lock.json | 6 +- package-lock.json | 212 +++++------ 4 files changed, 292 insertions(+), 371 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 218a21ed5..d0a748276 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,9 +63,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.7" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd2405b3ac1faab2990b74d728624cd9fd115651fcecc7c2d8daf01376275ba" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ "anstyle", "anstyle-parse", @@ -123,9 +123,9 @@ checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" [[package]] name = "argon2" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "askama_derive" -version = "0.12.2" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a0fc7dcf8bd4ead96b1d36b41df47c14beedf7b0301fc543d8f2384e66a2ec0" +checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" dependencies = [ "askama_parser", "basic-toml", @@ -156,7 +156,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -167,9 +167,9 @@ checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" [[package]] name = "askama_parser" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c268a96e01a4c47c8c5c2472aaa570707e006a875ea63e819f75474ceedaf7b4" +checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" dependencies = [ "nom", ] @@ -214,20 +214,20 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -259,9 +259,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -271,9 +271,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" +checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" dependencies = [ "serde", ] @@ -338,21 +338,21 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitwarden" version = "0.4.0" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", "bitwarden-generators", "chrono", - "getrandom 0.2.11", + "getrandom 0.2.12", "hmac", "log", "rand 0.8.5", @@ -425,7 +425,7 @@ version = "0.1.0" dependencies = [ "aes", "argon2", - "base64 0.21.5", + "base64 0.21.7", "cbc", "hkdf", "hmac", @@ -556,9 +556,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" dependencies = [ "memchr", "serde", @@ -613,9 +613,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" [[package]] name = "byteorder" @@ -646,9 +646,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] @@ -699,9 +699,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -709,7 +709,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.0", ] [[package]] @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.8" +version = "4.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf7dcb7c21d8ca1a2482ee0f1d341f437c9a7af6ca6da359dc5e1b164e98215" +checksum = "df631ae429f6613fcd3a7c1adbdb65f637271e561b03680adaa6573015dfb106" dependencies = [ "clap", ] @@ -762,7 +762,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -849,15 +849,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -923,9 +923,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -941,12 +941,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -970,7 +967,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossterm_winapi", "libc", "parking_lot", @@ -1003,7 +1000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -1073,9 +1070,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -1173,9 +1170,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -1208,9 +1205,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -1223,7 +1220,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "pin-project-lite", ] @@ -1298,9 +1295,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1313,9 +1310,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1323,15 +1320,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1340,9 +1337,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1361,26 +1358,26 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -1390,9 +1387,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1442,9 +1439,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -1474,7 +1471,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.3", + "regex-automata 0.4.4", "regex-syntax 0.8.2", ] @@ -1491,9 +1488,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -1528,9 +1525,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hkdf" @@ -1622,9 +1619,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1637,7 +1634,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1660,9 +1657,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1779,13 +1776,13 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1858,9 +1855,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" @@ -1884,7 +1881,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall", ] @@ -1900,9 +1897,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1945,9 +1942,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -2003,11 +2000,11 @@ dependencies = [ [[package]] name = "napi" -version = "2.14.1" +version = "2.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" +checksum = "902495f6b80f53f8435aefbbd2241c9c675fa239cd7e5f8e28fb57f3b69ecd09" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "ctor", "napi-derive", "napi-sys", @@ -2023,23 +2020,23 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.14.4" +version = "2.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5af262f1d8e660742eb722abc7113a5b3c3de4144d0ef23ede2518672ceff1" +checksum = "e61bec1ee990ae3e9a5f443484c65fb38e571a898437f0ad283ed69c82fc59c0" dependencies = [ "cfg-if", "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "napi-derive-backend" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea236321b521d6926213a2021e407b0562e28a257c037a45919e414d2cdb4f8" +checksum = "2314f777bc9cde51705d991c44466cee4de4a3f41c6d3d019fcbbebb5cdd47c4" dependencies = [ "convert_case", "once_cell", @@ -2047,7 +2044,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -2168,9 +2165,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2350,9 +2347,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "plain" @@ -2366,7 +2363,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "indexmap 2.1.0", "line-wrap", "quick-xml", @@ -2388,9 +2385,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.75" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2477,7 +2474,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -2489,7 +2486,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -2575,7 +2572,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", ] [[package]] @@ -2602,20 +2599,20 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.4", "regex-syntax 0.8.2", ] @@ -2630,9 +2627,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", @@ -2659,11 +2656,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2720,7 +2717,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.11", + "getrandom 0.2.12", "libc", "spin 0.9.8", "untrusted", @@ -2755,11 +2752,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -2796,14 +2793,14 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] name = "rustls-platform-verifier" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c573e165e19be8c9fc0264ee041d66292d4ee0439949af61d71fa747bf5df082" +checksum = "92c57b5de012da34087f2fe711fa29770f9a7abdde660b01bac3c9dbdee91b84" dependencies = [ "core-foundation", "core-foundation-sys", @@ -2865,11 +2862,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2928,7 +2925,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -2980,9 +2977,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" dependencies = [ "serde", ] @@ -3004,7 +3001,7 @@ checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3053,20 +3050,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -3085,9 +3082,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.27" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" +checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" dependencies = [ "indexmap 2.1.0", "itoa", @@ -3184,9 +3181,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smawk" @@ -3194,16 +3191,6 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.5" @@ -3270,7 +3257,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3302,9 +3289,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.47" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -3353,9 +3340,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.12" +version = "0.12.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" [[package]] name = "tempfile" @@ -3372,9 +3359,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -3407,7 +3394,7 @@ checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3422,9 +3409,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", @@ -3442,9 +3429,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -3476,7 +3463,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.5", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -3489,7 +3476,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3584,7 +3571,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3659,9 +3646,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3757,7 +3744,7 @@ version = "0.25.2" source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" dependencies = [ "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -3788,7 +3775,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.47", + "syn 2.0.48", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3867,9 +3854,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ "serde", ] @@ -3946,7 +3933,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -3980,7 +3967,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4013,14 +4000,14 @@ checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" dependencies = [ "proc-macro2", "quote", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -4082,20 +4069,11 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.52.0", ] [[package]] @@ -4116,21 +4094,6 @@ dependencies = [ "windows-targets 0.52.0", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.48.5" @@ -4161,12 +4124,6 @@ dependencies = [ "windows_x86_64_msvc 0.52.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4179,12 +4136,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -4197,12 +4148,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -4215,12 +4160,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -4233,12 +4172,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -4251,12 +4184,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -4269,12 +4196,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -4289,9 +4210,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.28" +version = "0.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" dependencies = [ "memchr", ] @@ -4314,7 +4235,7 @@ checksum = "13a3a53eaf34f390dd30d7b1b078287dd05df2aa2e21a589ccb80f5c7253c2e9" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.5", + "base64 0.21.7", "deadpool", "futures", "futures-timer", diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 27e945f60..6d1288fa9 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", - "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "version": "20.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.6.tgz", + "integrity": "sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==", "dev": true, "peer": true, "dependencies": { @@ -105,9 +105,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -117,9 +117,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", - "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index f5447f5fe..4f2b52824 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.8.tgz", - "integrity": "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==", + "version": "18.19.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", + "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/package-lock.json b/package-lock.json index 07b2080f6..f7c429825 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", - "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -178,61 +178,7 @@ "node": ">=8" } }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" - }, - "bin": { - "opencollective": "bin/opencollective.js" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/@openapitools/openapi-generator-cli": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.9.0.tgz", - "integrity": "sha512-KQpftKeiMoH5aEI/amOVLFGkGeT3DyA7Atj7v7l8xT3O9xnIUpoDmMg0WBTEh+NHxEwEAITQNDzr+JLjkXVaKw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@nestjs/axios": "3.0.1", - "@nestjs/common": "10.3.0", - "@nestjs/core": "10.3.0", - "@nuxtjs/opencollective": "0.3.2", - "axios": "1.6.5", - "chalk": "4.1.2", - "commander": "8.3.0", - "compare-versions": "4.1.4", - "concurrently": "6.5.1", - "console.table": "0.10.0", - "fs-extra": "10.1.0", - "glob": "7.2.3", - "inquirer": "8.2.6", - "lodash": "4.17.21", - "reflect-metadata": "0.1.13", - "rxjs": "7.8.1", - "tslib": "2.6.2" - }, - "bin": { - "openapi-generator-cli": "main.js" - }, - "engines": { - "node": ">=10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openapi_generator" - } - }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/axios": { + "node_modules/@nestjs/axios": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.0.1.tgz", "integrity": "sha512-VlOZhAGDmOoFdsmewn8AyClAdGpKXQQaY1+3PGB+g6ceurGIdTxZgRX3VXc1T6Zs60PedWjg3A82TDOB05mrzQ==", @@ -244,7 +190,7 @@ "rxjs": "^6.0.0 || ^7.0.0" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/common": { + "node_modules/@nestjs/common": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.0.tgz", "integrity": "sha512-DGv34UHsZBxCM3H5QGE2XE/+oLJzz5+714JQjBhjD9VccFlQs3LRxo/epso4l7nJIiNlZkPyIUC8WzfU/5RTsQ==", @@ -273,7 +219,7 @@ } } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/@nestjs/core": { + "node_modules/@nestjs/core": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.0.tgz", "integrity": "sha512-N06P5ncknW/Pm8bj964WvLIZn2gNhHliCBoAO1LeBvNImYkecqKcrmLbY49Fa1rmMfEM3MuBHeDys3edeuYAOA==", @@ -311,27 +257,58 @@ } } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.4", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" } }, - "node_modules/@openapitools/openapi-generator-cli/node_modules/uid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", - "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "node_modules/@openapitools/openapi-generator-cli": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@openapitools/openapi-generator-cli/-/openapi-generator-cli-2.9.0.tgz", + "integrity": "sha512-KQpftKeiMoH5aEI/amOVLFGkGeT3DyA7Atj7v7l8xT3O9xnIUpoDmMg0WBTEh+NHxEwEAITQNDzr+JLjkXVaKw==", "dev": true, + "hasInstallScript": true, "dependencies": { - "@lukeed/csprng": "^1.0.0" + "@nestjs/axios": "3.0.1", + "@nestjs/common": "10.3.0", + "@nestjs/core": "10.3.0", + "@nuxtjs/opencollective": "0.3.2", + "axios": "1.6.5", + "chalk": "4.1.2", + "commander": "8.3.0", + "compare-versions": "4.1.4", + "concurrently": "6.5.1", + "console.table": "0.10.0", + "fs-extra": "10.1.0", + "glob": "7.2.3", + "inquirer": "8.2.6", + "lodash": "4.17.21", + "reflect-metadata": "0.1.13", + "rxjs": "7.8.1", + "tslib": "2.6.2" + }, + "bin": { + "openapi-generator-cli": "main.js" }, "engines": { - "node": ">=8" + "node": ">=10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openapi_generator" } }, "node_modules/@pkgjs/parseargs": { @@ -369,9 +346,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.10.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz", - "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==", + "version": "20.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.6.tgz", + "integrity": "sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==", "dev": true, "peer": true, "dependencies": { @@ -397,9 +374,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -409,9 +386,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", - "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" @@ -468,6 +445,17 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/axios": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -611,6 +599,23 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", @@ -1138,20 +1143,6 @@ "node": ">=12.0.0" } }, - "node_modules/inquirer/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1222,9 +1213,9 @@ } }, "node_modules/js-base64": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", - "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==", + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.6.tgz", + "integrity": "sha512-NPrWuHFxFUknr1KqJRDgUQPexQF0uIJWjeT+2KjEePhitQxQEx5EJBG1lVn5/hc8aLycTpXrDOgPQ6Zq+EDiTA==", "dev": true }, "node_modules/jsonfile": { @@ -1971,6 +1962,18 @@ "node": ">=0.8.0" } }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "dev": true, + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -2078,9 +2081,9 @@ "dev": true }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -2088,10 +2091,7 @@ "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=8" } }, "node_modules/wrap-ansi-cjs": { From 25e65e4fa38d2baba915d2ddc477ba86d322edaa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:56:02 +0100 Subject: [PATCH 224/378] [deps]: Update Rust crate chrono to 0.4.33 (#539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [chrono](https://togithub.com/chronotope/chrono) | dependencies | patch | `0.4.31` -> `0.4.33` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index c2530af63..9aeed31ff 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -16,7 +16,7 @@ keywords = ["bitwarden", "secrets-manager", "cli"] bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } -chrono = { version = "0.4.31", features = [ +chrono = { version = "0.4.33", features = [ "clock", "std", ], default-features = false } From 40e45d496241cc827bc61d0524a3261f5946cd13 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:56:36 +0100 Subject: [PATCH 225/378] [deps]: Update Rust crate clap_complete to 4.4.9 (#540) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap_complete](https://togithub.com/clap-rs/clap) ([source](https://togithub.com/clap-rs/clap/tree/HEAD/clap_complete)) | dependencies | patch | `4.4.8` -> `4.4.9` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 9aeed31ff..fd723d3e6 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.33", features = [ "std", ], default-features = false } clap = { version = "4.4.18", features = ["derive", "env", "string"] } -clap_complete = "4.4.8" +clap_complete = "4.4.9" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" From bc995a8b551f635bf351e5be6801cc2c491a12da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 25 Jan 2024 16:02:58 +0100 Subject: [PATCH 226/378] [PM-5728] Enable Zeroize support for keys and EncStrings (#515) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective - Implemented Zeroize support for the encryption keys and the encStrings. - Boxed the internals of the encryption keys to avoid Rust from moving them around on the stack. - Changed some functions that passed around owned copies of the GenericArrays to pass references instead. GenericArray implements Copy, so passing them around by value only means more stack copies if the compiler can't optimize them out. - Changed the from impls for SymmCryptoKey to take mut slices so we can zeroize them after load. --- Cargo.lock | 20 ++++ crates/bitwarden-crypto/Cargo.toml | 7 +- crates/bitwarden-crypto/src/aes.rs | 36 +++--- .../src/enc_string/asymmetric.rs | 90 ++++++++------- .../src/enc_string/symmetric.rs | 20 ++-- .../src/keys/asymmetric_crypto_key.rs | 27 ++++- .../bitwarden-crypto/src/keys/device_key.rs | 8 +- .../bitwarden-crypto/src/keys/master_key.rs | 67 +++++------ .../src/keys/shareable_key.rs | 9 +- .../src/keys/symmetric_crypto_key.rs | 106 ++++++++++++------ crates/bitwarden-crypto/src/rsa.rs | 3 +- crates/bitwarden-crypto/src/util.rs | 13 ++- .../bitwarden/src/auth/login/access_token.rs | 4 +- .../src/client/encryption_settings.rs | 4 +- .../bitwarden/src/vault/cipher/attachment.rs | 4 +- crates/bitwarden/src/vault/cipher/cipher.rs | 4 +- 16 files changed, 260 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0a748276..36b37504c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,7 @@ dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] @@ -131,6 +132,7 @@ dependencies = [ "blake2", "cpufeatures", "password-hash", + "zeroize", ] [[package]] @@ -427,6 +429,7 @@ dependencies = [ "argon2", "base64 0.21.7", "cbc", + "generic-array", "hkdf", "hmac", "num-bigint", @@ -444,6 +447,7 @@ dependencies = [ "thiserror", "uniffi", "uuid", + "zeroize", ] [[package]] @@ -720,6 +724,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", + "zeroize", ] [[package]] @@ -1424,6 +1429,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -4254,6 +4260,20 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] [[package]] name = "zxcvbn" diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index ddcaceb06..1920fa991 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -18,12 +18,14 @@ default = [] mobile = ["uniffi"] [dependencies] -aes = ">=0.8.2, <0.9" +aes = { version = ">=0.8.2, <0.9", features = ["zeroize"] } argon2 = { version = ">=0.5.0, <0.6", features = [ "alloc", + "zeroize", ], default-features = false } base64 = ">=0.21.2, <0.22" -cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } +cbc = { version = ">=0.1.2, <0.2", features = ["alloc", "zeroize"] } +generic-array = { version = ">=0.14.7, <1.0", features = ["zeroize"] } hkdf = ">=0.12.3, <0.13" hmac = ">=0.12.1, <0.13" num-bigint = ">=0.4, <0.5" @@ -39,6 +41,7 @@ subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.2", optional = true } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } +zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } [dev-dependencies] rand_chacha = "0.3.1" diff --git a/crates/bitwarden-crypto/src/aes.rs b/crates/bitwarden-crypto/src/aes.rs index e948fdc18..195b818b7 100644 --- a/crates/bitwarden-crypto/src/aes.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -6,9 +6,9 @@ //! [KeyEncryptable][crate::KeyEncryptable] & [KeyDecryptable][crate::KeyDecryptable] instead. use aes::cipher::{ - block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, - BlockEncryptMut, KeyIvInit, + block_padding::Pkcs7, typenum::U32, BlockDecryptMut, BlockEncryptMut, KeyIvInit, }; +use generic_array::GenericArray; use hmac::Mac; use subtle::ConstantTimeEq; @@ -23,12 +23,12 @@ use crate::{ pub(crate) fn decrypt_aes256( iv: &[u8; 16], data: Vec, - key: GenericArray, + key: &GenericArray, ) -> Result> { // Decrypt data let iv = GenericArray::from_slice(iv); let mut data = data; - let decrypted_key_slice = cbc::Decryptor::::new(&key, iv) + let decrypted_key_slice = cbc::Decryptor::::new(key, iv) .decrypt_padded_mut::(&mut data) .map_err(|_| CryptoError::KeyDecrypt)?; @@ -47,10 +47,10 @@ pub(crate) fn decrypt_aes256_hmac( iv: &[u8; 16], mac: &[u8; 32], data: Vec, - mac_key: GenericArray, - key: GenericArray, + mac_key: &GenericArray, + key: &GenericArray, ) -> Result> { - let res = generate_mac(&mac_key, iv, &data)?; + let res = generate_mac(mac_key, iv, &data)?; if res.ct_ne(mac).into() { return Err(CryptoError::InvalidMac); } @@ -65,7 +65,7 @@ pub(crate) fn decrypt_aes256_hmac( /// /// A AesCbc256_B64 EncString #[allow(unused)] -pub(crate) fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u8; 16], Vec) { +pub(crate) fn encrypt_aes256(data_dec: &[u8], key: &GenericArray) -> ([u8; 16], Vec) { let rng = rand::thread_rng(); let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); @@ -81,12 +81,12 @@ pub(crate) fn encrypt_aes256(data_dec: &[u8], key: GenericArray) -> ([u /// A AesCbc256_HmacSha256_B64 EncString pub(crate) fn encrypt_aes256_hmac( data_dec: &[u8], - mac_key: GenericArray, - key: GenericArray, + mac_key: &GenericArray, + key: &GenericArray, ) -> Result<([u8; 16], [u8; 32], Vec)> { let rng = rand::thread_rng(); let (iv, data) = encrypt_aes256_internal(rng, data_dec, key); - let mac = generate_mac(&mac_key, &iv, &data)?; + let mac = generate_mac(mac_key, &iv, &data)?; Ok((iv, mac, data)) } @@ -99,11 +99,11 @@ pub(crate) fn encrypt_aes256_hmac( fn encrypt_aes256_internal( mut rng: impl rand::RngCore, data_dec: &[u8], - key: GenericArray, + key: &GenericArray, ) -> ([u8; 16], Vec) { let mut iv = [0u8; 16]; rng.fill_bytes(&mut iv); - let data = cbc::Encryptor::::new(&key, &iv.into()) + let data = cbc::Encryptor::::new(key, &iv.into()) .encrypt_padded_vec_mut::(data_dec); (iv, data) @@ -123,8 +123,8 @@ fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { #[cfg(test)] mod tests { - use aes::cipher::generic_array::sequence::GenericSequence; use base64::{engine::general_purpose::STANDARD, Engine}; + use generic_array::sequence::GenericSequence; use rand::SeedableRng; use super::*; @@ -146,7 +146,7 @@ mod tests { let key = generate_generic_array(0, 1); let rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); - let result = encrypt_aes256_internal(rng, "EncryptMe!".as_bytes(), key); + let result = encrypt_aes256_internal(rng, "EncryptMe!".as_bytes(), &key); assert_eq!( result, ( @@ -177,7 +177,7 @@ mod tests { let key = generate_generic_array(0, 1); let data = STANDARD.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); - let decrypted = decrypt_aes256(iv, data, key).unwrap(); + let decrypted = decrypt_aes256(iv, data, &key).unwrap(); assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); } @@ -187,8 +187,8 @@ mod tests { let key = generate_generic_array(0, 1); let data = "EncryptMe!"; - let (iv, encrypted) = encrypt_aes256(data.as_bytes(), key); - let decrypted = decrypt_aes256(&iv, encrypted, key).unwrap(); + let (iv, encrypted) = encrypt_aes256(data.as_bytes(), &key); + let decrypted = decrypt_aes256(&iv, encrypted, &key).unwrap(); assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); } diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index ea969f4f9..04768db9e 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -1,6 +1,7 @@ use std::{fmt::Display, str::FromStr}; use base64::{engine::general_purpose::STANDARD, Engine}; +pub use internal::AsymmetricEncString; use rsa::Oaep; use serde::Deserialize; @@ -11,48 +12,53 @@ use crate::{ AsymmetricCryptoKey, AsymmetricEncryptable, KeyDecryptable, }; -/// # Encrypted string primitive -/// -/// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically -/// encrypted string. They are used together with the KeyDecryptable and KeyEncryptable traits to -/// encrypt and decrypt data using [AsymmetricCryptoKey]s. -/// -/// The flexibility of the [AsymmetricEncString] type allows for different encryption algorithms to -/// be used which is represented by the different variants of the enum. -/// -/// ## Note -/// -/// For backwards compatibility we will rarely if ever be able to remove support for decrypting old -/// variants, but we should be opinionated in which variants are used for encrypting. -/// -/// ## Variants -/// - [Rsa2048_OaepSha256_B64](AsymmetricEncString::Rsa2048_OaepSha256_B64) -/// - [Rsa2048_OaepSha1_B64](AsymmetricEncString::Rsa2048_OaepSha1_B64) -/// -/// ## Serialization -/// -/// [AsymmetricEncString] implements [Display] and [FromStr] to allow for easy serialization and -/// uses a custom scheme to represent the different variants. -/// -/// The scheme is one of the following schemes: -/// - `[type].[data]` -/// -/// Where: -/// - `[type]`: is a digit number representing the variant. -/// - `[data]`: is the encrypted data. -#[derive(Clone)] -#[allow(unused, non_camel_case_types)] -pub enum AsymmetricEncString { - /// 3 - Rsa2048_OaepSha256_B64 { data: Vec }, - /// 4 - Rsa2048_OaepSha1_B64 { data: Vec }, - /// 5 - #[deprecated] - Rsa2048_OaepSha256_HmacSha256_B64 { data: Vec, mac: Vec }, - /// 6 - #[deprecated] - Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec, mac: Vec }, +// This module is a workaround to avoid deprecated warnings that come from the ZeroizeOnDrop +// macro expansion +#[allow(deprecated)] +mod internal { + /// # Encrypted string primitive + /// + /// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically + /// encrypted string. They are used together with the KeyDecryptable and KeyEncryptable + /// traits to encrypt and decrypt data using [crate::AsymmetricCryptoKey]s. + /// + /// The flexibility of the [AsymmetricEncString] type allows for different encryption algorithms + /// to be used which is represented by the different variants of the enum. + /// + /// ## Note + /// + /// For backwards compatibility we will rarely if ever be able to remove support for decrypting + /// old variants, but we should be opinionated in which variants are used for encrypting. + /// + /// ## Variants + /// - [Rsa2048_OaepSha256_B64](AsymmetricEncString::Rsa2048_OaepSha256_B64) + /// - [Rsa2048_OaepSha1_B64](AsymmetricEncString::Rsa2048_OaepSha1_B64) + /// + /// ## Serialization + /// + /// [AsymmetricEncString] implements [std::fmt::Display] and [std::str::FromStr] to allow for + /// easy serialization and uses a custom scheme to represent the different variants. + /// + /// The scheme is one of the following schemes: + /// - `[type].[data]` + /// + /// Where: + /// - `[type]`: is a digit number representing the variant. + /// - `[data]`: is the encrypted data. + #[derive(Clone, zeroize::ZeroizeOnDrop)] + #[allow(unused, non_camel_case_types)] + pub enum AsymmetricEncString { + /// 3 + Rsa2048_OaepSha256_B64 { data: Vec }, + /// 4 + Rsa2048_OaepSha1_B64 { data: Vec }, + /// 5 + #[deprecated] + Rsa2048_OaepSha256_HmacSha256_B64 { data: Vec, mac: Vec }, + /// 6 + #[deprecated] + Rsa2048_OaepSha1_HmacSha256_B64 { data: Vec, mac: Vec }, + } } /// To avoid printing sensitive information, [AsymmetricEncString] debug prints to diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index 25a0a8280..a76315e96 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -1,7 +1,8 @@ use std::{fmt::Display, str::FromStr}; -use aes::cipher::{generic_array::GenericArray, typenum::U32}; +use aes::cipher::typenum::U32; use base64::{engine::general_purpose::STANDARD, Engine}; +use generic_array::GenericArray; use serde::Deserialize; use super::{check_length, from_b64, from_b64_vec, split_enc_string}; @@ -43,7 +44,7 @@ use crate::{ /// - `[iv]`: (optional) is the initialization vector used for encryption. /// - `[data]`: is the encrypted data. /// - `[mac]`: (optional) is the MAC used to validate the integrity of the data. -#[derive(Clone)] +#[derive(Clone, zeroize::ZeroizeOnDrop)] #[allow(unused, non_camel_case_types)] pub enum EncString { /// 0 @@ -204,8 +205,8 @@ impl serde::Serialize for EncString { impl EncString { pub fn encrypt_aes256_hmac( data_dec: &[u8], - mac_key: GenericArray, - key: GenericArray, + mac_key: &GenericArray, + key: &GenericArray, ) -> Result { let (iv, mac, data) = crate::aes::encrypt_aes256_hmac(data_dec, mac_key, key)?; Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) @@ -224,7 +225,11 @@ impl EncString { impl LocateKey for EncString {} impl KeyEncryptable for &[u8] { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { - EncString::encrypt_aes256_hmac(self, key.mac_key.ok_or(CryptoError::InvalidMac)?, key.key) + EncString::encrypt_aes256_hmac( + self, + key.mac_key.as_ref().ok_or(CryptoError::InvalidMac)?, + &key.key, + ) } } @@ -232,8 +237,9 @@ impl KeyDecryptable> for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { - let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; - let dec = crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?; + let mac_key = key.mac_key.as_ref().ok_or(CryptoError::InvalidMac)?; + let dec = + crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, &key.key)?; Ok(dec) } _ => Err(CryptoError::InvalidKey), diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index 560e7e4cc..be523bbc6 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -1,3 +1,5 @@ +use std::pin::Pin; + use rsa::{pkcs8::DecodePublicKey, RsaPrivateKey, RsaPublicKey}; use super::key_encryptable::CryptoKey; @@ -35,30 +37,45 @@ impl AsymmetricEncryptable for AsymmetricPublicCryptoKey { /// An asymmetric encryption key. Contains both the public and private key. Can be used to both /// encrypt and decrypt [`AsymmetricEncString`](crate::AsymmetricEncString). pub struct AsymmetricCryptoKey { - pub(crate) key: RsaPrivateKey, + // RsaPrivateKey is not a Copy type so this isn't completely necessary, but + // to keep the compiler from making stack copies when moving this struct around, + // we use a Box to keep the values on the heap. We also pin the box to make sure + // that the contents can't be pulled out of the box and moved + pub(crate) key: Pin>, } +// Note that RsaPrivateKey already implements ZeroizeOnDrop, so we don't need to do anything +// We add this assertion to make sure that this is still true in the future +const _: () = { + fn assert_zeroize_on_drop() {} + fn assert_all() { + assert_zeroize_on_drop::(); + } +}; + +impl zeroize::ZeroizeOnDrop for AsymmetricCryptoKey {} + impl AsymmetricCryptoKey { /// Generate a random AsymmetricCryptoKey (RSA-2048). pub fn generate(rng: &mut R) -> Self { let bits = 2048; Self { - key: RsaPrivateKey::new(rng, bits).expect("failed to generate a key"), + key: Box::pin(RsaPrivateKey::new(rng, bits).expect("failed to generate a key")), } } pub fn from_pem(pem: &str) -> Result { use rsa::pkcs8::DecodePrivateKey; Ok(Self { - key: rsa::RsaPrivateKey::from_pkcs8_pem(pem).map_err(|_| CryptoError::InvalidKey)?, + key: Box::pin(RsaPrivateKey::from_pkcs8_pem(pem).map_err(|_| CryptoError::InvalidKey)?), }) } pub fn from_der(der: &[u8]) -> Result { use rsa::pkcs8::DecodePrivateKey; Ok(Self { - key: rsa::RsaPrivateKey::from_pkcs8_der(der).map_err(|_| CryptoError::InvalidKey)?, + key: Box::pin(RsaPrivateKey::from_pkcs8_der(der).map_err(|_| CryptoError::InvalidKey)?), }) } @@ -85,7 +102,7 @@ impl AsymmetricCryptoKey { impl AsymmetricEncryptable for AsymmetricCryptoKey { fn to_public_key(&self) -> &RsaPublicKey { - self.key.as_ref() + (*self.key).as_ref() } } diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs index 6588944fe..37bcd58f9 100644 --- a/crates/bitwarden-crypto/src/keys/device_key.rs +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -63,8 +63,8 @@ impl DeviceKey { let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; let device_private_key = AsymmetricCryptoKey::from_der(device_private_key.as_slice())?; - let dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; - let user_key: SymmetricCryptoKey = dec.as_slice().try_into()?; + let mut dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; + let user_key: SymmetricCryptoKey = dec.as_mut_slice().try_into()?; Ok(UserKey(user_key)) } @@ -96,7 +96,7 @@ mod tests { #[test] fn test_decrypt_user_key() { // Example keys from desktop app - let user_key: &[u8] = &[ + let user_key: &mut [u8] = &mut [ 109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216, 212, 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91, 215, 21, 128, 91, 226, 222, 165, 67, 251, 34, 83, 81, 77, 147, 225, 76, 13, 41, 102, 45, 183, @@ -104,7 +104,7 @@ mod tests { ]; let user_key = SymmetricCryptoKey::try_from(user_key).unwrap(); - let key_data: &[u8] = &[ + let key_data: &mut [u8] = &mut [ 114, 235, 60, 115, 172, 156, 203, 145, 195, 130, 215, 250, 88, 146, 215, 230, 12, 109, 245, 222, 54, 217, 255, 211, 221, 105, 230, 236, 65, 52, 209, 133, 76, 208, 113, 254, 194, 216, 156, 19, 230, 62, 32, 93, 87, 7, 144, 156, 117, 142, 250, 32, 182, 118, 187, diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index bdd626a1a..920f103e4 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -1,7 +1,8 @@ -use std::num::NonZeroU32; +use std::{num::NonZeroU32, pin::Pin}; -use aes::cipher::{generic_array::GenericArray, typenum::U32}; +use aes::cipher::typenum::U32; use base64::{engine::general_purpose::STANDARD, Engine}; +use generic_array::GenericArray; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use sha2::Digest; @@ -59,8 +60,8 @@ impl MasterKey { pub fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; - let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; - SymmetricCryptoKey::try_from(dec.as_slice()) + let mut dec: Vec = user_key.decrypt_with_key(&stretched_key)?; + SymmetricCryptoKey::try_from(dec.as_mut_slice()) } pub fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result { @@ -68,8 +69,8 @@ impl MasterKey { EncString::encrypt_aes256_hmac( user_key.to_vec().as_slice(), - stretched_key.mac_key.unwrap(), - stretched_key.key, + stretched_key.mac_key.as_ref().unwrap(), + &stretched_key.key, ) } } @@ -86,7 +87,7 @@ fn make_user_key( /// Derive a generic key from a secret and salt using the provided KDF. fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { - let hash = match kdf { + let mut hash = match kdf { Kdf::PBKDF2 { iterations } => crate::util::pbkdf2(secret, salt, iterations.get()), Kdf::Argon2id { @@ -117,17 +118,13 @@ fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result Result { - let key: GenericArray = hkdf_expand(&master_key.0.key, Some("enc"))?; - let mac_key: GenericArray = hkdf_expand(&master_key.0.key, Some("mac"))?; - - Ok(SymmetricCryptoKey { - key, - mac_key: Some(mac_key), - }) + let key: Pin>> = hkdf_expand(&master_key.0.key, Some("enc"))?; + let mac_key: Pin>> = hkdf_expand(&master_key.0.key, Some("mac"))?; + Ok(SymmetricCryptoKey::new(key, Some(mac_key))) } #[cfg(test)] @@ -185,14 +182,16 @@ mod tests { #[test] fn test_stretch_master_key() { - let master_key = MasterKey(SymmetricCryptoKey { - key: [ - 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, 167, - 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, - ] - .into(), - mac_key: None, - }); + let master_key = MasterKey(SymmetricCryptoKey::new( + Box::pin( + [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, + 167, 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + ), + None, + )); let stretched = stretch_master_key(&master_key).unwrap(); @@ -208,7 +207,7 @@ mod tests { 221, 127, 206, 234, 101, 27, 202, 38, 86, 52, 34, 28, 78, 28, 185, 16, 48, 61, 127, 166, 209, 247, 194, 87, 232, 26, 48, 85, 193, 249, 179, 155 ], - stretched.mac_key.unwrap().as_slice() + stretched.mac_key.as_ref().unwrap().as_slice() ); } @@ -254,14 +253,16 @@ mod tests { fn test_make_user_key() { let mut rng = rand_chacha::ChaCha8Rng::from_seed([0u8; 32]); - let master_key = MasterKey(SymmetricCryptoKey { - key: [ - 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, 167, - 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, - ] - .into(), - mac_key: None, - }); + let master_key = MasterKey(SymmetricCryptoKey::new( + Box::pin( + [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, + 167, 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + ), + None, + )); let (user_key, protected) = make_user_key(&mut rng, &master_key).unwrap(); @@ -273,7 +274,7 @@ mod tests { ] ); assert_eq!( - user_key.0.mac_key.unwrap().as_slice(), + user_key.0.mac_key.as_ref().unwrap().as_slice(), [ 152, 76, 225, 114, 185, 33, 111, 65, 159, 68, 83, 103, 69, 109, 86, 25, 49, 74, 66, 163, 218, 134, 176, 1, 56, 123, 253, 184, 14, 12, 254, 66 diff --git a/crates/bitwarden-crypto/src/keys/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs index eb5353401..fbb2d2e44 100644 --- a/crates/bitwarden-crypto/src/keys/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -1,4 +1,7 @@ -use aes::cipher::{generic_array::GenericArray, typenum::U64}; +use std::pin::Pin; + +use aes::cipher::typenum::U64; +use generic_array::GenericArray; use hmac::{Hmac, Mac}; use crate::{keys::SymmetricCryptoKey, util::hkdf_expand}; @@ -22,9 +25,9 @@ pub fn derive_shareable_key( .finalize() .into_bytes(); - let key: GenericArray = hkdf_expand(&res, info).unwrap(); + let mut key: Pin>> = hkdf_expand(&res, info).unwrap(); - SymmetricCryptoKey::try_from(key.as_slice()).unwrap() + SymmetricCryptoKey::try_from(key.as_mut_slice()).unwrap() } #[cfg(test)] diff --git a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 31b00fd54..0c165bb40 100644 --- a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -1,54 +1,80 @@ -use std::str::FromStr; +use std::{pin::Pin, str::FromStr}; -use aes::cipher::{generic_array::GenericArray, typenum::U32}; +use aes::cipher::typenum::U32; use base64::{engine::general_purpose::STANDARD, Engine}; +use generic_array::GenericArray; use rand::Rng; +use zeroize::{Zeroize, Zeroizing}; use super::key_encryptable::CryptoKey; use crate::CryptoError; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { - pub(crate) key: GenericArray, - pub(crate) mac_key: Option>, + // GenericArray is equivalent to [u8; N], which is a Copy type placed on the stack. + // To keep the compiler from making stack copies when moving this struct around, + // we use a Box to keep the values on the heap. We also pin the box to make sure + // that the contents can't be pulled out of the box and moved + pub(crate) key: Pin>>, + pub(crate) mac_key: Option>>>, } +impl Drop for SymmetricCryptoKey { + fn drop(&mut self) { + self.key.zeroize(); + if let Some(mac_key) = &mut self.mac_key { + mac_key.zeroize(); + } + } +} + +impl zeroize::ZeroizeOnDrop for SymmetricCryptoKey {} + impl SymmetricCryptoKey { const KEY_LEN: usize = 32; const MAC_LEN: usize = 32; /// Generate a new random [SymmetricCryptoKey] pub fn generate(mut rng: impl rand::RngCore) -> Self { - let mut key = [0u8; Self::KEY_LEN]; - let mut mac_key = [0u8; Self::MAC_LEN]; + let mut key = Box::pin(GenericArray::::default()); + let mut mac_key = Box::pin(GenericArray::::default()); - rng.fill(&mut key); - rng.fill(&mut mac_key); + rng.fill(key.as_mut_slice()); + rng.fill(mac_key.as_mut_slice()); SymmetricCryptoKey { - key: key.into(), - mac_key: Some(mac_key.into()), + key, + mac_key: Some(mac_key), } } - pub fn to_base64(&self) -> String { - let mut buf = Vec::new(); - buf.extend_from_slice(&self.key); + pub(crate) fn new( + key: Pin>>, + mac_key: Option>>>, + ) -> Self { + Self { key, mac_key } + } - if let Some(mac) = self.mac_key { - buf.extend_from_slice(&mac); - } + fn total_len(&self) -> usize { + self.key.len() + self.mac_key.as_ref().map_or(0, |mac| mac.len()) + } - STANDARD.encode(&buf) + pub fn to_base64(&self) -> String { + let mut buf = self.to_vec(); + + let result = STANDARD.encode(&buf); + buf.zeroize(); + result } - pub fn to_vec(&self) -> Vec { - let mut buf = Vec::new(); + pub fn to_vec(&self) -> Zeroizing> { + let mut buf = Vec::with_capacity(self.total_len()); + buf.extend_from_slice(&self.key); - if let Some(mac) = self.mac_key { - buf.extend_from_slice(&mac); + if let Some(mac) = &self.mac_key { + buf.extend_from_slice(mac); } - buf + Zeroizing::new(buf) } } @@ -56,28 +82,40 @@ impl FromStr for SymmetricCryptoKey { type Err = CryptoError; fn from_str(s: &str) -> Result { - let bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; - SymmetricCryptoKey::try_from(bytes.as_slice()) + let mut bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; + SymmetricCryptoKey::try_from(bytes.as_mut_slice()) } } -impl TryFrom<&[u8]> for SymmetricCryptoKey { +impl TryFrom<&mut [u8]> for SymmetricCryptoKey { type Error = CryptoError; - fn try_from(value: &[u8]) -> Result { - if value.len() == Self::KEY_LEN + Self::MAC_LEN { + /// Note: This function takes the byte slice by mutable reference and will zero out all + /// the data in it. This is to prevent the key from being left in memory. + fn try_from(value: &mut [u8]) -> Result { + let result = if value.len() == Self::KEY_LEN + Self::MAC_LEN { + let mut key = Box::pin(GenericArray::::default()); + let mut mac_key = Box::pin(GenericArray::::default()); + + key.copy_from_slice(&value[..Self::KEY_LEN]); + mac_key.copy_from_slice(&value[Self::KEY_LEN..]); + Ok(SymmetricCryptoKey { - key: GenericArray::clone_from_slice(&value[..Self::KEY_LEN]), - mac_key: Some(GenericArray::clone_from_slice(&value[Self::KEY_LEN..])), + key, + mac_key: Some(mac_key), }) } else if value.len() == Self::KEY_LEN { - Ok(SymmetricCryptoKey { - key: GenericArray::clone_from_slice(value), - mac_key: None, - }) + let mut key = Box::pin(GenericArray::::default()); + + key.copy_from_slice(&value[..Self::KEY_LEN]); + + Ok(SymmetricCryptoKey { key, mac_key: None }) } else { Err(CryptoError::InvalidKeyLen) - } + }; + + value.zeroize(); + result } } diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index bee88a655..231e77aaa 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -36,7 +36,8 @@ pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_pkcs8_der() .map_err(|_| RsaError::CreatePrivateKey)?; - let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; + let protected = + EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.as_ref().unwrap(), &key.key)?; Ok(RsaKeyPair { public: b64, diff --git a/crates/bitwarden-crypto/src/util.rs b/crates/bitwarden-crypto/src/util.rs index 261424e51..ba60db366 100644 --- a/crates/bitwarden-crypto/src/util.rs +++ b/crates/bitwarden-crypto/src/util.rs @@ -1,4 +1,7 @@ -use ::aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; +use std::pin::Pin; + +use ::aes::cipher::{ArrayLength, Unsigned}; +use generic_array::GenericArray; use hmac::digest::OutputSizeUser; use rand::{ distributions::{Distribution, Standard}, @@ -15,15 +18,15 @@ pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = pub(crate) fn hkdf_expand>( prk: &[u8], info: Option<&str>, -) -> Result> { +) -> Result>>> { let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| CryptoError::InvalidKeyLen)?; - let mut key = GenericArray::::default(); + let mut key = Box::>::default(); let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); hkdf.expand(i, &mut key) .map_err(|_| CryptoError::InvalidKeyLen)?; - Ok(key) + Ok(Box::into_pin(key)) } /// Generate random bytes that are cryptographically secure @@ -53,7 +56,7 @@ mod tests { ]; let info = Some("info"); - let result: GenericArray = hkdf_expand(prk, info).unwrap(); + let result: Pin>> = hkdf_expand(prk, info).unwrap(); let expected_output: [u8; 64] = [ 6, 114, 42, 38, 87, 231, 30, 109, 30, 255, 104, 129, 255, 94, 92, 108, 124, 145, 215, diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index e4cce33e4..d540b31a8 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -63,8 +63,8 @@ pub(crate) async fn login_access_token( } let payload: Payload = serde_json::from_slice(&decrypted_payload)?; - let encryption_key = STANDARD.decode(payload.encryption_key.clone())?; - let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_slice())?; + let mut encryption_key = STANDARD.decode(payload.encryption_key.clone())?; + let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_mut_slice())?; let access_token_obj: JWTToken = r.access_token.parse()?; diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 8b4c5197e..6e4da9895 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -95,9 +95,9 @@ impl EncryptionSettings { // Decrypt the org keys with the private key for (org_id, org_enc_key) in org_enc_keys { - let dec: Vec = org_enc_key.decrypt_with_key(private_key)?; + let mut dec: Vec = org_enc_key.decrypt_with_key(private_key)?; - let org_key = SymmetricCryptoKey::try_from(dec.as_slice())?; + let org_key = SymmetricCryptoKey::try_from(dec.as_mut_slice())?; self.org_keys.insert(org_id, org_key); } diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 40f32dcfb..1ec6be6fe 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -80,13 +80,13 @@ impl KeyDecryptable> for AttachmentFile { let ciphers_key = Cipher::get_cipher_key(key, &self.cipher.key)?; let ciphers_key = ciphers_key.as_ref().unwrap_or(key); - let attachment_key: Vec = self + let mut attachment_key: Vec = self .attachment .key .as_ref() .ok_or(CryptoError::MissingKey)? .decrypt_with_key(ciphers_key)?; - let attachment_key = SymmetricCryptoKey::try_from(attachment_key.as_slice())?; + let attachment_key = SymmetricCryptoKey::try_from(attachment_key.as_mut_slice())?; self.contents.decrypt_with_key(&attachment_key) } diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 34f01ca60..bbd944871 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -218,8 +218,8 @@ impl Cipher { ciphers_key .as_ref() .map(|k| { - let key: Vec = k.decrypt_with_key(key)?; - SymmetricCryptoKey::try_from(key.as_slice()) + let mut key: Vec = k.decrypt_with_key(key)?; + SymmetricCryptoKey::try_from(key.as_mut_slice()) }) .transpose() } From 933930c7797a8226c6597879b0f04a2398fb201d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:11:38 +0100 Subject: [PATCH 227/378] [deps]: Update Rust crate uniffi to v0.26.1 (#538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [uniffi](https://mozilla.github.io/uniffi-rs) ([source](https://togithub.com/mozilla/uniffi-rs)) | dependencies | minor | `=0.25.2` -> `=0.26.1` | | [uniffi](https://mozilla.github.io/uniffi-rs) ([source](https://togithub.com/mozilla/uniffi-rs)) | build-dependencies | minor | `=0.25.2` -> `=0.26.1` | --- ### Release Notes
mozilla/uniffi-rs (uniffi) ### [`v0.26.0`](https://togithub.com/mozilla/uniffi-rs/blob/HEAD/CHANGELOG.md#v0260-backend-crates-v0260---2024-01-23) [Compare Source](https://togithub.com/mozilla/uniffi-rs/compare/v0.25.3...0.26.0) ##### What's changed? - The `rust_future_continuation_callback_set` FFI function was removed. `rust_future_poll` now inputs the callback pointer. External bindings authors will need to update their code. ##### What's new? - Rust traits `Display`, `Hash` and `Eq` exposed to Kotlin and Swift [#​1817](https://togithub.com/mozilla/uniffi-rs/pull/1817) - Foreign types can now implement trait interfaces [#​1791](https://togithub.com/mozilla/uniffi-rs/pull/1791) and [the documentation](https://mozilla.github.io/uniffi-rs/udl/interfaces.html#foreign-implementations) - UDL: use the `[WithForeign]` attribute - proc-macros: use the `#[uniffi::export(with_foreign)]` attribute - Generated Python code is able to specify a package name for the module [#​1784](https://togithub.com/mozilla/uniffi-rs/pull/1784) - UDL can describe async function [#​1834](https://togithub.com/mozilla/uniffi-rs/pull/1834) - UDL files can reference types defined in procmacros in this crate - see [the external types docs](https://mozilla.github.io/uniffi-rs/udl/ext_types.html) and also external trait interfaces [#​1831](https://togithub.com/mozilla/uniffi-rs/issues/1831) - Add support for docstrings via procmacros [#​1862](https://togithub.com/mozilla/uniffi-rs/pull/1862) and [in UDL](https://mozilla.github.io/uniffi-rs/udl/docstrings.html) - Objects can now be returned from functions/constructors/methods without wrapping them in an `Arc<>`. [All changes in v0.26.0](https://togithub.com/mozilla/uniffi-rs/compare/v0.25.2...v0.26.0). ### [`v0.25.3`](https://togithub.com/mozilla/uniffi-rs/blob/HEAD/CHANGELOG.md#v0253-backend-crates-v0253---2023-12-07) [Compare Source](https://togithub.com/mozilla/uniffi-rs/compare/v0.25.2...v0.25.3) [All changes in v0.25.3](https://togithub.com/mozilla/uniffi-rs/compare/v0.25.2...v0.25.3). - Switched to a patched version of `oneshot` so that consumers who use `cargo vendor` don't vendor `loom` and it's sub-dependencies like `windows`
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Hinton Co-authored-by: Daniel García --- Cargo.lock | 183 ++++++------------------ Cargo.toml | 8 -- crates/bitwarden-crypto/Cargo.toml | 2 +- crates/bitwarden-crypto/uniffi.toml | 1 + crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden-generators/uniffi.toml | 1 + crates/bitwarden-uniffi/Cargo.toml | 4 +- crates/bitwarden-uniffi/uniffi.toml | 1 + crates/bitwarden/Cargo.toml | 2 +- crates/bitwarden/uniffi.toml | 1 + crates/uniffi-bindgen/Cargo.toml | 2 +- languages/kotlin/sdk/build.gradle | 4 + languages/kotlin/sdk/lint-baseline.xml | 39 +++++ 13 files changed, 95 insertions(+), 155 deletions(-) create mode 100644 languages/kotlin/sdk/lint-baseline.xml diff --git a/Cargo.lock b/Cargo.lock index 36b37504c..1fefd59fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,7 +296,7 @@ dependencies = [ "flate2", "globset", "home", - "nu-ansi-term 0.49.0", + "nu-ansi-term", "once_cell", "path_abs", "plist", @@ -1408,19 +1408,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -1477,15 +1464,15 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.4", + "regex-automata", "regex-syntax 0.8.2", ] [[package]] name = "goblin" -version = "0.6.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6b4de4a8eb6c46a8c77e1d3be942cb9a8bf073c22374578e5ba4b08ed0ff68" +checksum = "bb07a4ffed2093b118a525b1d8f5204ae274faed5604537caf7135d0f18d9887" dependencies = [ "log", "plain", @@ -1923,29 +1910,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "pin-utils", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[package]] name = "memchr" version = "2.7.1" @@ -2081,16 +2045,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.49.0" @@ -2185,13 +2139,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "oneshot" +name = "oneshot-uniffi" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f6640c6bda7731b1fdbab747981a0f896dd1fedaf9f4a53fa237a04a84431f4" -dependencies = [ - "loom", -] +checksum = "6c548d5c78976f6955d72d0ced18c48ca07030f7a1d4024529fedd7c1c01b29c" [[package]] name = "onig" @@ -2227,12 +2178,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" version = "3.5.0" @@ -2618,19 +2563,10 @@ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", + "regex-automata", "regex-syntax 0.8.2", ] -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - [[package]] name = "regex-automata" version = "0.4.4" @@ -2642,12 +2578,6 @@ dependencies = [ "regex-syntax 0.8.2", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.7.5" @@ -2916,18 +2846,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scroll" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" dependencies = [ "scroll_derive", ] [[package]] name = "scroll_derive" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" +checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", @@ -3565,21 +3495,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - [[package]] name = "tracing-core" version = "0.1.32" @@ -3600,33 +3518,15 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - [[package]] name = "tracing-subscriber" version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "matchers", - "nu-ansi-term 0.46.0", - "once_cell", - "regex", "sharded-slab", - "smallvec", "thread_local", - "tracing", "tracing-core", - "tracing-log", ] [[package]] @@ -3691,8 +3591,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uniffi" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad0be8bba6c242d2d16922de4a9c8f167b9491729fda552e70f8626bf7302cb" dependencies = [ "anyhow", "camino", @@ -3712,8 +3613,9 @@ dependencies = [ [[package]] name = "uniffi_bindgen" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab31006ab9c9c6870739f0e74235729d1478d82e73571b8f53c25aa176d67535" dependencies = [ "anyhow", "askama", @@ -3736,8 +3638,9 @@ dependencies = [ [[package]] name = "uniffi_build" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa3a7608c6872dc1ce53199d816a24d2e19af952d82ce557ecc8692a4ae9cba" dependencies = [ "anyhow", "camino", @@ -3746,8 +3649,9 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72775b3afa6adb30e0c92b3107858d2fcb0ff1a417ac242db1f648b0e2dd0ef2" dependencies = [ "quote", "syn 2.0.48", @@ -3755,8 +3659,9 @@ dependencies = [ [[package]] name = "uniffi_core" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d6e8db3f4e558faf0e25ac4b5bd775567973a4e18809f1123e74de52a853692" dependencies = [ "anyhow", "async-compat", @@ -3764,15 +3669,16 @@ dependencies = [ "camino", "log", "once_cell", - "oneshot", + "oneshot-uniffi", "paste", "static_assertions", ] [[package]] name = "uniffi_macros" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a126650799f97d97d8e38e3f10f15c65f5bc5a76b021bec21823efe9dd831a02" dependencies = [ "bincode", "camino", @@ -3789,8 +3695,9 @@ dependencies = [ [[package]] name = "uniffi_meta" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f64a99e905671738d9d293f9cce58708ce1af8e13ea29f9d6b6925114fc2e85" dependencies = [ "anyhow", "bytes", @@ -3800,8 +3707,9 @@ dependencies = [ [[package]] name = "uniffi_testing" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdca5719a22edf34c8239cc6ac9e3906d7ebc2a3e8a5e6ece4c3dffc312a4251" dependencies = [ "anyhow", "camino", @@ -3812,8 +3720,9 @@ dependencies = [ [[package]] name = "uniffi_udl" -version = "0.25.2" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6817c15714acccd0d0459f99b524cabebfdd622376464a2c6466a6485bdb4b" dependencies = [ "anyhow", "textwrap", @@ -4027,8 +3936,9 @@ checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "weedle2" -version = "4.0.0" -source = "git+https://github.com/mozilla/uniffi-rs?rev=23711c8151bbb794369aa1f9d383db386792dff9#23711c8151bbb794369aa1f9d383db386792dff9" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" dependencies = [ "nom", ] @@ -4064,15 +3974,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index f841f07c9..125aac2a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,3 @@ codegen-units = 1 # Stripping the binary reduces the size by ~30%, but the stacktraces won't be usable anymore. # This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now # strip = true - -# Using git dependency temporarily to add support for immutable records in generated code -[patch.crates-io] -uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } -uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } -uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } -uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } -uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "23711c8151bbb794369aa1f9d383db386792dff9" } diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 1920fa991..295cdd38e 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -39,7 +39,7 @@ sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" -uniffi = { version = "=0.25.2", optional = true } +uniffi = { version = "=0.26.1", optional = true } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } diff --git a/crates/bitwarden-crypto/uniffi.toml b/crates/bitwarden-crypto/uniffi.toml index f5826906b..3cac32ecc 100644 --- a/crates/bitwarden-crypto/uniffi.toml +++ b/crates/bitwarden-crypto/uniffi.toml @@ -1,6 +1,7 @@ [bindings.kotlin] package_name = "com.bitwarden.crypto" generate_immutable_records = true +android = true [bindings.swift] ffi_module_name = "BitwardenCryptoFFI" diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index d29c311aa..7f26a47cf 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -25,7 +25,7 @@ schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" thiserror = ">=1.0.40, <2.0" -uniffi = { version = "=0.25.2", optional = true } +uniffi = { version = "=0.26.1", optional = true } [dev-dependencies] rand_chacha = "0.3.1" diff --git a/crates/bitwarden-generators/uniffi.toml b/crates/bitwarden-generators/uniffi.toml index 923dd5e17..75f929b1a 100644 --- a/crates/bitwarden-generators/uniffi.toml +++ b/crates/bitwarden-generators/uniffi.toml @@ -1,6 +1,7 @@ [bindings.kotlin] package_name = "com.bitwarden.generators" generate_immutable_records = true +android = true [bindings.swift] ffi_module_name = "BitwardenGeneratorsFFI" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 6dc940062..59db0daf7 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -19,7 +19,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ ], default-features = false } env_logger = "0.10.1" schemars = { version = ">=0.8, <0.9", optional = true } -uniffi = "=0.25.2" +uniffi = "=0.26.1" bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0", features = [ @@ -30,4 +30,4 @@ bitwarden-generators = { path = "../bitwarden-generators", version = "=0.1.0", f ] } [build-dependencies] -uniffi = { version = "=0.25.2", features = ["build"] } +uniffi = { version = "=0.26.1", features = ["build"] } diff --git a/crates/bitwarden-uniffi/uniffi.toml b/crates/bitwarden-uniffi/uniffi.toml index c9cb0899c..8abfa33fc 100644 --- a/crates/bitwarden-uniffi/uniffi.toml +++ b/crates/bitwarden-uniffi/uniffi.toml @@ -2,6 +2,7 @@ package_name = "com.bitwarden.sdk" cdylib_name = "bitwarden_uniffi" generate_immutable_records = true +android = true [bindings.swift] ffi_module_name = "BitwardenFFI" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 51c892ae1..1f666e21c 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -53,7 +53,7 @@ serde_repr = ">=0.1.12, <0.2" sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" thiserror = ">=1.0.40, <2.0" -uniffi = { version = "=0.25.2", optional = true, features = ["tokio"] } +uniffi = { version = "=0.26.1", optional = true, features = ["tokio"] } uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } zxcvbn = ">= 2.2.2, <3.0" diff --git a/crates/bitwarden/uniffi.toml b/crates/bitwarden/uniffi.toml index bc4a9d9ec..7a804ef1d 100644 --- a/crates/bitwarden/uniffi.toml +++ b/crates/bitwarden/uniffi.toml @@ -1,6 +1,7 @@ [bindings.kotlin] package_name = "com.bitwarden.core" generate_immutable_records = true +android = true [bindings.swift] ffi_module_name = "BitwardenCoreFFI" diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index cfbb5b554..e8f6f3f3d 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -10,4 +10,4 @@ name = "uniffi-bindgen" path = "uniffi-bindgen.rs" [dependencies] -uniffi = { version = "=0.25.2", features = ["cli"] } +uniffi = { version = "=0.26.1", features = ["cli"] } diff --git a/languages/kotlin/sdk/build.gradle b/languages/kotlin/sdk/build.gradle index a4ee06814..9b3ca3585 100644 --- a/languages/kotlin/sdk/build.gradle +++ b/languages/kotlin/sdk/build.gradle @@ -30,6 +30,10 @@ android { jvmTarget = '1.8' } + lint { + baseline = file("lint-baseline.xml") + } + publishing { singleVariant('release') { withSourcesJar() diff --git a/languages/kotlin/sdk/lint-baseline.xml b/languages/kotlin/sdk/lint-baseline.xml new file mode 100644 index 000000000..3ae6c45f5 --- /dev/null +++ b/languages/kotlin/sdk/lint-baseline.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + From 5457935ea13876244c62b6d4316336b6fb7e039a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 26 Jan 2024 16:11:16 +0100 Subject: [PATCH 228/378] Add publish python stub (#541) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add stub to be able to test `publish-python.yml` workflow. ## Code changes - **.github/workflows/publish-python.yml:** Add stub ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-python.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/publish-python.yml diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml new file mode 100644 index 000000000..bccde1aa2 --- /dev/null +++ b/.github/workflows/publish-python.yml @@ -0,0 +1,13 @@ +--- +name: Publish Python SDK + +on: + workflow_dispatch: + +jobs: + stub: + name: Stub + runs-on: ubuntu-22.04 + steps: + - name: Stub + run: echo "Stub" From 74f8281ca7d048b3eb1ddd0c5563c9bbbb29a136 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:22:31 +0100 Subject: [PATCH 229/378] [deps]: Update Rust crate serde_json to v1.0.113 (#545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [serde_json](https://togithub.com/serde-rs/json) | dependencies | patch | `1.0.111` -> `1.0.113` | --- ### Release Notes
serde-rs/json (serde_json) ### [`v1.0.113`](https://togithub.com/serde-rs/json/releases/tag/v1.0.113) [Compare Source](https://togithub.com/serde-rs/json/compare/v1.0.112...v1.0.113) - Add `swap_remove` and `shift_remove` methods on Map ([#​1109](https://togithub.com/serde-rs/json/issues/1109)) ### [`v1.0.112`](https://togithub.com/serde-rs/json/releases/tag/v1.0.112) [Compare Source](https://togithub.com/serde-rs/json/compare/v1.0.111...v1.0.112) - Improve formatting of "invalid type" error messages involving floats ([#​1107](https://togithub.com/serde-rs/json/issues/1107))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- crates/sdk-schemas/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fefd59fd..88c74cad6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2953,9 +2953,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa", "ryu", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index fd723d3e6..1684b4354 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -32,7 +32,7 @@ regex = { version = "1.10.2", features = [ "perf", ], default-features = false } serde = "^1.0.195" -serde_json = "^1.0.111" +serde_json = "^1.0.113" serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.56" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 05c52bffa..3e7282e7e 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -15,7 +15,7 @@ internal = [ anyhow = "1.0.79" itertools = "0.12.0" schemars = { version = "0.8.16", features = ["preserve_order"] } -serde_json = "1.0.111" +serde_json = "1.0.113" bitwarden = { path = "../bitwarden" } bitwarden-json = { path = "../bitwarden-json" } From d708f7f7f1ba1950498e39ceed7aabd5520e7b4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:49:40 +0100 Subject: [PATCH 230/378] [deps]: Update Rust crate serde to v1.0.196 (#544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [serde](https://serde.rs) ([source](https://togithub.com/serde-rs/serde)) | dependencies | patch | `^1.0.195` -> `^1.0.196` | --- ### Release Notes
serde-rs/serde (serde) ### [`v1.0.196`](https://togithub.com/serde-rs/serde/compare/v1.0.195...v1.0.196) [Compare Source](https://togithub.com/serde-rs/serde/compare/v1.0.195...v1.0.196)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bitwarden-wasm/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88c74cad6..7dc7828c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,18 +2922,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 9cbada205..bd2a064a1 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -12,7 +12,7 @@ console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.67" log = "0.4.20" -serde = { version = "1.0.195", features = ["derive"] } +serde = { version = "1.0.196", features = ["derive"] } wasm-bindgen = { version = "0.2.90", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.40" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 1684b4354..dd4e1627c 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -31,7 +31,7 @@ regex = { version = "1.10.2", features = [ "std", "perf", ], default-features = false } -serde = "^1.0.195" +serde = "^1.0.196" serde_json = "^1.0.113" serde_yaml = "0.9" supports-color = "2.1.0" From de4cd5d9f9dbd76fc1d1eac20c0f896db5898451 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:50:16 +0100 Subject: [PATCH 231/378] [deps]: Update Rust crate regex to 1.10.3 (#543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [regex](https://togithub.com/rust-lang/regex) | dependencies | patch | `1.10.2` -> `1.10.3` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index dd4e1627c..30163d00b 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -27,7 +27,7 @@ comfy-table = "^7.1.0" directories = "5.0.1" env_logger = "0.10.1" log = "0.4.20" -regex = { version = "1.10.2", features = [ +regex = { version = "1.10.3", features = [ "std", "perf", ], default-features = false } From 1cb98557c9617f537ae78a603ff5b50a2ba6ebb6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:22:31 +0100 Subject: [PATCH 232/378] [deps]: Update Rust crate env_logger to v0.11.1 (#547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [env_logger](https://togithub.com/rust-cli/env_logger) | dependencies | minor | `0.10.1` -> `0.11.1` | --- ### Release Notes
rust-cli/env_logger (env_logger) ### [`v0.11.1`](https://togithub.com/rust-cli/env_logger/blob/HEAD/CHANGELOG.md#0111---2024-01-27) [Compare Source](https://togithub.com/rust-cli/env_logger/compare/v0.11.0...v0.11.1) ##### Fixes - Allow styling with `Target::Pipe` ### [`v0.11.0`](https://togithub.com/rust-cli/env_logger/blob/HEAD/CHANGELOG.md#0110---2024-01-19) [Compare Source](https://togithub.com/rust-cli/env_logger/compare/v0.10.2...v0.11.0) ##### Breaking Change - Removed bespoke styling API - `env_logger::fmt::Formatter::style` - `env_logger::fmt::Formatter::default_styled_level` - `env_logger::fmt::Style` - `env_logger::fmt::Color` - `env_logger::fmt::StyledValue` - Removed `env_logger::filter` in favor of `env_filter` ##### Compatibility MSRV changed to 1.71 ##### Features - Automatically adapt ANSI escape codes in logged messages to the current terminal's capabilities - Add support for `NO_COLOR` and `CLICOLOR_FORCE`, see https://bixense.com/clicolors/ ##### Fixes - Print colors when `is_test(true)` - Allow styling with `Target::Pipe`
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 29 +++++++++++++++-------------- crates/bitwarden-c/Cargo.toml | 2 +- crates/bitwarden-napi/Cargo.toml | 2 +- crates/bitwarden-uniffi/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7dc7828c5..52bc0239b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1173,17 +1173,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" -version = "0.10.2" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "05e7cf40684ae96ade6232ed84582f40ce0a66efcd43a5117aef610534f8e0b8" dependencies = [ + "anstream", + "anstyle", + "env_filter", "humantime", - "is-terminal", "log", - "regex", - "termcolor", ] [[package]] @@ -3293,15 +3303,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "textwrap" version = "0.16.0" diff --git a/crates/bitwarden-c/Cargo.toml b/crates/bitwarden-c/Cargo.toml index 20f3f5229..c6f0ec7f3 100644 --- a/crates/bitwarden-c/Cargo.toml +++ b/crates/bitwarden-c/Cargo.toml @@ -14,4 +14,4 @@ tokio = { version = ">=1.28.2, <2.0", features = ["rt-multi-thread", "macros"] } bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [dependencies] -env_logger = ">=0.10.0, <0.11" +env_logger = ">=0.10.0, <0.12" diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 63eae2b8b..4b6ff4ed1 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -16,7 +16,7 @@ rust-version = "1.57" crate-type = ["cdylib", "rlib"] [dependencies] -env_logger = "0.10.1" +env_logger = "0.11.1" log = "0.4.20" napi = { version = "2", features = ["async"] } napi-derive = "2" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 59db0daf7..7f780558b 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -17,7 +17,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", ], default-features = false } -env_logger = "0.10.1" +env_logger = "0.11.1" schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.26.1" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 210a6b80a..cc07397cd 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["bitwarden", "password-manager", "cli"] [dependencies] clap = { version = "4.4.18", features = ["derive", "env"] } color-eyre = "0.6" -env_logger = "0.10.1" +env_logger = "0.11.1" inquire = "0.6.2" log = "0.4.20" tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 30163d00b..8d821f9d3 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -25,7 +25,7 @@ clap_complete = "4.4.9" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" -env_logger = "0.10.1" +env_logger = "0.11.1" log = "0.4.20" regex = { version = "1.10.3", features = [ "std", From 51ae8bf3acd412d693968d2800d9038d6bf45e67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 12:01:08 +0100 Subject: [PATCH 233/378] [deps]: Update Rust crate uuid to ^1.7.0 (#546) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [uuid](https://togithub.com/uuid-rs/uuid) | dependencies | patch | `^1.6.1` -> `^1.7.0` | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 8d821f9d3..1c04a6668 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -38,7 +38,7 @@ supports-color = "2.1.0" thiserror = "1.0.56" tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } toml = "0.8.8" -uuid = { version = "^1.6.1", features = ["serde"] } +uuid = { version = "^1.7.0", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } From 2a30f0fe2deafabea6bdfb6cf178dc0288a3e345 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 12:01:24 +0100 Subject: [PATCH 234/378] [deps]: Update @types/node to v18.19.10 (#542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.9` -> `18.19.10`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.9/18.19.10) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.9/18.19.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.9/18.19.10?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 4f2b52824..004be9f0e 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.9.tgz", - "integrity": "sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==", + "version": "18.19.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.10.tgz", + "integrity": "sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 7dacc63c4403d88fbc401674fcb3b83b49c4bded Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 13:17:04 +0100 Subject: [PATCH 235/378] [deps]: Lock file maintenance (#557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 36 +++++++++++------------ crates/bitwarden-napi/package-lock.json | 6 ++-- languages/js/sdk-client/package-lock.json | 6 ++-- package-lock.json | 18 ++++++------ 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52bc0239b..c4e1fe3c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1501,7 +1501,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1716,9 +1716,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1980,9 +1980,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.14.4" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "902495f6b80f53f8435aefbbd2241c9c675fa239cd7e5f8e28fb57f3b69ecd09" +checksum = "efbf98e1bcb85cc441bbf7cdfb11070d2537a100e2697d75397b2584c32492d1" dependencies = [ "bitflags 2.4.2", "ctor", @@ -2000,9 +2000,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.14.6" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61bec1ee990ae3e9a5f443484c65fb38e571a898437f0ad283ed69c82fc59c0" +checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514" dependencies = [ "cfg-if", "convert_case", @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2314f777bc9cde51705d991c44466cee4de4a3f41c6d3d019fcbbebb5cdd47c4" +checksum = "8ec514d65fce18a959be55e7f683ac89c6cb850fb59b09e25ab777fd5a4a8d9e" dependencies = [ "convert_case", "once_cell", @@ -2325,7 +2325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.7", - "indexmap 2.1.0", + "indexmap 2.2.1", "line-wrap", "quick-xml", "serde", @@ -2579,9 +2579,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3028,11 +3028,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.30" +version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1bf28c79a99f70ee1f1d83d10c875d2e70618417fda01ad1785e027579d9d38" +checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -3476,7 +3476,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_spanned", "toml_datetime", @@ -4118,9 +4118,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 6d1288fa9..a8995bc77 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.6.tgz", - "integrity": "sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==", + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", "dev": true, "peer": true, "dependencies": { diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 004be9f0e..d1192e6f5 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -202,9 +202,9 @@ } }, "node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { "node": "14 || >=16.14" diff --git a/package-lock.json b/package-lock.json index f7c429825..747d7d809 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,9 +19,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" @@ -346,9 +346,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.6.tgz", - "integrity": "sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==", + "version": "20.11.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", + "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", "dev": true, "peer": true, "dependencies": { @@ -1253,9 +1253,9 @@ } }, "node_modules/lru-cache": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", - "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { "node": "14 || >=16.14" From eed8d568283658e107085014a04f06a9357de5e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:32:17 -0500 Subject: [PATCH 236/378] [deps]: Update docker/setup-qemu-action action to v3 (#556) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-cli-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index 4605da5e5..dd70fe51d 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -44,7 +44,7 @@ jobs: ########## Set up Docker ########## - name: Set up QEMU emulators - uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0 + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 From 218a9c828beb7669f0c1ca50dcaa31e2da2531d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:36:04 -0500 Subject: [PATCH 237/378] [deps]: Update docker/setup-buildx-action action to v3 (#555) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-cli-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index dd70fe51d..9b1960a44 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -47,7 +47,7 @@ jobs: uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 ########## Login to Docker registries ########## - name: Login to Azure - Prod Subscription From f78a98f452031d295aa9c5e2ffb57f99c0dd312c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:38:39 -0500 Subject: [PATCH 238/378] [deps]: Update docker/build-push-action action to v5 (#554) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-cli-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index 9b1960a44..c0aa62664 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -104,7 +104,7 @@ jobs: fi - name: Build and push Docker image - uses: docker/build-push-action@1104d471370f9806843c095c1db02b5a90c5f8b6 # v3.3.1 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: context: . file: crates/bws/Dockerfile From 4aca392a5b61432d237f1e553b00d5dcc16cca9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:39:06 -0500 Subject: [PATCH 239/378] [deps]: Update actions/upload-artifact action to v4 (#553) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-python-wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index dace2d047..5dc5b8d23 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -109,14 +109,14 @@ jobs: working-directory: ${{ github.workspace }}/languages/python - name: Upload wheels - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-${{ matrix.settings.target }} path: ${{ github.workspace }}/target/wheels/bitwarden_sdk*.whl - name: Upload sdists if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} # we only need one sdist - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-sdist path: ${{ github.workspace }}/target/wheels/bitwarden_sdk-*.tar.gz From 26110b2afab42e08498ba3c775befbda78d03ba5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:41:56 -0500 Subject: [PATCH 240/378] [deps]: Update actions/delete-package-versions action to v5 (#552) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/delete-old-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index 50c3a8fef..b3be807a6 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -15,7 +15,7 @@ jobs: name: Cleanup Android SDK runs-on: ubuntu-22.04 steps: - - uses: actions/delete-package-versions@0d39a63126868f5eefaa47169615edd3c0f61e20 # v4.1.1 + - uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0 with: package-name: com.bitwarden.sdk-android package-type: maven From d3026a5972cb52163599bb1205ad2919858e28c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:42:16 -0500 Subject: [PATCH 241/378] [deps]: Update actions/cache action to v4 (#551) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/golang-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golang-release.yml b/.github/workflows/golang-release.yml index 1578dee57..10ec7675e 100644 --- a/.github/workflows/golang-release.yml +++ b/.github/workflows/golang-release.yml @@ -34,7 +34,7 @@ jobs: go-version: ${{ env.GO_VERSION }} - name: Cache dependencies - uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c # v3.3.3 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} From 3064ac547093aab08c18fef036e85c3b3bc032ba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:42:40 -0500 Subject: [PATCH 242/378] [deps]: Update gh minor (#549) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 6 +++--- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/build-java.yml | 2 +- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/generate_schemas.yml | 14 +++++++------- .github/workflows/publish-ruby.yml | 2 +- .github/workflows/rust-test.yml | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index ce08322be..e1aeea244 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -46,7 +46,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so @@ -102,7 +102,7 @@ jobs: run: ./build-schemas.sh - name: Publish - uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1 + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 with: arguments: sdk:publish build-root-directory: languages/kotlin diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 1e8ad2896..769c9bea3 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -99,7 +99,7 @@ jobs: run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip @@ -142,7 +142,7 @@ jobs: run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws - name: Upload artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip path: ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip @@ -177,7 +177,7 @@ jobs: sed -i.bak 's/\$NAME\$/Bitwarden Secrets Manager CLI/g' THIRDPARTY.html - name: Upload artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: THIRDPARTY.html path: ./crates/bws/THIRDPARTY.html diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 232efee9d..e56bd2282 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -71,7 +71,7 @@ jobs: working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: Bitwarden.Sdk.0.0.1.nupkg path: | diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 3c574d823..0ed8997ca 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -61,7 +61,7 @@ jobs: path: languages/java/src/main/resources/win32-x86-64 - name: Publish Maven - uses: gradle/gradle-build-action@982da8e78c05368c70dac0351bb82647a9e9a5d2 # v2.11.1 + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 with: arguments: publish build-root-directory: languages/java diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 40e6ffaef..c1088a220 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -84,7 +84,7 @@ jobs: run: ${{ matrix.settings.build }} - name: Upload artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: sdk-bitwarden-napi-${{ matrix.settings.target }} path: ${{ github.workspace }}/crates/bitwarden-napi/sdk-napi.*.node diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 7495457df..8529ab484 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -41,7 +41,7 @@ jobs: run: cargo build --target ${{ matrix.settings.target }} --release - name: Upload Artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: libbitwarden_c_files-${{ matrix.settings.target }} path: | diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index a18b4910a..99e13089c 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -37,48 +37,48 @@ jobs: run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: schemas.ts path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: schemas.cs path: ${{ github.workspace }}/languages/csharp/Bitwarden.Sdk/schemas.cs if-no-files-found: error - name: Upload python schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 291834022..81aedcc22 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d # v1.169.0 + uses: ruby/setup-ruby@bd03e04863f52d169e18a2b190e8fa6b84938215 # v1.170.0 with: ruby-version: 3.2 diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 8dfcf1783..93a2ddecf 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -73,7 +73,7 @@ jobs: run: cargo llvm-cov --all-features --lcov --output-path lcov.info --ignore-filename-regex "crates/bitwarden-api-" - name: Upload to codecov.io - uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 + uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 878cd4a4d3a27c05e3306cf23d5a37920d313400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Wed, 31 Jan 2024 13:49:07 +0100 Subject: [PATCH 243/378] Implement password update support (#566) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Support re-encrypting the user key with the new password. --- crates/bitwarden-uniffi/src/crypto.rs | 15 ++- crates/bitwarden/src/mobile/client_crypto.rs | 11 +- crates/bitwarden/src/mobile/crypto.rs | 120 +++++++++++++++++++ languages/kotlin/doc.md | 12 ++ 4 files changed, 156 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 92afcbb87..2d847b33d 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use bitwarden::mobile::crypto::{ - DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, + DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse, }; use bitwarden_crypto::EncString; @@ -51,6 +51,19 @@ impl ClientCrypto { .await?) } + /// Update the user's password, which will re-encrypt the user's encryption key with the new + /// password. This returns the new encrypted user key and the new password hash. + pub async fn update_password(&self, new_password: String) -> Result { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .update_password(new_password) + .await?) + } + /// Generates a PIN protected user key from the provided PIN. The result can be stored and later /// used to initialize another client instance by using the PIN and the PIN key with /// `initialize_user_crypto`. diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index 6f8887002..f6ea3346b 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -7,7 +7,8 @@ use crate::{ error::Result, mobile::crypto::{ derive_pin_key, derive_pin_user_key, get_user_encryption_key, initialize_org_crypto, - initialize_user_crypto, DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, + initialize_user_crypto, update_password, DerivePinKeyResponse, InitOrgCryptoRequest, + InitUserCryptoRequest, UpdatePasswordResponse, }, }; @@ -31,6 +32,14 @@ impl<'a> ClientCrypto<'a> { get_user_encryption_key(self.client).await } + #[cfg(feature = "internal")] + pub async fn update_password( + &mut self, + new_password: String, + ) -> Result { + update_password(self.client, new_password) + } + #[cfg(feature = "internal")] pub async fn derive_pin_key(&mut self, pin: String) -> Result { derive_pin_key(self.client, pin) diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index bd71af2be..9b431b4b4 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -125,6 +125,53 @@ pub async fn get_user_encryption_key(client: &mut Client) -> Result { Ok(user_key.to_base64()) } +#[cfg(feature = "internal")] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct UpdatePasswordResponse { + /// Hash of the new password + password_hash: String, + /// User key, encrypted with the new password + new_key: EncString, +} + +pub fn update_password( + client: &mut Client, + new_password: String, +) -> Result { + let user_key = client + .get_encryption_settings()? + .get_key(&None) + .ok_or(Error::VaultLocked)?; + + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + // Derive a new master key from password + let new_master_key = match login_method { + LoginMethod::User( + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. }, + ) => MasterKey::derive(new_password.as_bytes(), email.as_bytes(), kdf)?, + _ => return Err(Error::NotAuthenticated), + }; + + let new_key = new_master_key.encrypt_user_key(user_key)?; + + let password_hash = new_master_key.derive_master_key_hash( + new_password.as_bytes(), + bitwarden_crypto::HashPurpose::ServerAuthorization, + )?; + + Ok(UpdatePasswordResponse { + password_hash, + new_key, + }) +} + #[cfg(feature = "internal")] #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -194,6 +241,79 @@ mod tests { use super::*; use crate::{client::Kdf, Client}; + #[tokio::test] + async fn test_update_password() { + let mut client = Client::new(None); + + let priv_key = "2.kmLY8NJVuiKBFJtNd/ZFpA==|qOodlRXER+9ogCe3yOibRHmUcSNvjSKhdDuztLlucs10jLiNoVVVAc+9KfNErLSpx5wmUF1hBOJM8zwVPjgQTrmnNf/wuDpwiaCxNYb/0v4FygPy7ccAHK94xP1lfqq7U9+tv+/yiZSwgcT+xF0wFpoxQeNdNRFzPTuD9o4134n8bzacD9DV/WjcrXfRjbBCzzuUGj1e78+A7BWN7/5IWLz87KWk8G7O/W4+8PtEzlwkru6Wd1xO19GYU18oArCWCNoegSmcGn7w7NDEXlwD403oY8Oa7ylnbqGE28PVJx+HLPNIdSC6YKXeIOMnVs7Mctd/wXC93zGxAWD6ooTCzHSPVV50zKJmWIG2cVVUS7j35H3rGDtUHLI+ASXMEux9REZB8CdVOZMzp2wYeiOpggebJy6MKOZqPT1R3X0fqF2dHtRFPXrNsVr1Qt6bS9qTyO4ag1/BCvXF3P1uJEsI812BFAne3cYHy5bIOxuozPfipJrTb5WH35bxhElqwT3y/o/6JWOGg3HLDun31YmiZ2HScAsUAcEkA4hhoTNnqy4O2s3yVbCcR7jF7NLsbQc0MDTbnjxTdI4VnqUIn8s2c9hIJy/j80pmO9Bjxp+LQ9a2hUkfHgFhgHxZUVaeGVth8zG2kkgGdrp5VHhxMVFfvB26Ka6q6qE/UcS2lONSv+4T8niVRJz57qwctj8MNOkA3PTEfe/DP/LKMefke31YfT0xogHsLhDkx+mS8FCc01HReTjKLktk/Jh9mXwC5oKwueWWwlxI935ecn+3I2kAuOfMsgPLkoEBlwgiREC1pM7VVX1x8WmzIQVQTHd4iwnX96QewYckGRfNYWz/zwvWnjWlfcg8kRSe+68EHOGeRtC5r27fWLqRc0HNcjwpgHkI/b6czerCe8+07TWql4keJxJxhBYj3iOH7r9ZS8ck51XnOb8tGL1isimAJXodYGzakwktqHAD7MZhS+P02O+6jrg7d+yPC2ZCuS/3TOplYOCHQIhnZtR87PXTUwr83zfOwAwCyv6KP84JUQ45+DItrXLap7nOVZKQ5QxYIlbThAO6eima6Zu5XHfqGPMNWv0bLf5+vAjIa5np5DJrSwz9no/hj6CUh0iyI+SJq4RGI60lKtypMvF6MR3nHLEHOycRUQbZIyTHWl4QQLdHzuwN9lv10ouTEvNr6sFflAX2yb6w3hlCo7oBytH3rJekjb3IIOzBpeTPIejxzVlh0N9OT5MZdh4sNKYHUoWJ8mnfjdM+L4j5Q2Kgk/XiGDgEebkUxiEOQUdVpePF5uSCE+TPav/9FIRGXGiFn6NJMaU7aBsDTFBLloffFLYDpd8/bTwoSvifkj7buwLYM+h/qcnfdy5FWau1cKav+Blq/ZC0qBpo658RTC8ZtseAFDgXoQZuksM10hpP9bzD04Bx30xTGX81QbaSTNwSEEVrOtIhbDrj9OI43KH4O6zLzK+t30QxAv5zjk10RZ4+5SAdYndIlld9Y62opCfPDzRy3ubdve4ZEchpIKWTQvIxq3T5ogOhGaWBVYnkMtM2GVqvWV//46gET5SH/MdcwhACUcZ9kCpMnWH9CyyUwYvTT3UlNyV+DlS27LMPvaw7tx7qa+GfNCoCBd8S4esZpQYK/WReiS8=|pc7qpD42wxyXemdNPuwxbh8iIaryrBPu8f/DGwYdHTw="; + + let kdf = Kdf::PBKDF2 { + iterations: 100_000.try_into().unwrap(), + }; + + initialize_user_crypto( + &mut client, + InitUserCryptoRequest { + kdf_params: kdf.clone(), + email: "test@bitwarden.com".into(), + private_key: priv_key.to_owned(), + method: InitUserCryptoMethod::Password { + password: "asdfasdfasdf".into(), + user_key: "2.u2HDQ/nH2J7f5tYHctZx6Q==|NnUKODz8TPycWJA5svexe1wJIz2VexvLbZh2RDfhj5VI3wP8ZkR0Vicvdv7oJRyLI1GyaZDBCf9CTBunRTYUk39DbZl42Rb+Xmzds02EQhc=|rwuo5wgqvTJf3rgwOUfabUyzqhguMYb3sGBjOYqjevc=".into(), + }, + }, + ) + .await + .unwrap(); + + let new_password_response = update_password(&mut client, "123412341234".into()).unwrap(); + + let mut client2 = Client::new(None); + + initialize_user_crypto( + &mut client2, + InitUserCryptoRequest { + kdf_params: kdf.clone(), + email: "test@bitwarden.com".into(), + private_key: priv_key.to_owned(), + method: InitUserCryptoMethod::Password { + password: "123412341234".into(), + user_key: new_password_response.new_key.to_string(), + }, + }, + ) + .await + .unwrap(); + + let new_hash = client2 + .kdf() + .hash_password( + "test@bitwarden.com".into(), + "123412341234".into(), + kdf.clone(), + bitwarden_crypto::HashPurpose::ServerAuthorization, + ) + .await + .unwrap(); + + assert_eq!(new_hash, new_password_response.password_hash); + + assert_eq!( + client + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64(), + client2 + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64() + ); + } + #[tokio::test] async fn test_initialize_user_crypto_pin() { let mut client = Client::new(None); diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index fd98e463e..f85222738 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -311,6 +311,18 @@ as it can be used to decrypt all of the user's data **Output**: std::result::Result +### `update_password` + +Update the user's password, which will re-encrypt the user's encryption key with the new +password. This returns the new encrypted user key and the new password hash. + +**Arguments**: + +- self: +- new_password: String + +**Output**: std::result::Result + ### `derive_pin_key` Generates a PIN protected user key from the provided PIN. The result can be stored and later used to From 8b468ec34a770f8857408382b8a71624a9176ad1 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 31 Jan 2024 14:20:04 +0100 Subject: [PATCH 244/378] Fix device keys incorrectly being treated as strings (#564) Device keys are generated from random u8 vectors. We incorrectly attempted to parse these as strings when decrypting them in the last trust device step. Added a complete test which confirms the whole device approval process. --- Cargo.lock | 1 + crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/auth/auth_request.rs | 86 ++++++++++++++++++++--- 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4e1fe3c2..8ebf52136 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,6 +373,7 @@ dependencies = [ "uniffi", "uuid", "wiremock", + "zeroize", "zxcvbn", ] diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 1f666e21c..b52e2f8f3 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -78,3 +78,4 @@ reqwest = { version = "*", features = [ rand_chacha = "0.3.1" tokio = { version = "1.35.1", features = ["rt", "macros"] } wiremock = "0.5.22" +zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } diff --git a/crates/bitwarden/src/auth/auth_request.rs b/crates/bitwarden/src/auth/auth_request.rs index facdc8f82..98fe4996a 100644 --- a/crates/bitwarden/src/auth/auth_request.rs +++ b/crates/bitwarden/src/auth/auth_request.rs @@ -58,9 +58,9 @@ pub(crate) fn auth_request_decrypt_user_key( user_key: AsymmetricEncString, ) -> Result { let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?; - let key: String = user_key.decrypt_with_key(&key)?; + let mut key: Vec = user_key.decrypt_with_key(&key)?; - Ok(key.parse()?) + Ok(SymmetricCryptoKey::try_from(key.as_mut_slice())?) } /// Approve an auth request. @@ -83,20 +83,25 @@ pub(crate) fn approve_auth_request( #[test] fn test_auth_request() { + use zeroize::Zeroizing; + let request = new_auth_request("test@bitwarden.com").unwrap(); - let secret = - "w2LO+nwV4oxwswVYCxlOfRUseXfvU03VzvKQHrqeklPgiMZrspUe6sOBToCnDn9Ay0tuCBn8ykVVRb7PWhub2Q=="; + let secret: &[u8] = &[ + 111, 32, 97, 169, 4, 241, 174, 74, 239, 206, 113, 86, 174, 68, 216, 238, 52, 85, 156, 27, + 134, 149, 54, 55, 91, 147, 45, 130, 131, 237, 51, 31, 191, 106, 155, 14, 160, 82, 47, 40, + 96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53, 248, 43, 255, + 67, 35, 61, 245, 93, + ]; let private_key = AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap()).unwrap(); - let encrypted = - AsymmetricEncString::encrypt_rsa2048_oaep_sha1(secret.as_bytes(), &private_key).unwrap(); + let encrypted = AsymmetricEncString::encrypt_rsa2048_oaep_sha1(secret, &private_key).unwrap(); let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap(); - assert_eq!(decrypted.to_base64(), secret); + assert_eq!(decrypted.to_vec(), Zeroizing::new(secret.to_owned())); } #[cfg(test)] @@ -106,7 +111,10 @@ mod tests { use bitwarden_crypto::Kdf; use super::*; - use crate::client::{LoginMethod, UserLoginMethod}; + use crate::{ + client::{LoginMethod, UserLoginMethod}, + mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, + }; #[test] fn test_approve() { @@ -134,4 +142,66 @@ mod tests { approve_auth_request(&mut client, public_key.to_owned()).unwrap(); } + + #[tokio::test] + async fn test_device_login() { + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }; + let email = "test@bitwarden.com"; + + let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); + let private_key = "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4="; + + // Initialize an existing client which is unlocked + let mut existing_device = Client::new(None); + existing_device.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "123".to_owned(), + email: email.to_owned(), + kdf: kdf.clone(), + })); + + existing_device + .initialize_user_crypto("asdfasdfasdf", user_key, private_key.parse().unwrap()) + .unwrap(); + + // Initialize a new device which will request to be logged in + let mut new_device = Client::new(None); + + // Initialize an auth request, and approve it on the existing device + let auth_req = new_auth_request(email).unwrap(); + let approved_req = approve_auth_request(&mut existing_device, auth_req.public_key).unwrap(); + + // Unlock the vault using the approved request + new_device + .crypto() + .initialize_user_crypto(InitUserCryptoRequest { + kdf_params: kdf, + email: email.to_owned(), + private_key: private_key.to_owned(), + method: InitUserCryptoMethod::AuthRequest { + request_private_key: auth_req.private_key, + protected_user_key: approved_req, + }, + }) + .await + .unwrap(); + + // We can validate that the vault is unlocked correctly by confirming the user key is the + // same + assert_eq!( + existing_device + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64(), + new_device + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_base64() + ); + } } From 4a2089cd9b885f51025d255f6afcc78ebf03b13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Wed, 31 Jan 2024 16:31:30 +0100 Subject: [PATCH 245/378] Add workflow linter (#567) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/workflow-linter.yml:** Add workflow linter ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/workflow-linter.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/workflow-linter.yml diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml new file mode 100644 index 000000000..24f10f1e4 --- /dev/null +++ b/.github/workflows/workflow-linter.yml @@ -0,0 +1,12 @@ +--- +name: Workflow linter + +on: + pull_request: + paths: + - .github/workflows/** + +jobs: + call-workflow: + name: Lint + uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main From 8c6b21562bc5bb5b862a0116f74d375265382ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Wed, 31 Jan 2024 16:33:18 +0100 Subject: [PATCH 246/378] [DEVOPS-1655] Build publish workflow for python sdk (#558) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Create publish workflow for Python SDK to publish it to pypi. ## Code changes - **.github/workflows/publish-python.yml:** Add steps to publish python SDK to pypi ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: MtnBurrit0 <77340197+mimartin12@users.noreply.github.com> --- .github/workflows/publish-python.yml | 94 ++++++++++++++++++++++++++-- .github/workflows/version-bump.yml | 8 +++ 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-python.yml b/.github/workflows/publish-python.yml index bccde1aa2..780195161 100644 --- a/.github/workflows/publish-python.yml +++ b/.github/workflows/publish-python.yml @@ -1,13 +1,99 @@ --- name: Publish Python SDK +run-name: Publish Python SDK ${{ inputs.release_type }} on: workflow_dispatch: + inputs: + release_type: + description: "Release Options" + required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + +defaults: + run: + shell: bash jobs: - stub: - name: Stub + setup: + name: Setup runs-on: ubuntu-22.04 steps: - - name: Stub - run: echo "Stub" + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Branch check + if: ${{ github.event.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 + + publish: + name: Publish + runs-on: ubuntu-22.04 + needs: setup + steps: + - name: Install Python + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + with: + python-version: "3.9" + + - name: Install twine + run: pip install twine + + - name: Download artifacts + uses: dawidd6/action-download-artifact@e7466d1a7587ed14867642c2ca74b5bcc1e19a2d # v3.0.0 + with: + workflow: build-python-wheels.yml + path: ${{ github.workspace }}/target/wheels/dist + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + name: bitwarden_sdk(.*) + name_is_regexp: true + + - name: Move files + working-directory: ${{ github.workspace }}/target/wheels/dist + run: | + find . -maxdepth 2 -type f -print0 | xargs -0 mv -t . + rm -rf */ + + - name: Login to Azure + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve pypi api token + id: retrieve-secret + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: "bitwarden-ci" + secrets: "pypi-api-token, + pypi-test-api-token" + + - name: Check + working-directory: ${{ github.workspace }}/target/wheels + run: twine check dist/* + + - name: Publish + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + working-directory: ${{ github.workspace }}/target/wheels + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ steps.retrieve-secret.outputs.pypi-api-token }} + run: twine upload --repository pypi dist/* + + - name: Dry Run - Publish + if: ${{ github.event.inputs.release_type == 'Dry Run' }} + working-directory: ${{ github.workspace }}/target/wheels + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ steps.retrieve-secret.outputs.pypi-test-api-token }} + run: twine upload --repository testpypi dist/* diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index c3055f097..e40f68a8e 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -18,6 +18,7 @@ on: - bitwarden-json - cli - napi + - python-sdk version_number: description: "New version (example: '2024.1.0')" required: true @@ -142,6 +143,13 @@ jobs: if: ${{ inputs.project == 'bitwarden-json' }} run: cargo-set-version set-version -p bitwarden-json ${{ inputs.version_number }} + ### python + - name: Bump python-sdk Version + if: ${{ inputs.project == 'python-sdk' }} + run: | + sed -i 's/version = "[0-9]\.[0-9]\.[0-9]"/version = "${{ inputs.version_number }}"/' ./languages/python/pyproject.toml + sed -i 's/__version__ = "[0-9]\.[0-9]\.[0-9]"/__version__ = "${{ inputs.version_number }}"/' ./languages/python/bitwarden_sdk/__init__.py + ############################ # VERSION BUMP SECTION END # ############################ From 872a05b7ba7c9ce267b64dc91b2ec53c4e4e7068 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:51:16 -0800 Subject: [PATCH 247/378] Update Python README (#563) ## Type of change Fix errors in README and update the Python package name in preparation for publishing to PyPI. - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ## Before you submit - Please add **unit tests** where it makes sense to do so --- languages/python/README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/languages/python/README.md b/languages/python/README.md index e77e7a8eb..f41fd8a12 100644 --- a/languages/python/README.md +++ b/languages/python/README.md @@ -2,7 +2,7 @@ ## Requirements - Python 3 -- `maturin` (install with `pip install maturin[patchelf]`) +- `maturin` (install with `pip install maturin`) - `npm` ## Build @@ -15,12 +15,15 @@ cd languages/python/ maturin develop ``` -You can now import `BitwardenClient` in your Python code. +You can now import `BitwardenClient` in your Python code with: +```python +from bitwarden_sdk import BitwardenClient +``` # Use without building locally ```bash -pip install BitwardenClient +pip install bitwarden-sdk ``` # Run From 2ac95f17ec1793fc5319d3892e5ab4b0070bc173 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 1 Feb 2024 16:31:13 +0100 Subject: [PATCH 248/378] Implement alternative login with device flow (#568) When approving from other devices we need to support the master key flow. Also implements login with device for the CLI as a testing tool. --- .../bitwarden-crypto/src/keys/master_key.rs | 4 + .../api/request/auth_request_token_request.rs | 59 ++++++++ crates/bitwarden/src/auth/api/request/mod.rs | 5 + .../api/request/password_token_request.rs | 14 +- crates/bitwarden/src/auth/auth_request.rs | 67 ++++++++- crates/bitwarden/src/auth/client_auth.rs | 21 +++ .../bitwarden/src/auth/login/auth_request.rs | 131 ++++++++++++++++++ crates/bitwarden/src/auth/login/mod.rs | 7 + crates/bitwarden/src/auth/login/password.rs | 16 ++- crates/bitwarden/src/auth/mod.rs | 4 +- crates/bitwarden/src/client/client.rs | 33 +++-- crates/bitwarden/src/mobile/crypto.rs | 35 ++++- crates/bw/src/auth/login.rs | 23 +++ crates/bw/src/auth/mod.rs | 2 +- crates/bw/src/main.rs | 11 ++ languages/kotlin/doc.md | 4 +- 16 files changed, 405 insertions(+), 31 deletions(-) create mode 100644 crates/bitwarden/src/auth/api/request/auth_request_token_request.rs create mode 100644 crates/bitwarden/src/auth/login/auth_request.rs diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 920f103e4..0a435ed88 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -39,6 +39,10 @@ pub enum HashPurpose { pub struct MasterKey(SymmetricCryptoKey); impl MasterKey { + pub fn new(key: SymmetricCryptoKey) -> MasterKey { + Self(key) + } + /// Derives a users master key from their password, email and KDF. pub fn derive(password: &[u8], email: &[u8], kdf: &Kdf) -> Result { derive_key(password, email, kdf).map(Self) diff --git a/crates/bitwarden/src/auth/api/request/auth_request_token_request.rs b/crates/bitwarden/src/auth/api/request/auth_request_token_request.rs new file mode 100644 index 000000000..cf5ae7ee4 --- /dev/null +++ b/crates/bitwarden/src/auth/api/request/auth_request_token_request.rs @@ -0,0 +1,59 @@ +use log::debug; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::{ + auth::api::response::IdentityTokenResponse, + client::{client_settings::DeviceType, ApiConfigurations}, + error::Result, +}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct AuthRequestTokenRequest { + scope: String, + client_id: String, + #[serde(rename = "deviceType")] + device_type: u8, + #[serde(rename = "deviceIdentifier")] + device_identifier: String, + #[serde(rename = "deviceName")] + device_name: String, + grant_type: String, + #[serde(rename = "username")] + email: String, + #[serde(rename = "authRequest")] + auth_request_id: Uuid, + #[serde(rename = "password")] + access_code: String, +} + +impl AuthRequestTokenRequest { + pub fn new( + email: &str, + auth_request_id: &Uuid, + access_code: &str, + device_type: DeviceType, + device_identifier: &str, + ) -> Self { + let obj = Self { + scope: "api offline_access".to_string(), + client_id: "web".to_string(), + device_type: device_type as u8, + device_identifier: device_identifier.to_string(), + device_name: "chrome".to_string(), + grant_type: "password".to_string(), + email: email.to_string(), + auth_request_id: *auth_request_id, + access_code: access_code.to_string(), + }; + debug!("initializing {:?}", obj); + obj + } + + pub(crate) async fn send( + &self, + configurations: &ApiConfigurations, + ) -> Result { + super::send_identity_connect_request(configurations, Some(&self.email), &self).await + } +} diff --git a/crates/bitwarden/src/auth/api/request/mod.rs b/crates/bitwarden/src/auth/api/request/mod.rs index 67796f2f3..2b5bde225 100644 --- a/crates/bitwarden/src/auth/api/request/mod.rs +++ b/crates/bitwarden/src/auth/api/request/mod.rs @@ -15,6 +15,11 @@ pub(crate) use password_token_request::*; #[cfg(feature = "internal")] pub(crate) use renew_token_request::*; +#[cfg(feature = "mobile")] +mod auth_request_token_request; +#[cfg(feature = "mobile")] +pub(crate) use auth_request_token_request::*; + use crate::{ auth::api::response::{parse_identity_response, IdentityTokenResponse}, client::ApiConfigurations, diff --git a/crates/bitwarden/src/auth/api/request/password_token_request.rs b/crates/bitwarden/src/auth/api/request/password_token_request.rs index fd016d898..2f6414bcd 100644 --- a/crates/bitwarden/src/auth/api/request/password_token_request.rs +++ b/crates/bitwarden/src/auth/api/request/password_token_request.rs @@ -6,7 +6,7 @@ use crate::{ api::response::IdentityTokenResponse, login::{TwoFactorProvider, TwoFactorRequest}, }, - client::ApiConfigurations, + client::{client_settings::DeviceType, ApiConfigurations}, error::Result, }; @@ -35,13 +35,19 @@ pub struct PasswordTokenRequest { } impl PasswordTokenRequest { - pub fn new(email: &str, password_hash: &String, two_factor: &Option) -> Self { + pub fn new( + email: &str, + password_hash: &str, + device_type: DeviceType, + device_identifier: &str, + two_factor: &Option, + ) -> Self { let tf = two_factor.as_ref(); let obj = Self { scope: "api offline_access".to_string(), client_id: "web".to_string(), - device_type: 10, - device_identifier: "b86dd6ab-4265-4ddf-a7f1-eb28d5677f33".to_string(), + device_type: device_type as u8, + device_identifier: device_identifier.to_string(), device_name: "firefox".to_string(), grant_type: "password".to_string(), master_password_hash: password_hash.to_string(), diff --git a/crates/bitwarden/src/auth/auth_request.rs b/crates/bitwarden/src/auth/auth_request.rs index 98fe4996a..18c71afba 100644 --- a/crates/bitwarden/src/auth/auth_request.rs +++ b/crates/bitwarden/src/auth/auth_request.rs @@ -3,7 +3,7 @@ use bitwarden_crypto::{ fingerprint, AsymmetricCryptoKey, AsymmetricEncString, AsymmetricPublicCryptoKey, }; #[cfg(feature = "mobile")] -use bitwarden_crypto::{KeyDecryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; use bitwarden_generators::{password, PasswordGeneratorRequest}; use crate::{error::Error, Client}; @@ -63,6 +63,22 @@ pub(crate) fn auth_request_decrypt_user_key( Ok(SymmetricCryptoKey::try_from(key.as_mut_slice())?) } +/// Decrypt the user key using the private key generated previously. +#[cfg(feature = "mobile")] +pub(crate) fn auth_request_decrypt_master_key( + private_key: String, + master_key: AsymmetricEncString, + user_key: EncString, +) -> Result { + use bitwarden_crypto::MasterKey; + + let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?; + let mut master_key: Vec = master_key.decrypt_with_key(&key)?; + let master_key = MasterKey::new(SymmetricCryptoKey::try_from(master_key.as_mut_slice())?); + + Ok(master_key.decrypt_user_key(user_key)?) +} + /// Approve an auth request. /// /// Encrypts the user key with a public key. @@ -113,14 +129,14 @@ mod tests { use super::*; use crate::{ client::{LoginMethod, UserLoginMethod}, - mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, + mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, }; #[test] fn test_approve() { let mut client = Client::new(None); client.set_login_method(LoginMethod::User(UserLoginMethod::Username { - client_id: "123".to_owned(), + client_id: "7b821276-e27c-400b-9853-606393c87f18".to_owned(), email: "test@bitwarden.com".to_owned(), kdf: Kdf::PBKDF2 { iterations: NonZeroU32::new(600_000).unwrap(), @@ -133,16 +149,53 @@ mod tests { .initialize_user_crypto("asdfasdfasdf", user_key, private_key) .unwrap(); - let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnRtpYLp9QLaEUkdPkWZX6TrMUKFoSaFamBKDL0NlS6xwtETTqYIxRVsvnHii3Dhz+fh3aHQVyBa1rBXogeH3MLERzNADwZhpWtBT9wKCXY5o0fIWYdZV/Nf0Y+0ZoKdImrGPLPmyHGfCqrvrK7g09q8+3kXUlkdAImlQqc5TiYwiHBfUQVTBq/Ae7a0FEpajx1NUM4h3edpCYxbvnpSTuzMgbmbUUS4gdCaheA2ibYxy/zkLzsaLygoibMyGNl9Y8J5n7dDrVXpUKZTihVfXwHfEZwtKNunWsmmt8rEJWVpguUDEDVSUogoxQcNaCi7KHn9ioSip76hg1jLpypO3WwIDAQAB"; + let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyLRDUwXB4BfQ507D4meFPmwn5zwy3IqTPJO4plrrhnclWahXa240BzyFW9gHgYu+Jrgms5xBfRTBMcEsqqNm7+JpB6C1B6yvnik0DpJgWQw1rwvy4SUYidpR/AWbQi47n/hvnmzI/sQxGddVfvWu1iTKOlf5blbKYAXnUE5DZBGnrWfacNXwRRdtP06tFB0LwDgw+91CeLSJ9py6dm1qX5JIxoO8StJOQl65goLCdrTWlox+0Jh4xFUfCkb+s3px+OhSCzJbvG/hlrSRcUz5GnwlCEyF3v5lfUtV96MJD+78d8pmH6CfFAp2wxKRAbGdk+JccJYO6y6oIXd3Fm7twIDAQAB"; // Verify fingerprint let pbkey = STANDARD.decode(public_key).unwrap(); let fingerprint = fingerprint("test@bitwarden.com", &pbkey).unwrap(); - assert_eq!(fingerprint, "spill-applaud-sweep-habitable-shrunk"); + assert_eq!(fingerprint, "childless-unfair-prowler-dropbox-designate"); approve_auth_request(&mut client, public_key.to_owned()).unwrap(); } + #[tokio::test] + async fn test_decrypt_user_key() { + let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ="; + + let enc_user_key = "4.dxbd5OMwi/Avy7DQxvLV+Z7kDJgHBtg/jAbgYNO7QU0Zii4rLFNco2lS5aS9z42LTZHc2p5HYwn2ZwkZNfHsQ6//d5q40MDgGYJMKBXOZP62ZHhct1XsvYBmtcUtIOm5j2HSjt2pjEuGAc1LbyGIWRJJQ3Lp1ULbL2m71I+P23GF36JyOM8SUWvpvxE/3+qqVhRFPG2VqMCYa2kLLxwVfUmpV+KKjX1TXsrq6pfJIwHNwHw4h7MSfD8xTy2bx4MiBt638Z9Vt1pGsSQkh9RgPvCbnhuCpZQloUgJ8ByLVEcrlKx3yaaxiQXvte+ZhuOI7rGdjmoVoOzisooje4JgYw==".parse().unwrap(); + let dec = auth_request_decrypt_user_key(private_key.to_owned(), enc_user_key).unwrap(); + + assert_eq!( + dec.to_vec().as_ref(), + vec![ + 201, 37, 234, 213, 21, 75, 40, 70, 149, 213, 234, 16, 19, 251, 162, 245, 161, 74, + 34, 245, 211, 151, 211, 192, 95, 10, 117, 50, 88, 223, 23, 157 + ] + ); + } + + #[tokio::test] + async fn test_decrypt_master_key() { + let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ="; + + let enc_master_key = "4.dxbd5OMwi/Avy7DQxvLV+Z7kDJgHBtg/jAbgYNO7QU0Zii4rLFNco2lS5aS9z42LTZHc2p5HYwn2ZwkZNfHsQ6//d5q40MDgGYJMKBXOZP62ZHhct1XsvYBmtcUtIOm5j2HSjt2pjEuGAc1LbyGIWRJJQ3Lp1ULbL2m71I+P23GF36JyOM8SUWvpvxE/3+qqVhRFPG2VqMCYa2kLLxwVfUmpV+KKjX1TXsrq6pfJIwHNwHw4h7MSfD8xTy2bx4MiBt638Z9Vt1pGsSQkh9RgPvCbnhuCpZQloUgJ8ByLVEcrlKx3yaaxiQXvte+ZhuOI7rGdjmoVoOzisooje4JgYw==".parse().unwrap(); + let enc_user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); + let dec = + auth_request_decrypt_master_key(private_key.to_owned(), enc_master_key, enc_user_key) + .unwrap(); + + assert_eq!( + dec.to_vec().as_ref(), + vec![ + 109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216, + 212, 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91, + 215, 21, 128, 91, 226, 222, 165, 67, 251, 34, 83, 81, 77, 147, 225, 76, 13, 41, + 102, 45, 183, 218, 106, 89, 254, 208, 251, 101, 130, 10, + ] + ); + } + #[tokio::test] async fn test_device_login() { let kdf = Kdf::PBKDF2 { @@ -181,7 +234,9 @@ mod tests { private_key: private_key.to_owned(), method: InitUserCryptoMethod::AuthRequest { request_private_key: auth_req.private_key, - protected_user_key: approved_req, + method: AuthRequestMethod::UserKey { + protected_user_key: approved_req, + }, }, }) .await diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index aaa387741..0ae2f6f33 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,6 +1,8 @@ #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, DeviceKey, TrustDeviceResponse}; +#[cfg(feature = "mobile")] +use crate::auth::login::NewAuthRequestResponse; #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; use crate::{auth::renew::renew_token, error::Result, Client}; @@ -116,6 +118,25 @@ impl<'a> ClientAuth<'a> { } } +#[cfg(feature = "mobile")] +impl<'a> ClientAuth<'a> { + pub async fn login_device( + &mut self, + email: String, + device_identifier: String, + ) -> Result { + use crate::auth::login::send_new_auth_request; + + send_new_auth_request(self.client, email, device_identifier).await + } + + pub async fn login_device_complete(&mut self, auth_req: NewAuthRequestResponse) -> Result<()> { + use crate::auth::login::complete_auth_request; + + complete_auth_request(self.client, auth_req).await + } +} + #[cfg(feature = "internal")] fn trust_device(client: &Client) -> Result { let enc = client.get_encryption_settings()?; diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs new file mode 100644 index 000000000..30db06124 --- /dev/null +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -0,0 +1,131 @@ +use std::num::NonZeroU32; + +use bitwarden_api_api::{ + apis::auth_requests_api::{auth_requests_id_response_get, auth_requests_post}, + models::{AuthRequestCreateRequestModel, AuthRequestType}, +}; +use bitwarden_crypto::Kdf; +use uuid::Uuid; + +use crate::{ + auth::{ + api::{request::AuthRequestTokenRequest, response::IdentityTokenResponse}, + auth_request::new_auth_request, + }, + client::{LoginMethod, UserLoginMethod}, + error::Result, + mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, + Client, +}; + +pub struct NewAuthRequestResponse { + pub fingerprint: String, + email: String, + device_identifier: String, + auth_request_id: Uuid, + access_code: String, + private_key: String, +} + +pub(crate) async fn send_new_auth_request( + client: &mut Client, + email: String, + device_identifier: String, +) -> Result { + let config = client.get_api_configurations().await; + + let auth = new_auth_request(&email)?; + + let req = AuthRequestCreateRequestModel { + email: email.clone(), + public_key: auth.public_key, + device_identifier: device_identifier.clone(), + access_code: auth.access_code.clone(), + r#type: AuthRequestType::Variant0, // AuthenticateAndUnlock + }; + + let res = auth_requests_post(&config.api, Some(req)).await?; + + Ok(NewAuthRequestResponse { + fingerprint: auth.fingerprint, + email, + device_identifier, + auth_request_id: res.id.unwrap(), + access_code: auth.access_code, + private_key: auth.private_key, + }) +} + +pub(crate) async fn complete_auth_request( + client: &mut Client, + auth_req: NewAuthRequestResponse, +) -> Result<()> { + let config = client.get_api_configurations().await; + + let res = auth_requests_id_response_get( + &config.api, + auth_req.auth_request_id, + Some(&auth_req.access_code), + ) + .await?; + + let approved = res.request_approved.unwrap_or(false); + + if !approved { + return Err("Auth request was not approved".into()); + } + + let response = AuthRequestTokenRequest::new( + &auth_req.email, + &auth_req.auth_request_id, + &auth_req.access_code, + config.device_type, + &auth_req.device_identifier, + ) + .send(config) + .await?; + + if let IdentityTokenResponse::Authenticated(r) = response { + let kdf = Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }; + + client.set_tokens( + r.access_token.clone(), + r.refresh_token.clone(), + r.expires_in, + ); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "web".to_owned(), + email: auth_req.email.to_owned(), + kdf: kdf.clone(), + })); + + let method = match res.master_password_hash { + Some(_) => AuthRequestMethod::MasterKey { + protected_master_key: res.key.unwrap().parse().unwrap(), + auth_request_key: r.key.unwrap().parse().unwrap(), + }, + None => AuthRequestMethod::UserKey { + protected_user_key: res.key.unwrap().parse().unwrap(), + }, + }; + + client + .crypto() + .initialize_user_crypto(InitUserCryptoRequest { + kdf_params: kdf, + email: auth_req.email, + private_key: r.private_key.unwrap(), + method: InitUserCryptoMethod::AuthRequest { + request_private_key: auth_req.private_key, + method, + }, + }) + .await?; + + Ok(()) + } else { + Err("Failed to authenticate".into()) + } +} diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index afd7873a4..a36d27ae9 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -29,6 +29,13 @@ pub(crate) use api_key::login_api_key; #[cfg(feature = "internal")] pub use api_key::{ApiKeyLoginRequest, ApiKeyLoginResponse}; +#[cfg(feature = "mobile")] +mod auth_request; +#[cfg(feature = "mobile")] +pub use auth_request::NewAuthRequestResponse; +#[cfg(feature = "mobile")] +pub(crate) use auth_request::{complete_auth_request, send_new_auth_request}; + #[cfg(feature = "secrets")] mod access_token; #[cfg(feature = "secrets")] diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index f873ace97..4c978e559 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -63,12 +63,20 @@ pub(crate) async fn login_password( async fn request_identity_tokens( client: &mut Client, input: &PasswordLoginRequest, - password_hash: &String, + password_hash: &str, ) -> Result { + use crate::client::client_settings::DeviceType; + let config = client.get_api_configurations().await; - PasswordTokenRequest::new(&input.email, password_hash, &input.two_factor) - .send(config) - .await + PasswordTokenRequest::new( + &input.email, + password_hash, + DeviceType::ChromeBrowser, + "b86dd6ab-4265-4ddf-a7f1-eb28d5677f33", + &input.two_factor, + ) + .send(config) + .await } #[cfg(feature = "internal")] diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 23b64eaf9..d77847574 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -14,10 +14,10 @@ use bitwarden_crypto::{HashPurpose, MasterKey}; pub use register::{RegisterKeyResponse, RegisterRequest}; #[cfg(feature = "internal")] mod auth_request; -#[cfg(feature = "mobile")] -pub(crate) use auth_request::auth_request_decrypt_user_key; #[cfg(feature = "internal")] pub use auth_request::AuthRequestResponse; +#[cfg(feature = "mobile")] +pub(crate) use auth_request::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; #[cfg(feature = "internal")] use crate::{client::Kdf, error::Result}; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 3ccb7f9ca..b8632e21e 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -6,7 +6,7 @@ use bitwarden_crypto::SymmetricCryptoKey; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmetricEncString, EncString}; use chrono::Utc; -use reqwest::header::{self}; +use reqwest::header::{self, HeaderValue}; use uuid::Uuid; use super::AccessToken; @@ -29,6 +29,9 @@ use crate::{ pub(crate) struct ApiConfigurations { pub identity: bitwarden_api_identity::apis::configuration::Configuration, pub api: bitwarden_api_api::apis::configuration::Configuration, + /// Reqwest client useable for external integrations like email forwarders, HIBP. + #[allow(unused)] + pub external_client: reqwest::Client, pub device_type: DeviceType, } @@ -86,17 +89,28 @@ impl Client { pub fn new(settings_input: Option) -> Self { let settings = settings_input.unwrap_or_default(); - let headers = header::HeaderMap::new(); + fn new_client_builder() -> reqwest::ClientBuilder { + #[allow(unused_mut)] + let mut client_builder = reqwest::Client::builder(); - #[allow(unused_mut)] - let mut client_builder = reqwest::Client::builder().default_headers(headers); + #[cfg(all(not(target_os = "android"), not(target_arch = "wasm32")))] + { + client_builder = + client_builder.use_preconfigured_tls(rustls_platform_verifier::tls_config()); + } - #[cfg(all(not(target_os = "android"), not(target_arch = "wasm32")))] - { - client_builder = - client_builder.use_preconfigured_tls(rustls_platform_verifier::tls_config()); + client_builder } + let external_client = new_client_builder().build().unwrap(); + + let mut headers = header::HeaderMap::new(); + headers.append( + "Device-Type", + HeaderValue::from_str(&(settings.device_type as u8).to_string()).unwrap(), + ); + let client_builder = new_client_builder().default_headers(headers); + let client = client_builder.build().unwrap(); let identity = bitwarden_api_identity::apis::configuration::Configuration { @@ -127,6 +141,7 @@ impl Client { __api_configurations: ApiConfigurations { identity, api, + external_client, device_type: settings.device_type, }, encryption_settings: None, @@ -142,7 +157,7 @@ impl Client { #[cfg(feature = "mobile")] pub(crate) fn get_http_client(&self) -> &reqwest::Client { - &self.__api_configurations.api.client + &self.__api_configurations.external_client } #[cfg(feature = "secrets")] diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 9b431b4b4..37bb3b905 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -54,14 +54,31 @@ pub enum InitUserCryptoMethod { AuthRequest { /// Private Key generated by the `crate::auth::new_auth_request`. request_private_key: String, + + method: AuthRequestMethod, + }, +} + +#[cfg(feature = "internal")] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] +pub enum AuthRequestMethod { + UserKey { /// User Key protected by the private key provided in `AuthRequestResponse`. protected_user_key: AsymmetricEncString, }, + MasterKey { + /// Master Key protected by the private key provided in `AuthRequestResponse`. + protected_master_key: AsymmetricEncString, + /// User Key protected by the MasterKey, provided by the auth response. + auth_request_key: EncString, + }, } #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { - use crate::auth::auth_request_decrypt_user_key; + use crate::auth::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { client_id: "".to_string(), @@ -89,9 +106,21 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ } InitUserCryptoMethod::AuthRequest { request_private_key, - protected_user_key, + method, } => { - let user_key = auth_request_decrypt_user_key(request_private_key, protected_user_key)?; + let user_key = match method { + AuthRequestMethod::UserKey { protected_user_key } => { + auth_request_decrypt_user_key(request_private_key, protected_user_key)? + } + AuthRequestMethod::MasterKey { + protected_master_key, + auth_request_key, + } => auth_request_decrypt_master_key( + request_private_key, + protected_master_key, + auth_request_key, + )?, + }; client.initialize_user_crypto_decrypted_key(user_key, private_key)?; } } diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index 53b9b609e..e0195f5aa 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -114,3 +114,26 @@ pub(crate) async fn login_api_key( Ok(()) } + +pub(crate) async fn login_device( + mut client: Client, + email: Option, + device_identifier: Option, +) -> Result<()> { + let email = text_prompt_when_none("Email", email)?; + let device_identifier = text_prompt_when_none("Device Identifier", device_identifier)?; + + let auth = client + .auth() + .login_device(email, device_identifier) + .await + .unwrap(); + + println!("Fingerprint: {}", auth.fingerprint); + + Text::new("Press enter once approved").prompt()?; + + client.auth().login_device_complete(auth).await.unwrap(); + + Ok(()) +} diff --git a/crates/bw/src/auth/mod.rs b/crates/bw/src/auth/mod.rs index a4c7e2ed5..1f165f5f3 100644 --- a/crates/bw/src/auth/mod.rs +++ b/crates/bw/src/auth/mod.rs @@ -1,2 +1,2 @@ mod login; -pub(crate) use login::{login_api_key, login_password}; +pub(crate) use login::{login_api_key, login_device, login_password}; diff --git a/crates/bw/src/main.rs b/crates/bw/src/main.rs index 0e7cd975e..6674bda1e 100644 --- a/crates/bw/src/main.rs +++ b/crates/bw/src/main.rs @@ -78,6 +78,11 @@ enum LoginCommands { client_id: Option, client_secret: Option, }, + Device { + #[arg(short = 'e', long, help = "Email address")] + email: Option, + device_identifier: Option, + }, } #[derive(Subcommand, Clone)] @@ -163,6 +168,12 @@ async fn process_commands() -> Result<()> { client_id, client_secret, } => auth::login_api_key(client, client_id, client_secret).await?, + LoginCommands::Device { + email, + device_identifier, + } => { + auth::login_device(client, email, device_identifier).await?; + } } return Ok(()); } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index f85222738..d69e134c4 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -1280,9 +1280,9 @@ implementations. Private Key generated by the `crate::auth::new_auth_request`. - protected_user_key + method + - User Key protected by the private key provided in `AuthRequestResponse`. From 6749058b7a2f196acff18d97eaae6c92a166fe8c Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 1 Feb 2024 16:47:59 +0100 Subject: [PATCH 249/378] Write more tests for Crypto crate (#570) Extend unit testing for the crypto crate. --- .../src/enc_string/asymmetric.rs | 33 ++++++++ crates/bitwarden-crypto/src/enc_string/mod.rs | 53 +++++++++++++ .../src/enc_string/symmetric.rs | 76 +++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 04768db9e..f9bda838a 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -206,6 +206,8 @@ impl schemars::JsonSchema for AsymmetricEncString { #[cfg(test)] mod tests { + use schemars::schema_for; + use super::{AsymmetricCryptoKey, AsymmetricEncString, KeyDecryptable}; const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- @@ -288,4 +290,35 @@ XKZBokBGnjFnTnKcs7nv/O8= assert_eq!(t.key.to_string(), cipher); assert_eq!(serde_json::to_string(&t).unwrap(), serialized); } + + #[test] + fn test_from_str_invalid() { + let enc_str = "7.ABC"; + let enc_string: Result = enc_str.parse(); + + let err = enc_string.unwrap_err(); + assert_eq!( + err.to_string(), + "EncString error, Invalid asymmetric type, got type 7 with 1 parts" + ); + } + + #[test] + fn test_debug_format() { + let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw=="; + let enc_string: AsymmetricEncString = enc_str.parse().unwrap(); + + let debug_string = format!("{:?}", enc_string); + assert_eq!(debug_string, "AsymmetricEncString"); + } + + #[test] + fn test_json_schema() { + let schema = schema_for!(AsymmetricEncString); + + assert_eq!( + serde_json::to_string(&schema).unwrap(), + r#"{"$schema":"http://json-schema.org/draft-07/schema#","title":"AsymmetricEncString","type":"string"}"# + ); + } } diff --git a/crates/bitwarden-crypto/src/enc_string/mod.rs b/crates/bitwarden-crypto/src/enc_string/mod.rs index e1433821f..3250c1a58 100644 --- a/crates/bitwarden-crypto/src/enc_string/mod.rs +++ b/crates/bitwarden-crypto/src/enc_string/mod.rs @@ -75,3 +75,56 @@ where T::from_str(v).map_err(|e| E::custom(format!("{:?}", e))) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_check_length_less_than_expected() { + let buf = [1, 2, 3]; + let expected = 5; + let result = check_length(&buf, expected); + assert!(result.is_err()); + } + + #[test] + fn test_check_length_equal_to_expected() { + let buf = [1, 2, 3, 4, 5]; + let expected = 5; + let result = check_length(&buf, expected); + assert!(result.is_ok()); + } + + #[test] + fn test_check_length_greater_than_expected() { + let buf = [1, 2, 3, 4, 5, 6]; + let expected = 5; + let result = check_length(&buf, expected); + assert!(result.is_ok()); + } + + #[test] + fn test_split_enc_string_new_format() { + let s = "2.abc|def|ghi"; + let (header, parts) = split_enc_string(s); + assert_eq!(header, "2"); + assert_eq!(parts, vec!["abc", "def", "ghi"]); + } + + #[test] + fn test_split_enc_string_old_format_three_parts() { + let s = "abc|def|ghi"; + let (header, parts) = split_enc_string(s); + assert_eq!(header, "1"); + assert_eq!(parts, vec!["abc", "def", "ghi"]); + } + + #[test] + fn test_split_enc_string_old_format_fewer_parts() { + let s = "abc|def"; + let (header, parts) = split_enc_string(s); + assert_eq!(header, "0"); + assert_eq!(parts, vec!["abc", "def"]); + } +} diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index a76315e96..a7768de23 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -274,6 +274,8 @@ impl schemars::JsonSchema for EncString { #[cfg(test)] mod tests { + use schemars::schema_for; + use super::EncString; use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable}; @@ -325,4 +327,78 @@ mod tests { assert_eq!(enc_string_new.to_string(), enc_str) } + + #[test] + fn test_from_str_cbc256() { + let enc_str = "0.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w=="; + let enc_string: EncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 0); + if let EncString::AesCbc256_B64 { iv, data } = &enc_string { + assert_eq!( + iv, + &[164, 196, 186, 254, 39, 19, 64, 0, 109, 186, 92, 57, 218, 154, 182, 150] + ); + assert_eq!( + data, + &[93, 118, 241, 43, 16, 211, 135, 233, 150, 136, 221, 71, 140, 125, 141, 215] + ); + } + } + + #[test] + fn test_from_str_cbc128_hmac() { + let enc_str = "1.Hh8gISIjJCUmJygpKissLQ==|MjM0NTY3ODk6Ozw9Pj9AQUJDREU=|KCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkc="; + let enc_string: EncString = enc_str.parse().unwrap(); + + assert_eq!(enc_string.enc_type(), 1); + if let EncString::AesCbc128_HmacSha256_B64 { iv, mac, data } = &enc_string { + assert_eq!( + iv, + &[30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45] + ); + assert_eq!( + mac, + &[ + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71 + ] + ); + assert_eq!( + data, + &[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69] + ); + } + } + + #[test] + fn test_from_str_invalid() { + let enc_str = "7.ABC"; + let enc_string: Result = enc_str.parse(); + + let err = enc_string.unwrap_err(); + assert_eq!( + err.to_string(), + "EncString error, Invalid symmetric type, got type 7 with 1 parts" + ); + } + + #[test] + fn test_debug_format() { + let enc_str = "2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8="; + let enc_string: EncString = enc_str.parse().unwrap(); + + let debug_string = format!("{:?}", enc_string); + assert_eq!(debug_string, "EncString"); + } + + #[test] + fn test_json_schema() { + let schema = schema_for!(EncString); + + assert_eq!( + serde_json::to_string(&schema).unwrap(), + r#"{"$schema":"http://json-schema.org/draft-07/schema#","title":"EncString","type":"string"}"# + ); + } } From ac58ac9becb16fbf28862a02783fc4140a1c04f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 2 Feb 2024 12:06:04 +0100 Subject: [PATCH 250/378] Add test to ensure we are using a compatible rustls version (#569) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective We need to keep the version of rustls that reqwest and rustls-platform-verifier use in sync to avoid runtime errors when creating the reqwest client, we can't check it at compile time due to the use of `&dyn Any` and downcasting, but we can add a test. --- crates/bitwarden/src/client/client.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index b8632e21e..5b2c8b7e0 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -306,3 +306,23 @@ impl Client { Ok(self.encryption_settings.as_ref().unwrap()) } } + +#[cfg(test)] +mod tests { + #[test] + fn test_reqwest_rustls_platform_verifier_are_compatible() { + // rustls-platform-verifier is generating a rustls::ClientConfig, + // which reqwest accepts as a &dyn Any and then downcasts it to a + // rustls::ClientConfig. + + // This means that if the rustls version of the two crates don't match, + // the downcast will fail and we will get a runtime error. + + // This tests is added to ensure that it doesn't happen. + + let _ = reqwest::ClientBuilder::new() + .use_preconfigured_tls(rustls_platform_verifier::tls_config()) + .build() + .unwrap(); + } +} From 32be569f753794884930bbc0e102313a7cc04487 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 2 Feb 2024 13:36:41 +0100 Subject: [PATCH 251/378] Support validating password by decrypting user key (#572) Enables password validation without knowing the password hash by decrypting the user key. --- crates/bitwarden-uniffi/src/auth/mod.rs | 23 +++- crates/bitwarden/src/auth/client_auth.rs | 15 ++- crates/bitwarden/src/auth/login/password.rs | 3 +- crates/bitwarden/src/auth/login/two_factor.rs | 3 +- crates/bitwarden/src/auth/mod.rs | 10 +- crates/bitwarden/src/auth/password/mod.rs | 2 + .../bitwarden/src/auth/password/validate.rs | 121 ++++++++++++++++-- 7 files changed, 153 insertions(+), 24 deletions(-) diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 62c791967..75e0c5656 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -90,8 +90,27 @@ impl ClientAuth { .write() .await .auth() - .validate_password(password, password_hash.to_string()) - .await?) + .validate_password(password, password_hash.to_string())?) + } + + /// Validate the user password without knowing the password hash + /// + /// Used for accounts that we know have master passwords but that have not logged in with a + /// password. Some example are login with device or TDE. + /// + /// This works by comparing the provided password against the encrypted user key. + pub async fn validate_password_user_key( + &self, + password: String, + encrypted_user_key: String, + ) -> Result { + Ok(self + .0 + .0 + .write() + .await + .auth() + .validate_password_user_key(password, encrypted_user_key)?) } /// Initialize a new auth request diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 0ae2f6f33..f08daf0b7 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -16,7 +16,8 @@ use crate::{ TwoFactorEmailRequest, }, password::{ - password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, + password_strength, satisfies_policy, validate_password, validate_password_user_key, + MasterPasswordPolicyOptions, }, register::{make_register_keys, register}, AuthRequestResponse, RegisterKeyResponse, RegisterRequest, @@ -101,8 +102,16 @@ impl<'a> ClientAuth<'a> { send_two_factor_email(self.client, tf).await } - pub async fn validate_password(&self, password: String, password_hash: String) -> Result { - validate_password(self.client, password, password_hash).await + pub fn validate_password(&self, password: String, password_hash: String) -> Result { + validate_password(self.client, password, password_hash) + } + + pub fn validate_password_user_key( + &self, + password: String, + encrypted_user_key: String, + ) -> Result { + validate_password_user_key(self.client, password, encrypted_user_key) } pub fn new_auth_request(&self, email: &str) -> Result { diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 4c978e559..02552b70e 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -34,8 +34,7 @@ pub(crate) async fn login_password( &input.kdf, &input.password, HashPurpose::ServerAuthorization, - ) - .await?; + )?; let response = request_identity_tokens(client, input, &password_hash).await?; if let IdentityTokenResponse::Authenticated(r) = &response { diff --git a/crates/bitwarden/src/auth/login/two_factor.rs b/crates/bitwarden/src/auth/login/two_factor.rs index 45be042c7..c8f0cc55b 100644 --- a/crates/bitwarden/src/auth/login/two_factor.rs +++ b/crates/bitwarden/src/auth/login/two_factor.rs @@ -27,8 +27,7 @@ pub(crate) async fn send_two_factor_email( &kdf, &input.password, HashPurpose::ServerAuthorization, - ) - .await?; + )?; let config = client.get_api_configurations().await; bitwarden_api_api::apis::two_factor_api::two_factor_send_email_login_post( diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index d77847574..021c97c0f 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -23,7 +23,7 @@ pub(crate) use auth_request::{auth_request_decrypt_master_key, auth_request_decr use crate::{client::Kdf, error::Result}; #[cfg(feature = "internal")] -async fn determine_password_hash( +fn determine_password_hash( email: &str, kdf: &Kdf, password: &str, @@ -40,8 +40,8 @@ mod tests { use super::*; #[cfg(feature = "internal")] - #[tokio::test] - async fn test_determine_password_hash() { + #[test] + fn test_determine_password_hash() { use super::determine_password_hash; let password = "password123"; @@ -51,9 +51,7 @@ mod tests { }; let purpose = HashPurpose::LocalAuthorization; - let result = determine_password_hash(email, &kdf, password, purpose) - .await - .unwrap(); + let result = determine_password_hash(email, &kdf, password, purpose).unwrap(); assert_eq!(result, "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU="); } diff --git a/crates/bitwarden/src/auth/password/mod.rs b/crates/bitwarden/src/auth/password/mod.rs index b7833c7f8..d0f3329f2 100644 --- a/crates/bitwarden/src/auth/password/mod.rs +++ b/crates/bitwarden/src/auth/password/mod.rs @@ -3,5 +3,7 @@ pub(crate) use policy::satisfies_policy; pub use policy::MasterPasswordPolicyOptions; mod validate; pub(crate) use validate::validate_password; +#[cfg(feature = "internal")] +pub(crate) use validate::validate_password_user_key; mod strength; pub(crate) use strength::password_strength; diff --git a/crates/bitwarden/src/auth/password/validate.rs b/crates/bitwarden/src/auth/password/validate.rs index f6d22e11a..9003347d9 100644 --- a/crates/bitwarden/src/auth/password/validate.rs +++ b/crates/bitwarden/src/auth/password/validate.rs @@ -1,4 +1,4 @@ -use bitwarden_crypto::HashPurpose; +use bitwarden_crypto::{HashPurpose, MasterKey}; use crate::{ auth::determine_password_hash, @@ -8,7 +8,7 @@ use crate::{ }; /// Validate if the provided password matches the password hash stored in the client. -pub(crate) async fn validate_password( +pub(crate) fn validate_password( client: &Client, password: String, password_hash: String, @@ -22,9 +22,12 @@ pub(crate) async fn validate_password( match login_method { UserLoginMethod::Username { email, kdf, .. } | UserLoginMethod::ApiKey { email, kdf, .. } => { - let hash = - determine_password_hash(email, kdf, &password, HashPurpose::LocalAuthorization) - .await?; + let hash = determine_password_hash( + email, + kdf, + &password, + HashPurpose::LocalAuthorization, + )?; Ok(hash == password_hash) } @@ -34,13 +37,53 @@ pub(crate) async fn validate_password( } } +#[cfg(feature = "internal")] +pub(crate) fn validate_password_user_key( + client: &Client, + password: String, + encrypted_user_key: String, +) -> Result { + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + if let LoginMethod::User(login_method) = login_method { + match login_method { + UserLoginMethod::Username { email, kdf, .. } + | UserLoginMethod::ApiKey { email, kdf, .. } => { + let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; + let user_key = master_key + .decrypt_user_key(encrypted_user_key.parse()?) + .map_err(|_| "wrong password")?; + + let enc = client + .get_encryption_settings() + .map_err(|_| Error::VaultLocked)?; + + let existing_key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + + if user_key.to_vec() != existing_key.to_vec() { + return Err("wrong user key".into()); + } + + Ok(master_key + .derive_master_key_hash(password.as_bytes(), HashPurpose::LocalAuthorization)?) + } + } + } else { + Err(Error::NotAuthenticated) + } +} + #[cfg(test)] mod tests { - #[tokio::test] - async fn test_validate_password() { + use crate::auth::password::{validate::validate_password_user_key, validate_password}; + + #[test] + fn test_validate_password() { use std::num::NonZeroU32; - use super::validate_password; use crate::client::{Client, Kdf, LoginMethod, UserLoginMethod}; let mut client = Client::new(None); @@ -55,8 +98,68 @@ mod tests { let password = "password123".to_string(); let password_hash = "7kTqkF1pY/3JeOu73N9kR99fDDe9O1JOZaVc7KH3lsU=".to_string(); - let result = validate_password(&client, password, password_hash).await; + let result = validate_password(&client, password, password_hash); assert!(result.unwrap()); } + + #[cfg(feature = "internal")] + #[test] + fn test_validate_password_user_key() { + use std::num::NonZeroU32; + + use crate::client::{Client, Kdf, LoginMethod, UserLoginMethod}; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + email: "test@bitwarden.com".to_string(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + client_id: "1".to_string(), + })); + + let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE="; + let private_key = "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap(); + + client + .initialize_user_crypto("asdfasdfasdf", user_key.parse().unwrap(), private_key) + .unwrap(); + + let result = + validate_password_user_key(&client, "asdfasdfasdf".to_string(), user_key.to_string()) + .unwrap(); + + assert_eq!(result, "aOvkBXFhSdgrBWR3hZCMRoML9+h5yRblU3lFphCdkeA="); + assert!(validate_password(&client, "asdfasdfasdf".to_string(), result.to_string()).unwrap()) + } + + #[cfg(feature = "internal")] + #[test] + fn test_validate_password_user_key_wrong_password() { + use std::num::NonZeroU32; + + use crate::client::{Client, Kdf, LoginMethod, UserLoginMethod}; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + email: "test@bitwarden.com".to_string(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + client_id: "1".to_string(), + })); + + let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE="; + let private_key = "2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap(); + + client + .initialize_user_crypto("asdfasdfasdf", user_key.parse().unwrap(), private_key) + .unwrap(); + + let result = validate_password_user_key(&client, "abc".to_string(), user_key.to_string()) + .unwrap_err(); + + assert_eq!(result.to_string(), "Internal error: wrong password"); + } } From 0be34620bfa94def4d09cab515ca287b9a6ed7ce Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 10:41:05 +0100 Subject: [PATCH 252/378] [deps]: Update Rust crate toml to 0.8.9 (#577) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [toml](https://togithub.com/toml-rs/toml) | dependencies | patch | `0.8.8` -> `0.8.9` | --- ### Release Notes
toml-rs/toml (toml) ### [`v0.8.9`](https://togithub.com/toml-rs/toml/compare/toml-v0.8.8...toml-v0.8.9) [Compare Source](https://togithub.com/toml-rs/toml/compare/toml-v0.8.8...toml-v0.8.9)
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- crates/bws/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8ebf52136..f7e721c1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -612,7 +612,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.8", + "toml 0.8.9", "uuid", ] @@ -3452,9 +3452,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" dependencies = [ "serde", "serde_spanned", @@ -3473,9 +3473,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.1", "serde", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 1c04a6668..bb757eca6 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -37,7 +37,7 @@ serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.56" tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } -toml = "0.8.8" +toml = "0.8.9" uuid = { version = "^1.7.0", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } From ddd98880cf6ee026ab38cb0446827ef5351e89b5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:01:34 +0100 Subject: [PATCH 253/378] [deps]: Update Rust crate itertools to 0.12.1 (#576) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [itertools](https://togithub.com/rust-itertools/itertools) | dependencies | patch | `0.12.0` -> `0.12.1` | --- ### Release Notes
rust-itertools/itertools (itertools) ### [`v0.12.1`](https://togithub.com/rust-itertools/itertools/blob/HEAD/CHANGELOG.md#0121) [Compare Source](https://togithub.com/rust-itertools/itertools/compare/v0.12.0...v0.12.1) ##### Added - Documented iteration order guarantee for `Itertools::[tuple_]combinations` ([#​822](https://togithub.com/rust-itertools/itertools/issues/822)) - Documented possible panic in `iterate` ([#​842](https://togithub.com/rust-itertools/itertools/issues/842)) - Implemented `Clone` and `Debug` for `Diff` ([#​845](https://togithub.com/rust-itertools/itertools/issues/845)) - Implemented `Debug` for `WithPosition` ([#​859](https://togithub.com/rust-itertools/itertools/issues/859)) - Implemented `Eq` for `MinMaxResult` ([#​838](https://togithub.com/rust-itertools/itertools/issues/838)) - Implemented `From>` for `Option>` ([#​843](https://togithub.com/rust-itertools/itertools/issues/843)) - Implemented `PeekingNext` for `RepeatN` ([#​855](https://togithub.com/rust-itertools/itertools/issues/855)) ##### Changed - Made `CoalesceBy` lazy ([#​801](https://togithub.com/rust-itertools/itertools/issues/801)) - Optimized `Filter[Map]Ok::next`, `Itertools::partition`, `Unique[By]::next[_back]` ([#​818](https://togithub.com/rust-itertools/itertools/issues/818)) - Optimized `Itertools::find_position` ([#​837](https://togithub.com/rust-itertools/itertools/issues/837)) - Optimized `Positions::next[_back]` ([#​816](https://togithub.com/rust-itertools/itertools/issues/816)) - Optimized `ZipLongest::fold` ([#​854](https://togithub.com/rust-itertools/itertools/issues/854)) - Relaxed `Debug` bounds for `GroupingMapBy` ([#​860](https://togithub.com/rust-itertools/itertools/issues/860)) - Specialized `ExactlyOneError::fold` ([#​826](https://togithub.com/rust-itertools/itertools/issues/826)) - Specialized `Interleave[Shortest]::fold` ([#​849](https://togithub.com/rust-itertools/itertools/issues/849)) - Specialized `MultiPeek::fold` ([#​820](https://togithub.com/rust-itertools/itertools/issues/820)) - Specialized `PadUsing::[r]fold` ([#​825](https://togithub.com/rust-itertools/itertools/issues/825)) - Specialized `PeekNth::fold` ([#​824](https://togithub.com/rust-itertools/itertools/issues/824)) - Specialized `Positions::[r]fold` ([#​813](https://togithub.com/rust-itertools/itertools/issues/813)) - Specialized `PutBackN::fold` ([#​823](https://togithub.com/rust-itertools/itertools/issues/823)) - Specialized `RepeatN::[r]fold` ([#​821](https://togithub.com/rust-itertools/itertools/issues/821)) - Specialized `TakeWhileInclusive::fold` ([#​851](https://togithub.com/rust-itertools/itertools/issues/851)) - Specialized `ZipLongest::rfold` ([#​848](https://togithub.com/rust-itertools/itertools/issues/848)) ##### Notable Internal Changes - Added test coverage in CI ([#​847](https://togithub.com/rust-itertools/itertools/issues/847), [#​856](https://togithub.com/rust-itertools/itertools/issues/856)) - Added semver check in CI ([#​784](https://togithub.com/rust-itertools/itertools/issues/784)) - Enforced `clippy` in CI ([#​740](https://togithub.com/rust-itertools/itertools/issues/740)) - Enforced `rustdoc` in CI ([#​840](https://togithub.com/rust-itertools/itertools/issues/840)) - Improved specialization tests ([#​807](https://togithub.com/rust-itertools/itertools/issues/807)) - More specialization benchmarks ([#​806](https://togithub.com/rust-itertools/itertools/issues/806))
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 6 +++--- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7e721c1a..03f0cfc2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1806,9 +1806,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -2893,7 +2893,7 @@ dependencies = [ "bitwarden", "bitwarden-json", "bitwarden-uniffi", - "itertools 0.12.0", + "itertools 0.12.1", "schemars", "serde_json", ] diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 3e7282e7e..81a9d76ca 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -13,7 +13,7 @@ internal = [ [dependencies] anyhow = "1.0.79" -itertools = "0.12.0" +itertools = "0.12.1" schemars = { version = "0.8.16", features = ["preserve_order"] } serde_json = "1.0.113" From 098870d2b02d1a3abee461c0e9e318a0ecd829dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:02:11 +0100 Subject: [PATCH 254/378] [deps]: Update Rust crate tokio to 1.36.0 (#579) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | dependencies | minor | `1.35.1` -> `1.36.0` | | [tokio](https://tokio.rs) ([source](https://togithub.com/tokio-rs/tokio)) | dev-dependencies | minor | `1.35.1` -> `1.36.0` | --- ### Release Notes
tokio-rs/tokio (tokio) ### [`v1.36.0`](https://togithub.com/tokio-rs/tokio/releases/tag/tokio-1.36.0): Tokio v1.36.0 [Compare Source](https://togithub.com/tokio-rs/tokio/compare/tokio-1.35.1...tokio-1.36.0) ##### 1.36.0 (February 2nd, 2024) ##### Added - io: add `tokio::io::Join` ([#​6220]) - io: implement `AsyncWrite` for `Empty` ([#​6235]) - net: add support for anonymous unix pipes ([#​6127]) - net: add `UnixSocket` ([#​6290]) - net: expose keepalive option on `TcpSocket` ([#​6311]) - sync: add `{Receiver,UnboundedReceiver}::poll_recv_many` ([#​6236]) - sync: add `Sender::{try_,}reserve_many` ([#​6205]) - sync: add `watch::Receiver::mark_unchanged` ([#​6252]) - task: add `JoinSet::try_join_next` ([#​6280]) - time: add `FutureExt::timeout` ([#​6276]) ##### Changed - io: make `copy` cooperative ([#​6265]) - io: make `repeat` and `sink` cooperative ([#​6254]) - io: simplify check for empty slice ([#​6293]) - rt: improve robustness of `wake_in_drop_after_panic` test ([#​6238]) - process: use pidfd on Linux when available ([#​6152]) - sync: use AtomicBool in broadcast channel future ([#​6298]) ##### Fixed - chore: typographic improvements ([#​6262]) - runtime: remove obsolete comment ([#​6303]) - task: fix typo ([#​6261]) ##### Documented - io: clarify `clear_ready` docs ([#​6304]) - net: document that `*Fd` traits on `TcpSocket` are unix-only ([#​6294]) - sync: document FIFO behavior of `tokio::sync::Mutex` ([#​6279]) [#​6220]: https://togithub.com/tokio-rs/tokio/pull/6220 [#​6235]: https://togithub.com/tokio-rs/tokio/pull/6235 [#​6127]: https://togithub.com/tokio-rs/tokio/pull/6127 [#​6290]: https://togithub.com/tokio-rs/tokio/pull/6290 [#​6311]: https://togithub.com/tokio-rs/tokio/pull/6311 [#​6236]: https://togithub.com/tokio-rs/tokio/pull/6236 [#​6205]: https://togithub.com/tokio-rs/tokio/pull/6205 [#​6252]: https://togithub.com/tokio-rs/tokio/pull/6252 [#​6280]: https://togithub.com/tokio-rs/tokio/pull/6280 [#​6276]: https://togithub.com/tokio-rs/tokio/pull/6276 [#​6265]: https://togithub.com/tokio-rs/tokio/pull/6265 [#​6254]: https://togithub.com/tokio-rs/tokio/pull/6254 [#​6293]: https://togithub.com/tokio-rs/tokio/pull/6293 [#​6238]: https://togithub.com/tokio-rs/tokio/pull/6238 [#​6152]: https://togithub.com/tokio-rs/tokio/pull/6152 [#​6298]: https://togithub.com/tokio-rs/tokio/pull/6298 [#​6262]: https://togithub.com/tokio-rs/tokio/pull/6262 [#​6303]: https://togithub.com/tokio-rs/tokio/pull/6303 [#​6261]: https://togithub.com/tokio-rs/tokio/pull/6261 [#​6304]: https://togithub.com/tokio-rs/tokio/pull/6304 [#​6294]: https://togithub.com/tokio-rs/tokio/pull/6294 [#​6279]: https://togithub.com/tokio-rs/tokio/pull/6279
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden-py/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03f0cfc2f..b4469fc04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3391,9 +3391,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index 7f26a47cf..39eeb3d71 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -29,5 +29,5 @@ uniffi = { version = "=0.26.1", optional = true } [dev-dependencies] rand_chacha = "0.3.1" -tokio = { version = "1.35.1", features = ["rt", "macros"] } +tokio = { version = "1.36.0", features = ["rt", "macros"] } wiremock = "0.5.22" diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index ed7c5df5e..e81f2f5a8 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -18,7 +18,7 @@ bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3-build-config = { version = "0.20.2" } [target.'cfg(not(target_arch="wasm32"))'.dependencies] -tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index b52e2f8f3..d9508258b 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -76,6 +76,6 @@ reqwest = { version = "*", features = [ [dev-dependencies] rand_chacha = "0.3.1" -tokio = { version = "1.35.1", features = ["rt", "macros"] } +tokio = { version = "1.36.0", features = ["rt", "macros"] } wiremock = "0.5.22" zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index cc07397cd..1943e5ad5 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6" env_logger = "0.11.1" inquire = "0.6.2" log = "0.4.20" -tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ "internal", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index bb757eca6..608db45a8 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -36,7 +36,7 @@ serde_json = "^1.0.113" serde_yaml = "0.9" supports-color = "2.1.0" thiserror = "1.0.56" -tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.9" uuid = { version = "^1.7.0", features = ["serde"] } From bf02c3ba5a6080c4d67765e01a7d6e85e49e1363 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:02:56 +0100 Subject: [PATCH 255/378] [deps]: Update Rust crate clap_complete to 4.4.10 (#575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap_complete](https://togithub.com/clap-rs/clap) ([source](https://togithub.com/clap-rs/clap/tree/HEAD/clap_complete)) | dependencies | patch | `4.4.9` -> `4.4.10` | --- ### Release Notes
clap-rs/clap (clap_complete) ### [`v4.4.10`](https://togithub.com/clap-rs/clap/blob/HEAD/clap_complete/CHANGELOG.md#4410---2024-02-02) [Compare Source](https://togithub.com/clap-rs/clap/compare/clap_complete-v4.4.9...clap_complete-v4.4.10) ##### Fixes - *(bash)* Allow completing filenames with spaces
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4469fc04..6cae436a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -752,9 +752,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.9" +version = "4.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df631ae429f6613fcd3a7c1adbdb65f637271e561b03680adaa6573015dfb106" +checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3" dependencies = [ "clap", ] diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 608db45a8..3766ad682 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.33", features = [ "std", ], default-features = false } clap = { version = "4.4.18", features = ["derive", "env", "string"] } -clap_complete = "4.4.9" +clap_complete = "4.4.10" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" From 4883eba21061b67fa5b821aa8e6926d976eeb621 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:41:26 +0100 Subject: [PATCH 256/378] [deps]: Update Rust crate supports-color to v3 (#582) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [supports-color](https://togithub.com/zkat/supports-color) | dependencies | major | `2.1.0` -> `3.0.0` | --- ### Release Notes
zkat/supports-color (supports-color) ### [`v3.0.0`](https://togithub.com/zkat/supports-color/blob/HEAD/CHANGELOG.md#300-2024-02-04) [Compare Source](https://togithub.com/zkat/supports-color/compare/v2.1.0...v3.0.0) ##### Features - **deps:** Replace `is-terminal` with `std::io::IsTerminal` ([#​11](https://togithub.com/zkat/supports-color/issues/11)) ([6fb6e359](https://togithub.com/zkat/supports-color/commit/6fb6e35961055a701264d879744f615c25b7629d)) - **BREAKING CHANGE**: This bumps the MSRV to 1.70.0 due to the new `std::io::IsTerminal` API.
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 20 ++++---------------- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6cae436a0..9054b7734 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1778,22 +1778,11 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "is_ci" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "itertools" @@ -3215,11 +3204,10 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "supports-color" -version = "2.1.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" dependencies = [ - "is-terminal", "is_ci", ] diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index bded30904..4248c9189 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -8,4 +8,4 @@ rust-version = "1.57" clap = { version = "4.4.18", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" -supports-color = "2.1.0" +supports-color = "3.0.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 3766ad682..8acc9f92c 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -34,7 +34,7 @@ regex = { version = "1.10.3", features = [ serde = "^1.0.196" serde_json = "^1.0.113" serde_yaml = "0.9" -supports-color = "2.1.0" +supports-color = "3.0.0" thiserror = "1.0.56" tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.9" From 851f4a6896580894b7e95a106d78fbe152879c9d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:41:46 +0100 Subject: [PATCH 257/378] [deps]: Update @types/node to v18.19.14 (#574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.10` -> `18.19.14`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.10/18.19.14) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.10/18.19.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.10/18.19.14?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index d1192e6f5..eb8d010db 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.10.tgz", - "integrity": "sha512-IZD8kAM02AW1HRDTPOlz3npFava678pr8Ie9Vp8uRhBROXAv8MXT2pCnGZZAKYdromsNQLHQcfWQ6EOatVLtqA==", + "version": "18.19.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.14.tgz", + "integrity": "sha512-EnQ4Us2rmOS64nHDWr0XqAD8DsO6f3XR6lf9UIIrZQpUzPVdN/oPuEzfDWNHSyXLvoGgjuEm/sPwFGSSs35Wtg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From a67b173f9acdc103a2274f85382b1a53dcfd5d02 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 13:43:17 +0100 Subject: [PATCH 258/378] [PM-6067] [deps]: Lock file maintenance (#584) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). [PM-6067](https://bitwarden.atlassian.net/browse/PM-6067) [PM-6067]: https://bitwarden.atlassian.net/browse/PM-6067?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 75 +++++++++++++++---------- crates/bitwarden-napi/package-lock.json | 6 +- package-lock.json | 6 +- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9054b7734..98274e54f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] name = "anstyle-parse" @@ -1242,9 +1242,9 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -1502,7 +1502,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.1", + "indexmap 2.2.2", "slab", "tokio", "tokio-util", @@ -1661,9 +1661,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1717,9 +1717,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" +checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1848,9 +1848,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -1949,9 +1949,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1970,9 +1970,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.15.0" +version = "2.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbf98e1bcb85cc441bbf7cdfb11070d2537a100e2697d75397b2584c32492d1" +checksum = "43792514b0c95c5beec42996da0c1b39265b02b75c97baa82d163d3ef55cbfa7" dependencies = [ "bitflags 2.4.2", "ctor", @@ -2082,6 +2082,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.45" @@ -2315,7 +2321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.7", - "indexmap 2.2.1", + "indexmap 2.2.2", "line-wrap", "quick-xml", "serde", @@ -2592,9 +2598,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ "base64 0.21.7", "bytes", @@ -2619,6 +2625,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls", @@ -2688,9 +2695,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.2", "errno", @@ -3022,7 +3029,7 @@ version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -3233,6 +3240,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "syntect" version = "5.1.0" @@ -3335,12 +3348,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -3355,10 +3369,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -3465,7 +3480,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.1", + "indexmap 2.2.2", "serde", "serde_spanned", "toml_datetime", @@ -3920,9 +3935,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "weedle2" @@ -4107,9 +4122,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.35" +version = "0.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" +checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" dependencies = [ "memchr", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index a8995bc77..9c9d87de9 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dev": true, "peer": true, "dependencies": { diff --git a/package-lock.json b/package-lock.json index 747d7d809..4ad23e90b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -346,9 +346,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.10.tgz", - "integrity": "sha512-rZEfe/hJSGYmdfX9tvcPMYeYPW2sNl50nsw4jZmRcaG0HIAb0WYEpsB05GOb53vjqpyE9GUhlDQ4jLSoB5q9kg==", + "version": "20.11.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", + "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", "dev": true, "peer": true, "dependencies": { From 43bdcf0a51696c4d8aa0e337d31214531db8bafe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:06:55 +0100 Subject: [PATCH 259/378] [deps]: Update prettier to v3.2.5 (#583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [prettier](https://prettier.io) ([source](https://togithub.com/prettier/prettier)) | [`3.2.4` -> `3.2.5`](https://renovatebot.com/diffs/npm/prettier/3.2.4/3.2.5) | [![age](https://developer.mend.io/api/mc/badges/age/npm/prettier/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/prettier/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/prettier/3.2.4/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/prettier/3.2.4/3.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
prettier/prettier (prettier) ### [`v3.2.5`](https://togithub.com/prettier/prettier/blob/HEAD/CHANGELOG.md#325) [Compare Source](https://togithub.com/prettier/prettier/compare/3.2.4...3.2.5) [diff](https://togithub.com/prettier/prettier/compare/3.2.4...3.2.5) ##### Support Angular inline styles as single template literal ([#​15968](https://togithub.com/prettier/prettier/pull/15968) by [@​sosukesuzuki](https://togithub.com/sosukesuzuki)) [Angular v17](https://blog.angular.io/introducing-angular-v17-4d7033312e4b) supports single string inline styles. ```ts // Input @​Component({ template: `
...
`, styles: `h1 { color: blue; }`, }) export class AppComponent {} // Prettier 3.2.4 @​Component({ template: `
...
`, styles: `h1 { color: blue; }`, }) export class AppComponent {} // Prettier 3.2.5 @​Component({ template: `
...
`, styles: ` h1 { color: blue; } `, }) export class AppComponent {} ``` ##### Unexpected embedded formatting for Angular template ([#​15969](https://togithub.com/prettier/prettier/pull/15969) by [@​JounQin](https://togithub.com/JounQin)) Computed template should not be considered as Angular component template ```ts // Input const template = "foobar"; @​Component({ [template]: `

{{ hello }}

`, }) export class AppComponent {} // Prettier 3.2.4 const template = "foobar"; @​Component({ [template]: `

{{ hello }}

`, }) export class AppComponent {} // Prettier 3.2.5 const template = "foobar"; @​Component({ [template]: `

{{ hello }}

`, }) export class AppComponent {} ``` ##### Use `"json"` parser for `tsconfig.json` by default ([#​16012](https://togithub.com/prettier/prettier/pull/16012) by [@​sosukesuzuki](https://togithub.com/sosukesuzuki)) In [v2.3.0](https://prettier.io/blog/2024/01/12/3.2.0#new-jsonc-parser-added-15831httpsgithubcomprettierprettierpull15831-by-fiskerhttpsgithubcomfisker), we introduced `"jsonc"` parser which adds trialing comma **by default**. When adding a new parser we also define how it will be used based on the [`linguist-languages`](https://www.npmjs.com/package/linguist-languages) data. `tsconfig.json` is a special file used by [TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#using-tsconfigjson-or-jsconfigjson), it uses `.json` file extension, but it actually uses the [JSON with Comments](https://code.visualstudio.com/docs/languages/json#\_json-with-comments) syntax. However, we found that there are many third-party tools not recognize it correctly because of the confusing `.json` file extension. We decide to treat it as a JSON file for now to avoid the extra configuration step. To keep using the `"jsonc"` parser for your `tsconfig.json` files, add the following to your `.pretterrc` file ```json { "overrides": [ { "files": ["tsconfig.json", "jsconfig.json"], "options": { "parser": "jsonc" } } ] } ``` ``` ```
--- ### Configuration 📅 **Schedule**: Branch creation - "every weekend" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Hinton --- crates/bitwarden-napi/tsconfig.json | 4 ++-- package-lock.json | 8 ++++---- package.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden-napi/tsconfig.json b/crates/bitwarden-napi/tsconfig.json index 8ec7e00d4..f977e0759 100644 --- a/crates/bitwarden-napi/tsconfig.json +++ b/crates/bitwarden-napi/tsconfig.json @@ -7,7 +7,7 @@ "strict": true, "noImplicitAny": true, "esModuleInterop": true, - "declaration": true, + "declaration": true }, - "include": ["src-ts", "src-ts/bitwarden_client", "src-ts/index.ts"], + "include": ["src-ts", "src-ts/bitwarden_client", "src-ts/index.ts"] } diff --git a/package-lock.json b/package-lock.json index 4ad23e90b..bdb82563e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", - "prettier": "3.2.4", + "prettier": "3.2.5", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", @@ -1471,9 +1471,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" diff --git a/package.json b/package.json index 14b5692a0..05195270e 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "devDependencies": { "@openapitools/openapi-generator-cli": "2.9.0", "handlebars": "^4.7.8", - "prettier": "3.2.4", + "prettier": "3.2.5", "quicktype-core": "23.0.81", "rimraf": "5.0.5", "ts-node": "10.9.2", From 11e36557dcb86c7cb376d278124371fb6e764b7d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 09:02:30 -0500 Subject: [PATCH 260/378] [deps]: Update codecov/codecov-action action to v4 (#580) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rust-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 93a2ddecf..8408dd1d7 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -73,7 +73,7 @@ jobs: run: cargo llvm-cov --all-features --lcov --output-path lcov.info --ignore-filename-regex "crates/bitwarden-api-" - name: Upload to codecov.io - uses: codecov/codecov-action@4fe8c5f003fae66aa5ebb77cfd3e7bfbbda0b6b0 # v3.1.5 + uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From 46c72f3dbadc3dce09acb1775f7033b2a3ba882a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 09:13:05 -0500 Subject: [PATCH 261/378] [deps]: Update ruby/setup-ruby action to v1.171.0 (#578) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 81aedcc22..12abd18f0 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -23,7 +23,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Set up Ruby - uses: ruby/setup-ruby@bd03e04863f52d169e18a2b190e8fa6b84938215 # v1.170.0 + uses: ruby/setup-ruby@22fdc77bf4148f810455b226c90fb81b5cbc00a7 # v1.171.0 with: ruby-version: 3.2 From 69a5d7bf01b17aeccb3be7bc77272bf50cb24de9 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Mon, 5 Feb 2024 10:46:47 -0500 Subject: [PATCH 262/378] Update Gradle action as recommended in new release (#585) --- .github/workflows/build-android.yml | 2 +- .github/workflows/build-java.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index e1aeea244..efa8c7bf0 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -102,7 +102,7 @@ jobs: run: ./build-schemas.sh - name: Publish - uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 + uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 with: arguments: sdk:publish build-root-directory: languages/kotlin diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 0ed8997ca..2559f659c 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -61,7 +61,7 @@ jobs: path: languages/java/src/main/resources/win32-x86-64 - name: Publish Maven - uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 + uses: gradle/actions/setup-gradle@ec92e829475ac0c2315ea8f9eced72db85bb337a # v3.0.0 with: arguments: publish build-root-directory: languages/java From b98a019482d06e8c89afeceded1b6bffc32bd127 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 6 Feb 2024 10:34:43 +0100 Subject: [PATCH 263/378] Use base renovate config (#586) Use shared renovate config. --- .github/renovate.json | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index ae4ad0e9d..ddfc900dc 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,21 +1,8 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "config:base", - "github>bitwarden/renovate-config:pin-actions", - ":combinePatchMinorReleases", - ":dependencyDashboard", - ":maintainLockFilesWeekly", - ":prConcurrentLimit10", - ":rebaseStalePrs", - ":separateMajorReleases", - "group:monorepos", - "schedule:weekends" - ], + "extends": ["github>bitwarden/renovate-config:non-pinned"], "separateMajorMinor": true, "enabledManagers": ["cargo", "github-actions", "npm", "nuget"], - "commitMessagePrefix": "[deps]:", - "commitMessageTopic": "{{depName}}", "packageRules": [ { "matchManagers": ["cargo"], From 714c2d40d1811c13c751b6de9a9fe0ae51f61583 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 6 Feb 2024 11:52:38 +0100 Subject: [PATCH 264/378] [PM-3438] Vault exports (#561) Vault export implementation. New crate `bitwarden-exporters` which defines it's own data structure, isolating it from the other code areas. It primarily focuses on converting a data model to csv and json. Currently all data has to be decrypted independently of what is required for the export which is an area of improvement for the future. --- .prettierignore | 3 + .vscode/settings.json | 2 + Cargo.lock | 34 + crates/bitwarden-exporters/Cargo.toml | 26 + crates/bitwarden-exporters/README.md | 6 + .../resources/json_export.json | 146 ++++ crates/bitwarden-exporters/src/csv.rs | 266 ++++++ crates/bitwarden-exporters/src/json.rs | 762 ++++++++++++++++++ crates/bitwarden-exporters/src/lib.rs | 142 ++++ crates/bitwarden/Cargo.toml | 1 + crates/bitwarden/src/error.rs | 5 + .../src/tool/exporters/client_exporter.rs | 6 +- crates/bitwarden/src/tool/exporters/mod.rs | 278 ++++++- crates/bitwarden/src/vault/cipher/field.rs | 8 +- .../bitwarden/src/vault/cipher/linked_id.rs | 8 +- crates/bitwarden/src/vault/cipher/mod.rs | 7 +- .../bitwarden/src/vault/cipher/secure_note.rs | 2 +- crates/bitwarden/src/vault/folder.rs | 6 +- crates/bitwarden/src/vault/mod.rs | 7 +- 19 files changed, 1685 insertions(+), 30 deletions(-) create mode 100644 crates/bitwarden-exporters/Cargo.toml create mode 100644 crates/bitwarden-exporters/README.md create mode 100644 crates/bitwarden-exporters/resources/json_export.json create mode 100644 crates/bitwarden-exporters/src/csv.rs create mode 100644 crates/bitwarden-exporters/src/json.rs create mode 100644 crates/bitwarden-exporters/src/lib.rs diff --git a/.prettierignore b/.prettierignore index d5ffe5a0e..97474cca9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,3 +7,6 @@ schemas /crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts about.hbs support/docs/template.hbs + +# Test fixtures +crates/bitwarden-exporters/resources/* diff --git a/.vscode/settings.json b/.vscode/settings.json index 63c3dccaa..e92fcfb76 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,8 +15,10 @@ "Pbkdf", "PKCS8", "repr", + "reprompt", "reqwest", "schemars", + "totp", "uniffi", "wordlist", "zxcvbn" diff --git a/Cargo.lock b/Cargo.lock index 98274e54f..b2728124b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,6 +352,7 @@ dependencies = [ "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", + "bitwarden-exporters", "bitwarden-generators", "chrono", "getrandom 0.2.12", @@ -451,6 +452,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bitwarden-exporters" +version = "0.1.0" +dependencies = [ + "chrono", + "csv", + "serde", + "serde_json", + "thiserror", + "uuid", +] + [[package]] name = "bitwarden-generators" version = "0.1.0" @@ -999,6 +1012,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.2.6" diff --git a/crates/bitwarden-exporters/Cargo.toml b/crates/bitwarden-exporters/Cargo.toml new file mode 100644 index 000000000..0008fbb49 --- /dev/null +++ b/crates/bitwarden-exporters/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "bitwarden-exporters" +version = "0.1.0" +authors = ["Bitwarden Inc"] +license-file = "LICENSE" +repository = "https://github.com/bitwarden/sdk" +homepage = "https://bitwarden.com" +description = """ +Internal crate for the bitwarden crate. Do not use. +""" +keywords = ["bitwarden"] +edition = "2021" +rust-version = "1.57" +exclude = ["/resources"] + +[dependencies] +chrono = { version = ">=0.4.26, <0.5", features = [ + "clock", + "serde", + "std", +], default-features = false } +csv = "1.3.0" +serde = { version = ">=1.0, <2.0", features = ["derive"] } +serde_json = ">=1.0.96, <2.0" +thiserror = ">=1.0.40, <2.0" +uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } diff --git a/crates/bitwarden-exporters/README.md b/crates/bitwarden-exporters/README.md new file mode 100644 index 000000000..59936680f --- /dev/null +++ b/crates/bitwarden-exporters/README.md @@ -0,0 +1,6 @@ +# Bitwarden Exporters + +This is an internal crate for the Bitwarden SDK do not depend on this directly and use the +[`bitwarden`](https://crates.io/crates/bitwarden) crate instead. + +This crate does not follow semantic versioning and the public interface may change at any time. diff --git a/crates/bitwarden-exporters/resources/json_export.json b/crates/bitwarden-exporters/resources/json_export.json new file mode 100644 index 000000000..ad5380550 --- /dev/null +++ b/crates/bitwarden-exporters/resources/json_export.json @@ -0,0 +1,146 @@ +{ + "encrypted": false, + "folders": [ + { + "id": "942e2984-1b9a-453b-b039-b107012713b9", + "name": "Important" + } + ], + "items": [ + { + "id": "25c8c414-b446-48e9-a1bd-b10700bbd740", + "folderId": "942e2984-1b9a-453b-b039-b107012713b9", + "organizationId": null, + "collectionIds": null, + "name": "Bitwarden", + "notes": "My note", + "type": 1, + "login": { + "username": "test@bitwarden.com", + "password": "asdfasdfasdf", + "uris": [ + { + "uri": "https://vault.bitwarden.com", + "match": null + } + ], + "totp": "ABC", + "fido2Credentials": [] + }, + "favorite": true, + "reprompt": 0, + "fields": [ + { + "name": "Text", + "value": "A", + "type": 0, + "linkedId": null + }, + { + "name": "Hidden", + "value": "B", + "type": 1, + "linkedId": null + }, + { + "name": "Boolean (true)", + "value": "true", + "type": 2, + "linkedId": null + }, + { + "name": "Boolean (false)", + "value": "false", + "type": 2, + "linkedId": null + }, + { + "name": "Linked", + "value": null, + "type": 3, + "linkedId": 101 + } + ], + "passwordHistory": null, + "revisionDate": "2024-01-30T14:09:33.753Z", + "creationDate": "2024-01-30T11:23:54.416Z", + "deletedDate": null + }, + { + "id": "23f0f877-42b1-4820-a850-b10700bc41eb", + "folderId": null, + "organizationId": null, + "collectionIds": null, + "name": "My secure note", + "notes": "Very secure!", + "type": 2, + "secureNote": { + "type": 0 + }, + "favorite": false, + "reprompt": 0, + "passwordHistory": null, + "revisionDate": "2024-01-30T11:25:25.466Z", + "creationDate": "2024-01-30T11:25:25.466Z", + "deletedDate": null + }, + { + "id": "3ed8de45-48ee-4e26-a2dc-b10701276c53", + "folderId": null, + "organizationId": null, + "collectionIds": null, + "name": "My card", + "notes": null, + "type": 3, + "card": { + "cardholderName": "John Doe", + "expMonth": "1", + "expYear": "2032", + "code": "123", + "brand": "Visa", + "number": "4111111111111111" + }, + "favorite": false, + "reprompt": 0, + "passwordHistory": null, + "revisionDate": "2024-01-30T17:55:36.150Z", + "creationDate": "2024-01-30T17:55:36.150Z", + "deletedDate": null + }, + { + "id": "41cc3bc1-c3d9-4637-876c-b10701273712", + "folderId": "942e2984-1b9a-453b-b039-b107012713b9", + "organizationId": null, + "collectionIds": null, + "name": "My identity", + "notes": null, + "type": 4, + "identity": { + "title": "Mr", + "firstName": "John", + "middleName": null, + "lastName": "Doe", + "address1": null, + "address2": null, + "address3": null, + "city": null, + "state": null, + "postalCode": null, + "country": null, + "company": "Bitwarden", + "email": null, + "phone": null, + "ssn": null, + "username": "JDoe", + "passportNumber": null, + "licenseNumber": null + }, + "favorite": false, + "reprompt": 0, + "passwordHistory": null, + "revisionDate": "2024-01-30T17:54:50.706Z", + "creationDate": "2024-01-30T17:54:50.706Z", + "deletedDate": null + } + ] +} \ No newline at end of file diff --git a/crates/bitwarden-exporters/src/csv.rs b/crates/bitwarden-exporters/src/csv.rs new file mode 100644 index 000000000..644eeb030 --- /dev/null +++ b/crates/bitwarden-exporters/src/csv.rs @@ -0,0 +1,266 @@ +use std::collections::HashMap; + +use csv::Writer; +use serde::Serializer; +use thiserror::Error; +use uuid::Uuid; + +use crate::{Cipher, CipherType, Field, Folder}; + +#[derive(Debug, Error)] +pub enum CsvError { + #[error("CSV error")] + Csv, +} + +pub(crate) fn export_csv(folders: Vec, ciphers: Vec) -> Result { + let folders: HashMap = folders.into_iter().map(|f| (f.id, f.name)).collect(); + + let rows = ciphers + .into_iter() + .filter(|c| matches!(c.r#type, CipherType::Login(_) | CipherType::SecureNote(_))) + .map(|c| { + let login = if let CipherType::Login(l) = &c.r#type { + Some(l) + } else { + None + }; + + CsvRow { + folder: c + .folder_id + .and_then(|f| folders.get(&f)) + .map(|f| f.to_owned()), + favorite: c.favorite, + r#type: c.r#type.to_string(), + name: c.name.to_owned(), + notes: c.notes.to_owned(), + fields: c.fields, + reprompt: c.reprompt, + login_uri: login + .map(|l| l.login_uris.iter().flat_map(|l| l.uri.clone()).collect()) + .unwrap_or_default(), + login_username: login.and_then(|l| l.username.clone()), + login_password: login.and_then(|l| l.password.clone()), + login_totp: login.and_then(|l| l.totp.clone()), + } + }); + + let mut wtr = Writer::from_writer(vec![]); + for row in rows { + wtr.serialize(row).unwrap(); + } + + String::from_utf8(wtr.into_inner().map_err(|_| CsvError::Csv)?).map_err(|_| CsvError::Csv) +} + +/// CSV export format. See https://bitwarden.com/help/condition-bitwarden-import/#condition-a-csv +/// +/// Be careful when changing this struct to maintain compatibility with old exports. +#[derive(serde::Serialize)] +struct CsvRow { + folder: Option, + #[serde(serialize_with = "bool_serialize")] + favorite: bool, + r#type: String, + name: String, + notes: Option, + #[serde(serialize_with = "fields_serialize")] + fields: Vec, + reprompt: u8, + #[serde(serialize_with = "vec_serialize")] + login_uri: Vec, + login_username: Option, + login_password: Option, + login_totp: Option, +} + +fn vec_serialize(x: &[String], s: S) -> Result +where + S: Serializer, +{ + s.serialize_str(x.join(",").as_str()) +} + +fn bool_serialize(x: &bool, s: S) -> Result +where + S: Serializer, +{ + s.serialize_str(if *x { "1" } else { "" }) +} + +fn fields_serialize(x: &[Field], s: S) -> Result +where + S: Serializer, +{ + s.serialize_str( + x.iter() + .map(|f| { + format!( + "{}: {}", + f.name.to_owned().unwrap_or_default(), + f.value.to_owned().unwrap_or_default() + ) + }) + .collect::>() + .join("\n") + .as_str(), + ) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Card, Identity, Login, LoginUri}; + + #[test] + fn test_export_csv() { + let folders = vec![ + Folder { + id: "d55d65d7-c161-40a4-94ca-b0d20184d91a".parse().unwrap(), + name: "Test Folder A".to_string(), + }, + Folder { + id: "583e7665-0126-4d37-9139-b0d20184dd86".parse().unwrap(), + name: "Test Folder B".to_string(), + }, + ]; + let ciphers = vec![ + Cipher { + id: "d55d65d7-c161-40a4-94ca-b0d20184d91a".parse().unwrap(), + folder_id: None, + name: "test@bitwarden.com".to_string(), + notes: None, + r#type: CipherType::Login(Box::new(Login { + username: Some("test@bitwarden.com".to_string()), + password: Some("Abc123".to_string()), + login_uris: vec![LoginUri { + uri: Some("https://google.com".to_string()), + r#match: None, + }], + totp: None, + })), + favorite: false, + reprompt: 0, + fields: vec![], + revision_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + creation_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "7dd81bd0-cc72-4f42-96e7-b0fc014e71a3".parse().unwrap(), + folder_id: Some("583e7665-0126-4d37-9139-b0d20184dd86".parse().unwrap()), + name: "Steam Account".to_string(), + notes: None, + r#type: CipherType::Login(Box::new(Login { + username: Some("steam".to_string()), + password: Some("3Pvb8u7EfbV*nJ".to_string()), + login_uris: vec![LoginUri { + uri: Some("https://steampowered.com".to_string()), + r#match: None, + }], + totp: Some("steam://ABCD123".to_string()), + })), + favorite: true, + reprompt: 0, + fields: vec![ + Field { + name: Some("Test".to_string()), + value: Some("v".to_string()), + r#type: 0, + linked_id: None, + }, + Field { + name: Some("Hidden".to_string()), + value: Some("asdfer".to_string()), + r#type: 1, + linked_id: None, + }, + ], + revision_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + creation_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + deleted_date: None, + }, + ]; + + let csv = export_csv(folders, ciphers).unwrap(); + let expected = [ + "folder,favorite,type,name,notes,fields,reprompt,login_uri,login_username,login_password,login_totp", + ",,login,test@bitwarden.com,,,0,https://google.com,test@bitwarden.com,Abc123,", + "Test Folder B,1,login,Steam Account,,\"Test: v\nHidden: asdfer\",0,https://steampowered.com,steam,3Pvb8u7EfbV*nJ,steam://ABCD123", + "", + ].join("\n"); + + assert_eq!(csv, expected); + } + + #[test] + fn test_export_ignore_card() { + let folders = vec![]; + let ciphers = vec![Cipher { + id: "d55d65d7-c161-40a4-94ca-b0d20184d91a".parse().unwrap(), + folder_id: None, + name: "My Card".to_string(), + notes: None, + r#type: CipherType::Card(Box::new(Card { + cardholder_name: None, + exp_month: None, + exp_year: None, + code: None, + brand: None, + number: None, + })), + favorite: false, + reprompt: 0, + fields: vec![], + revision_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + creation_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + deleted_date: None, + }]; + + let csv = export_csv(folders, ciphers).unwrap(); + + assert_eq!(csv, ""); + } + + #[test] + fn test_export_ignore_identity() { + let folders = vec![]; + let ciphers = vec![Cipher { + id: "d55d65d7-c161-40a4-94ca-b0d20184d91a".parse().unwrap(), + folder_id: None, + name: "My Identity".to_string(), + notes: None, + r#type: CipherType::Identity(Box::new(Identity { + title: None, + first_name: None, + middle_name: None, + last_name: None, + address1: None, + address2: None, + address3: None, + city: None, + state: None, + postal_code: None, + country: None, + company: None, + email: None, + phone: None, + ssn: None, + username: None, + passport_number: None, + license_number: None, + })), + favorite: false, + reprompt: 0, + fields: vec![], + revision_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + creation_date: "2024-01-30T11:28:20.036Z".parse().unwrap(), + deleted_date: None, + }]; + + let csv = export_csv(folders, ciphers).unwrap(); + + assert_eq!(csv, ""); + } +} diff --git a/crates/bitwarden-exporters/src/json.rs b/crates/bitwarden-exporters/src/json.rs new file mode 100644 index 000000000..3f6c72c1f --- /dev/null +++ b/crates/bitwarden-exporters/src/json.rs @@ -0,0 +1,762 @@ +use chrono::{DateTime, Utc}; +use thiserror::Error; +use uuid::Uuid; + +use crate::{Card, Cipher, CipherType, Field, Folder, Identity, Login, LoginUri, SecureNote}; + +#[derive(Error, Debug)] +pub enum JsonError { + #[error("JSON error: {0}")] + Serde(#[from] serde_json::Error), +} + +pub(crate) fn export_json(folders: Vec, ciphers: Vec) -> Result { + let export = JsonExport { + encrypted: false, + folders: folders.into_iter().map(|f| f.into()).collect(), + items: ciphers.into_iter().map(|c| c.into()).collect(), + }; + + Ok(serde_json::to_string_pretty(&export)?) +} + +/// JSON export format. These are intentionally decoupled from the internal data structures to +/// ensure internal changes are not reflected in the public exports. +/// +/// Be careful about changing these structs to maintain compatibility with old exporters/importers. +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonExport { + encrypted: bool, + folders: Vec, + items: Vec, +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonFolder { + id: Uuid, + name: String, +} + +impl From for JsonFolder { + fn from(folder: Folder) -> Self { + JsonFolder { + id: folder.id, + name: folder.name, + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonCipher { + id: Uuid, + folder_id: Option, + // Organizational IDs which are always empty in personal exports + organization_id: Option, + collection_ids: Option>, + + name: String, + notes: Option, + + r#type: u8, + #[serde(skip_serializing_if = "Option::is_none")] + login: Option, + #[serde(skip_serializing_if = "Option::is_none")] + identity: Option, + #[serde(skip_serializing_if = "Option::is_none")] + card: Option, + #[serde(skip_serializing_if = "Option::is_none")] + secure_note: Option, + + favorite: bool, + reprompt: u8, + + #[serde(skip_serializing_if = "Vec::is_empty")] + fields: Vec, + password_history: Option>, + + revision_date: DateTime, + creation_date: DateTime, + deleted_date: Option>, +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonLogin { + username: Option, + password: Option, + uris: Vec, + totp: Option, + fido2_credentials: Vec, +} + +impl From for JsonLogin { + fn from(login: Login) -> Self { + JsonLogin { + username: login.username, + password: login.password, + uris: login.login_uris.into_iter().map(|u| u.into()).collect(), + totp: login.totp, + fido2_credentials: vec![], + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonLoginUri { + uri: Option, + r#match: Option, +} + +impl From for JsonLoginUri { + fn from(login_uri: LoginUri) -> Self { + JsonLoginUri { + uri: login_uri.uri, + r#match: login_uri.r#match, + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonSecureNote { + r#type: u8, +} + +impl From for JsonSecureNote { + fn from(note: SecureNote) -> Self { + JsonSecureNote { + r#type: note.r#type as u8, + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonCard { + cardholder_name: Option, + exp_month: Option, + exp_year: Option, + code: Option, + brand: Option, + number: Option, +} + +impl From for JsonCard { + fn from(card: Card) -> Self { + JsonCard { + cardholder_name: card.cardholder_name, + exp_month: card.exp_month, + exp_year: card.exp_year, + code: card.code, + brand: card.brand, + number: card.number, + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonIdentity { + title: Option, + first_name: Option, + middle_name: Option, + last_name: Option, + address1: Option, + address2: Option, + address3: Option, + city: Option, + state: Option, + postal_code: Option, + country: Option, + company: Option, + email: Option, + phone: Option, + ssn: Option, + username: Option, + passport_number: Option, + license_number: Option, +} + +impl From for JsonIdentity { + fn from(identity: Identity) -> Self { + JsonIdentity { + title: identity.title, + first_name: identity.first_name, + middle_name: identity.middle_name, + last_name: identity.last_name, + address1: identity.address1, + address2: identity.address2, + address3: identity.address3, + city: identity.city, + state: identity.state, + postal_code: identity.postal_code, + country: identity.country, + company: identity.company, + email: identity.email, + phone: identity.phone, + ssn: identity.ssn, + username: identity.username, + passport_number: identity.passport_number, + license_number: identity.license_number, + } + } +} + +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonField { + name: Option, + value: Option, + r#type: u8, + linked_id: Option, +} + +impl From for JsonField { + fn from(field: Field) -> Self { + JsonField { + name: field.name, + value: field.value, + r#type: field.r#type, + linked_id: field.linked_id, + } + } +} + +impl From for JsonCipher { + fn from(cipher: Cipher) -> Self { + let r#type = match cipher.r#type { + CipherType::Login(_) => 1, + CipherType::SecureNote(_) => 2, + CipherType::Card(_) => 3, + CipherType::Identity(_) => 4, + }; + + let (login, secure_note, card, identity) = match cipher.r#type { + CipherType::Login(l) => (Some((*l).into()), None, None, None), + CipherType::SecureNote(s) => (None, Some((*s).into()), None, None), + CipherType::Card(c) => (None, None, Some((*c).into()), None), + CipherType::Identity(i) => (None, None, None, Some((*i).into())), + }; + + JsonCipher { + id: cipher.id, + folder_id: cipher.folder_id, + organization_id: None, + collection_ids: None, + name: cipher.name, + notes: cipher.notes, + r#type, + login, + identity, + card, + secure_note, + favorite: cipher.favorite, + reprompt: cipher.reprompt, + fields: cipher.fields.into_iter().map(|f| f.into()).collect(), + password_history: None, + revision_date: cipher.revision_date, + creation_date: cipher.creation_date, + deleted_date: cipher.deleted_date, + } + } +} + +#[cfg(test)] +mod tests { + use std::{fs, io::Read, path::PathBuf}; + + use super::*; + use crate::{Cipher, Field, LoginUri, SecureNoteType}; + + #[test] + fn test_convert_login() { + let cipher = Cipher { + id: "25c8c414-b446-48e9-a1bd-b10700bbd740".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "Bitwarden".to_string(), + notes: Some("My note".to_string()), + + r#type: CipherType::Login(Box::new(Login { + username: Some("test@bitwarden.com".to_string()), + password: Some("asdfasdfasdf".to_string()), + login_uris: vec![LoginUri { + uri: Some("https://vault.bitwarden.com".to_string()), + r#match: None, + }], + totp: Some("ABC".to_string()), + })), + + favorite: true, + reprompt: 0, + + fields: vec![ + Field { + name: Some("Text".to_string()), + value: Some("A".to_string()), + r#type: 0, + linked_id: None, + }, + Field { + name: Some("Hidden".to_string()), + value: Some("B".to_string()), + r#type: 1, + linked_id: None, + }, + Field { + name: Some("Boolean (true)".to_string()), + value: Some("true".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Boolean (false)".to_string()), + value: Some("false".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Linked".to_string()), + value: None, + r#type: 3, + linked_id: Some(101), + }, + ], + + revision_date: "2024-01-30T14:09:33.753Z".parse().unwrap(), + creation_date: "2024-01-30T11:23:54.416Z".parse().unwrap(), + deleted_date: None, + }; + + let json = serde_json::to_string(&JsonCipher::from(cipher)).unwrap(); + + let expected = r#"{ + "passwordHistory": null, + "revisionDate": "2024-01-30T14:09:33.753Z", + "creationDate": "2024-01-30T11:23:54.416Z", + "deletedDate": null, + "id": "25c8c414-b446-48e9-a1bd-b10700bbd740", + "organizationId": null, + "folderId": "942e2984-1b9a-453b-b039-b107012713b9", + "type": 1, + "reprompt": 0, + "name": "Bitwarden", + "notes": "My note", + "favorite": true, + "fields": [ + { + "name": "Text", + "value": "A", + "type": 0, + "linkedId": null + }, + { + "name": "Hidden", + "value": "B", + "type": 1, + "linkedId": null + }, + { + "name": "Boolean (true)", + "value": "true", + "type": 2, + "linkedId": null + }, + { + "name": "Boolean (false)", + "value": "false", + "type": 2, + "linkedId": null + }, + { + "name": "Linked", + "value": null, + "type": 3, + "linkedId": 101 + } + ], + "login": { + "fido2Credentials": [], + "uris": [ + { + "match": null, + "uri": "https://vault.bitwarden.com" + } + ], + "username": "test@bitwarden.com", + "password": "asdfasdfasdf", + "totp": "ABC" + }, + "collectionIds": null + }"#; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ) + } + + #[test] + fn test_convert_secure_note() { + let cipher = Cipher { + id: "23f0f877-42b1-4820-a850-b10700bc41eb".parse().unwrap(), + folder_id: None, + + name: "My secure note".to_string(), + notes: Some("Very secure!".to_string()), + + r#type: CipherType::SecureNote(Box::new(SecureNote { + r#type: SecureNoteType::Generic, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + creation_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + deleted_date: None, + }; + + let json = serde_json::to_string(&JsonCipher::from(cipher)).unwrap(); + + let expected = r#"{ + "passwordHistory": null, + "revisionDate": "2024-01-30T11:25:25.466Z", + "creationDate": "2024-01-30T11:25:25.466Z", + "deletedDate": null, + "id": "23f0f877-42b1-4820-a850-b10700bc41eb", + "organizationId": null, + "folderId": null, + "type": 2, + "reprompt": 0, + "name": "My secure note", + "notes": "Very secure!", + "favorite": false, + "secureNote": { + "type": 0 + }, + "collectionIds": null + }"#; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ) + } + + #[test] + fn test_convert_card() { + let cipher = Cipher { + id: "3ed8de45-48ee-4e26-a2dc-b10701276c53".parse().unwrap(), + folder_id: None, + + name: "My card".to_string(), + notes: None, + + r#type: CipherType::Card(Box::new(Card { + cardholder_name: Some("John Doe".to_string()), + exp_month: Some("1".to_string()), + exp_year: Some("2032".to_string()), + code: Some("123".to_string()), + brand: Some("Visa".to_string()), + number: Some("4111111111111111".to_string()), + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + }; + + let json = serde_json::to_string(&JsonCipher::from(cipher)).unwrap(); + + let expected = r#"{ + "passwordHistory": null, + "revisionDate": "2024-01-30T17:55:36.150Z", + "creationDate": "2024-01-30T17:55:36.150Z", + "deletedDate": null, + "id": "3ed8de45-48ee-4e26-a2dc-b10701276c53", + "organizationId": null, + "folderId": null, + "type": 3, + "reprompt": 0, + "name": "My card", + "notes": null, + "favorite": false, + "card": { + "cardholderName": "John Doe", + "brand": "Visa", + "number": "4111111111111111", + "expMonth": "1", + "expYear": "2032", + "code": "123" + }, + "collectionIds": null + }"#; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ) + } + + #[test] + fn test_convert_identity() { + let cipher = Cipher { + id: "41cc3bc1-c3d9-4637-876c-b10701273712".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "My identity".to_string(), + notes: None, + + r#type: CipherType::Identity(Box::new(Identity { + title: Some("Mr".to_string()), + first_name: Some("John".to_string()), + middle_name: None, + last_name: Some("Doe".to_string()), + address1: None, + address2: None, + address3: None, + city: None, + state: None, + postal_code: None, + country: None, + company: Some("Bitwarden".to_string()), + email: None, + phone: None, + ssn: None, + username: Some("JDoe".to_string()), + passport_number: None, + license_number: None, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + creation_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + deleted_date: None, + }; + + let json = serde_json::to_string(&JsonCipher::from(cipher)).unwrap(); + + let expected = r#"{ + "passwordHistory": null, + "revisionDate": "2024-01-30T17:54:50.706Z", + "creationDate": "2024-01-30T17:54:50.706Z", + "deletedDate": null, + "id": "41cc3bc1-c3d9-4637-876c-b10701273712", + "organizationId": null, + "folderId": "942e2984-1b9a-453b-b039-b107012713b9", + "type": 4, + "reprompt": 0, + "name": "My identity", + "notes": null, + "favorite": false, + "identity": { + "title": "Mr", + "firstName": "John", + "middleName": null, + "lastName": "Doe", + "address1": null, + "address2": null, + "address3": null, + "city": null, + "state": null, + "postalCode": null, + "country": null, + "company": "Bitwarden", + "email": null, + "phone": null, + "ssn": null, + "username": "JDoe", + "passportNumber": null, + "licenseNumber": null + }, + "collectionIds": null + }"#; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ) + } + + #[test] + pub fn test_export() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("resources"); + d.push("json_export.json"); + + let mut file = fs::File::open(d).unwrap(); + + let mut expected = String::new(); + file.read_to_string(&mut expected).unwrap(); + + let export = export_json( + vec![Folder { + id: "942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap(), + name: "Important".to_string(), + }], + vec![ + Cipher { + id: "25c8c414-b446-48e9-a1bd-b10700bbd740".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "Bitwarden".to_string(), + notes: Some("My note".to_string()), + + r#type: CipherType::Login(Box::new(Login { + username: Some("test@bitwarden.com".to_string()), + password: Some("asdfasdfasdf".to_string()), + login_uris: vec![LoginUri { + uri: Some("https://vault.bitwarden.com".to_string()), + r#match: None, + }], + totp: Some("ABC".to_string()), + })), + + favorite: true, + reprompt: 0, + + fields: vec![ + Field { + name: Some("Text".to_string()), + value: Some("A".to_string()), + r#type: 0, + linked_id: None, + }, + Field { + name: Some("Hidden".to_string()), + value: Some("B".to_string()), + r#type: 1, + linked_id: None, + }, + Field { + name: Some("Boolean (true)".to_string()), + value: Some("true".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Boolean (false)".to_string()), + value: Some("false".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Linked".to_string()), + value: None, + r#type: 3, + linked_id: Some(101), + }, + ], + + revision_date: "2024-01-30T14:09:33.753Z".parse().unwrap(), + creation_date: "2024-01-30T11:23:54.416Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "23f0f877-42b1-4820-a850-b10700bc41eb".parse().unwrap(), + folder_id: None, + + name: "My secure note".to_string(), + notes: Some("Very secure!".to_string()), + + r#type: CipherType::SecureNote(Box::new(SecureNote { + r#type: SecureNoteType::Generic, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + creation_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "3ed8de45-48ee-4e26-a2dc-b10701276c53".parse().unwrap(), + folder_id: None, + + name: "My card".to_string(), + notes: None, + + r#type: CipherType::Card(Box::new(Card { + cardholder_name: Some("John Doe".to_string()), + exp_month: Some("1".to_string()), + exp_year: Some("2032".to_string()), + code: Some("123".to_string()), + brand: Some("Visa".to_string()), + number: Some("4111111111111111".to_string()), + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "41cc3bc1-c3d9-4637-876c-b10701273712".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "My identity".to_string(), + notes: None, + + r#type: CipherType::Identity(Box::new(Identity { + title: Some("Mr".to_string()), + first_name: Some("John".to_string()), + middle_name: None, + last_name: Some("Doe".to_string()), + address1: None, + address2: None, + address3: None, + city: None, + state: None, + postal_code: None, + country: None, + company: Some("Bitwarden".to_string()), + email: None, + phone: None, + ssn: None, + username: Some("JDoe".to_string()), + passport_number: None, + license_number: None, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + creation_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + deleted_date: None, + }, + ], + ) + .unwrap(); + + assert_eq!( + export.parse::().unwrap(), + expected.parse::().unwrap() + ) + } +} diff --git a/crates/bitwarden-exporters/src/lib.rs b/crates/bitwarden-exporters/src/lib.rs new file mode 100644 index 000000000..bb690fbc1 --- /dev/null +++ b/crates/bitwarden-exporters/src/lib.rs @@ -0,0 +1,142 @@ +use chrono::{DateTime, Utc}; +use thiserror::Error; +use uuid::Uuid; + +mod csv; +use csv::export_csv; +mod json; +use json::export_json; + +pub enum Format { + Csv, + Json, + EncryptedJson { password: String }, +} + +/// Export representation of a Bitwarden folder. +/// +/// These are mostly duplicated from the `bitwarden` vault models to facilitate a stable export API +/// that is not tied to the internal vault models. We may revisit this in the future. +pub struct Folder { + pub id: Uuid, + pub name: String, +} + +/// Export representation of a Bitwarden cipher. +/// +/// These are mostly duplicated from the `bitwarden` vault models to facilitate a stable export API +/// that is not tied to the internal vault models. We may revisit this in the future. +pub struct Cipher { + pub id: Uuid, + pub folder_id: Option, + + pub name: String, + pub notes: Option, + + pub r#type: CipherType, + + pub favorite: bool, + pub reprompt: u8, + + pub fields: Vec, + + pub revision_date: DateTime, + pub creation_date: DateTime, + pub deleted_date: Option>, +} + +#[derive(Clone)] +pub struct Field { + pub name: Option, + pub value: Option, + pub r#type: u8, + pub linked_id: Option, +} + +pub enum CipherType { + Login(Box), + SecureNote(Box), + Card(Box), + Identity(Box), +} + +impl ToString for CipherType { + fn to_string(&self) -> String { + match self { + CipherType::Login(_) => "login".to_string(), + CipherType::SecureNote(_) => "note".to_string(), + CipherType::Card(_) => "card".to_string(), + CipherType::Identity(_) => "identity".to_string(), + } + } +} + +pub struct Login { + pub username: Option, + pub password: Option, + pub login_uris: Vec, + pub totp: Option, +} + +pub struct LoginUri { + pub uri: Option, + pub r#match: Option, +} + +pub struct Card { + pub cardholder_name: Option, + pub exp_month: Option, + pub exp_year: Option, + pub code: Option, + pub brand: Option, + pub number: Option, +} + +pub struct SecureNote { + pub r#type: SecureNoteType, +} + +pub enum SecureNoteType { + Generic = 0, +} + +pub struct Identity { + pub title: Option, + pub first_name: Option, + pub middle_name: Option, + pub last_name: Option, + pub address1: Option, + pub address2: Option, + pub address3: Option, + pub city: Option, + pub state: Option, + pub postal_code: Option, + pub country: Option, + pub company: Option, + pub email: Option, + pub phone: Option, + pub ssn: Option, + pub username: Option, + pub passport_number: Option, + pub license_number: Option, +} + +#[derive(Error, Debug)] +pub enum ExportError { + #[error("CSV error: {0}")] + Csv(#[from] csv::CsvError), + #[error("JSON error: {0}")] + Json(#[from] json::JsonError), +} + +pub fn export( + folders: Vec, + ciphers: Vec, + format: Format, +) -> Result { + match format { + Format::Csv => Ok(export_csv(folders, ciphers)?), + Format::Json => Ok(export_json(folders, ciphers)?), + Format::EncryptedJson { password: _ } => todo!(), + } +} diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index d9508258b..c6f580282 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -31,6 +31,7 @@ base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-exporters = { path = "../bitwarden-exporters", version = "0.1.0" } bitwarden-generators = { path = "../bitwarden-generators", version = "0.1.0" } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 173557b04..ed5d27c3e 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -4,6 +4,7 @@ use std::{borrow::Cow, fmt::Debug}; use bitwarden_api_api::apis::Error as ApiError; use bitwarden_api_identity::apis::Error as IdentityError; +use bitwarden_exporters::ExportError; use bitwarden_generators::{PassphraseError, PasswordError, UsernameError}; use reqwest::StatusCode; use thiserror::Error; @@ -50,6 +51,7 @@ pub enum Error { #[error("The state file could not be read")] InvalidStateFile, + // Generators #[error(transparent)] UsernameError(#[from] UsernameError), #[error(transparent)] @@ -57,6 +59,9 @@ pub enum Error { #[error(transparent)] PasswordError(#[from] PasswordError), + #[error(transparent)] + ExportError(#[from] ExportError), + #[error("Internal error: {0}")] Internal(Cow<'static, str>), } diff --git a/crates/bitwarden/src/tool/exporters/client_exporter.rs b/crates/bitwarden/src/tool/exporters/client_exporter.rs index 9e0dfd5fc..05eb737f3 100644 --- a/crates/bitwarden/src/tool/exporters/client_exporter.rs +++ b/crates/bitwarden/src/tool/exporters/client_exporter.rs @@ -6,7 +6,7 @@ use crate::{ }; pub struct ClientExporters<'a> { - pub(crate) _client: &'a crate::Client, + pub(crate) client: &'a crate::Client, } impl<'a> ClientExporters<'a> { @@ -17,7 +17,7 @@ impl<'a> ClientExporters<'a> { ciphers: Vec, format: ExportFormat, ) -> Result { - export_vault(folders, ciphers, format) + export_vault(self.client, folders, ciphers, format) } pub async fn export_organization_vault( @@ -32,6 +32,6 @@ impl<'a> ClientExporters<'a> { impl<'a> Client { pub fn exporters(&'a self) -> ClientExporters<'a> { - ClientExporters { _client: self } + ClientExporters { client: self } } } diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index d03ddeb77..cbdb5bb86 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -1,8 +1,14 @@ +use bitwarden_crypto::Decryptable; +use bitwarden_exporters::export; use schemars::JsonSchema; use crate::{ - error::Result, - vault::{Cipher, Collection, Folder}, + error::{Error, Result}, + vault::{ + login::LoginUriView, Cipher, CipherType, CipherView, Collection, FieldView, Folder, + FolderView, SecureNoteType, + }, + Client, }; mod client_exporter; @@ -13,21 +19,26 @@ pub use client_exporter::ClientExporters; pub enum ExportFormat { Csv, Json, - AccountEncryptedJson, // TODO: Should we deprecate this option completely? EncryptedJson { password: String }, } pub(super) fn export_vault( - _folders: Vec, - _ciphers: Vec, + client: &Client, + folders: Vec, + ciphers: Vec, format: ExportFormat, ) -> Result { - Ok(match format { - ExportFormat::Csv => "Csv".to_owned(), - ExportFormat::Json => "Json".to_owned(), - ExportFormat::AccountEncryptedJson => "AccountEncryptedJson".to_owned(), - ExportFormat::EncryptedJson { .. } => "EncryptedJson".to_owned(), - }) + let enc = client.get_encryption_settings()?; + + let folders: Vec = folders.decrypt(enc, &None)?; + let folders: Vec = + folders.into_iter().flat_map(|f| f.try_into()).collect(); + + let ciphers: Vec = ciphers.decrypt(enc, &None)?; + let ciphers: Vec = + ciphers.into_iter().flat_map(|c| c.try_into()).collect(); + + Ok(export(folders, ciphers, format.into())?) } pub(super) fn export_organization_vault( @@ -37,3 +48,248 @@ pub(super) fn export_organization_vault( ) -> Result { todo!(); } + +impl TryFrom for bitwarden_exporters::Folder { + type Error = Error; + + fn try_from(value: FolderView) -> Result { + Ok(Self { + id: value.id.ok_or(Error::MissingFields)?, + name: value.name, + }) + } +} + +impl TryFrom for bitwarden_exporters::Cipher { + type Error = Error; + + fn try_from(value: CipherView) -> Result { + let r = match value.r#type { + CipherType::Login => { + let l = value.login.ok_or(Error::MissingFields)?; + bitwarden_exporters::CipherType::Login(Box::new(bitwarden_exporters::Login { + username: l.username, + password: l.password, + login_uris: l + .uris + .unwrap_or_default() + .into_iter() + .map(|u| u.into()) + .collect(), + totp: l.totp, + })) + } + CipherType::SecureNote => bitwarden_exporters::CipherType::SecureNote(Box::new( + bitwarden_exporters::SecureNote { + r#type: value + .secure_note + .map(|t| t.r#type) + .unwrap_or(SecureNoteType::Generic) + .into(), + }, + )), + CipherType::Card => { + let c = value.card.ok_or(Error::MissingFields)?; + bitwarden_exporters::CipherType::Card(Box::new(bitwarden_exporters::Card { + cardholder_name: c.cardholder_name, + exp_month: c.exp_month, + exp_year: c.exp_year, + code: c.code, + brand: c.brand, + number: c.number, + })) + } + CipherType::Identity => { + let i = value.identity.ok_or(Error::MissingFields)?; + bitwarden_exporters::CipherType::Identity(Box::new(bitwarden_exporters::Identity { + title: i.title, + first_name: i.first_name, + middle_name: i.middle_name, + last_name: i.last_name, + address1: i.address1, + address2: i.address2, + address3: i.address3, + city: i.city, + state: i.state, + postal_code: i.postal_code, + country: i.country, + company: i.company, + email: i.email, + phone: i.phone, + ssn: i.ssn, + username: i.username, + passport_number: i.passport_number, + license_number: i.license_number, + })) + } + }; + + Ok(Self { + id: value.id.ok_or(Error::MissingFields)?, + folder_id: value.folder_id, + name: value.name, + notes: value.notes, + r#type: r, + favorite: value.favorite, + reprompt: value.reprompt as u8, + fields: value + .fields + .unwrap_or_default() + .into_iter() + .map(|f| f.into()) + .collect(), + revision_date: value.revision_date, + creation_date: value.creation_date, + deleted_date: value.deleted_date, + }) + } +} + +impl From for bitwarden_exporters::Field { + fn from(value: FieldView) -> Self { + Self { + name: value.name, + value: value.value, + r#type: value.r#type as u8, + linked_id: value.linked_id.map(|id| id.into()), + } + } +} + +impl From for bitwarden_exporters::LoginUri { + fn from(value: LoginUriView) -> Self { + Self { + r#match: value.r#match.map(|v| v as u8), + uri: value.uri, + } + } +} + +impl From for bitwarden_exporters::SecureNoteType { + fn from(value: SecureNoteType) -> Self { + match value { + SecureNoteType::Generic => bitwarden_exporters::SecureNoteType::Generic, + } + } +} + +impl From for bitwarden_exporters::Format { + fn from(value: ExportFormat) -> Self { + match value { + ExportFormat::Csv => Self::Csv, + ExportFormat::Json => Self::Json, + ExportFormat::EncryptedJson { password } => Self::EncryptedJson { password }, + } + } +} + +#[cfg(test)] +mod tests { + use chrono::{DateTime, Utc}; + + use super::*; + use crate::vault::{login::LoginView, CipherRepromptType}; + + #[test] + fn test_try_from_folder_view() { + let view = FolderView { + id: Some("fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap()), + name: "test_name".to_string(), + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + }; + + let f: bitwarden_exporters::Folder = view.try_into().unwrap(); + + assert_eq!( + f.id, + "fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap() + ); + assert_eq!(f.name, "test_name".to_string()); + } + + #[test] + fn test_try_from_cipher_view_login() { + let cipher_view = CipherView { + r#type: CipherType::Login, + login: Some(LoginView { + username: Some("test_username".to_string()), + password: Some("test_password".to_string()), + password_revision_date: None, + uris: None, + totp: None, + autofill_on_page_load: None, + }), + id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), + organization_id: None, + folder_id: None, + collection_ids: vec![], + key: None, + name: "My login".to_string(), + notes: None, + identity: None, + card: None, + secure_note: None, + favorite: false, + reprompt: CipherRepromptType::None, + organization_use_totp: true, + edit: true, + view_password: true, + local_data: None, + attachments: None, + fields: None, + password_history: None, + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + }; + + let cipher: bitwarden_exporters::Cipher = cipher_view.try_into().unwrap(); + + assert_eq!( + cipher.id, + "fd411a1a-fec8-4070-985d-0e6560860e69".parse().unwrap() + ); + assert_eq!(cipher.folder_id, None); + assert_eq!(cipher.name, "My login".to_string()); + assert_eq!(cipher.notes, None); + assert!(!cipher.favorite); + assert_eq!(cipher.reprompt, 0); + assert!(cipher.fields.is_empty()); + assert_eq!( + cipher.revision_date, + "2024-01-30T17:55:36.150Z".parse::>().unwrap() + ); + assert_eq!( + cipher.creation_date, + "2024-01-30T17:55:36.150Z".parse::>().unwrap() + ); + assert_eq!(cipher.deleted_date, None); + + if let bitwarden_exporters::CipherType::Login(l) = cipher.r#type { + assert_eq!(l.username, Some("test_username".to_string())); + assert_eq!(l.password, Some("test_password".to_string())); + assert!(l.login_uris.is_empty()); + assert_eq!(l.totp, None); + } else { + panic!("Expected login type"); + } + } + + #[test] + fn test_from_export_format() { + assert!(matches!( + bitwarden_exporters::Format::from(ExportFormat::Csv), + bitwarden_exporters::Format::Csv + )); + assert!(matches!( + bitwarden_exporters::Format::from(ExportFormat::Json), + bitwarden_exporters::Format::Json + )); + assert!(matches!( + bitwarden_exporters::Format::from(ExportFormat::EncryptedJson { + password: "password".to_string() + }), + bitwarden_exporters::Format::EncryptedJson { .. } + )); + } +} diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index db896474f..bde713a05 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -34,11 +34,11 @@ pub struct Field { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct FieldView { - name: Option, - value: Option, - r#type: FieldType, + pub(crate) name: Option, + pub(crate) value: Option, + pub(crate) r#type: FieldType, - linked_id: Option, + pub(crate) linked_id: Option, } impl KeyEncryptable for FieldView { diff --git a/crates/bitwarden/src/vault/cipher/linked_id.rs b/crates/bitwarden/src/vault/cipher/linked_id.rs index 6fb676dfe..77429438e 100644 --- a/crates/bitwarden/src/vault/cipher/linked_id.rs +++ b/crates/bitwarden/src/vault/cipher/linked_id.rs @@ -25,7 +25,13 @@ impl UniffiCustomTypeConverter for LinkedIdType { } fn from_custom(obj: Self) -> Self::Builtin { - serde_json::to_value(obj) + obj.into() + } +} + +impl From for u32 { + fn from(v: LinkedIdType) -> Self { + serde_json::to_value(v) .expect("LinkedIdType should be serializable") .as_u64() .expect("Not a numeric enum value") as u32 diff --git a/crates/bitwarden/src/vault/cipher/mod.rs b/crates/bitwarden/src/vault/cipher/mod.rs index c891f439d..c2b49eb37 100644 --- a/crates/bitwarden/src/vault/cipher/mod.rs +++ b/crates/bitwarden/src/vault/cipher/mod.rs @@ -9,4 +9,9 @@ pub(crate) mod local_data; pub(crate) mod login; pub(crate) mod secure_note; -pub use cipher::{Cipher, CipherListView, CipherView}; +pub use attachment::{ + Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView, +}; +pub use cipher::{Cipher, CipherListView, CipherRepromptType, CipherType, CipherView}; +pub use field::FieldView; +pub use secure_note::SecureNoteType; diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 8f7069ee1..2433a9c2a 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -24,7 +24,7 @@ pub struct SecureNote { #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct SecureNoteView { - r#type: SecureNoteType, + pub(crate) r#type: SecureNoteType, } impl KeyEncryptable for SecureNoteView { diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 17d1d40aa..edd1cac42 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -22,9 +22,9 @@ pub struct Folder { #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct FolderView { - id: Option, - name: String, - revision_date: DateTime, + pub id: Option, + pub name: String, + pub revision_date: DateTime, } impl LocateKey for FolderView {} diff --git a/crates/bitwarden/src/vault/mod.rs b/crates/bitwarden/src/vault/mod.rs index dce7b0e04..2addfec6b 100644 --- a/crates/bitwarden/src/vault/mod.rs +++ b/crates/bitwarden/src/vault/mod.rs @@ -6,12 +6,7 @@ mod send; #[cfg(feature = "mobile")] mod totp; -pub use cipher::{ - attachment::{ - Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView, - }, - Cipher, CipherListView, CipherView, -}; +pub use cipher::*; pub use collection::{Collection, CollectionView}; pub use folder::{Folder, FolderView}; pub use password_history::{PasswordHistory, PasswordHistoryView}; From 1595306d0f80807983c374aaebc4938a835be78c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 6 Feb 2024 18:02:33 +0100 Subject: [PATCH 265/378] [DEVOPS-1711] Add Docker image for bws versioning for release workflow (#573) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add docker publish to `release-cli.yml` workflow. ## Code changes - **.github/workflows/release-cli.yml:** Add docker publish job to `release-cli.yml` workflow. - **.github/workflows/build-cli-docker.yml** Remove unused input. Publish docker only if building for publish branch ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> --- .github/workflows/build-cli-docker.yml | 7 +-- .github/workflows/release-cli.yml | 85 ++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index c0aa62664..5cee3899b 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -6,11 +6,6 @@ on: paths: - "crates/bws/**" workflow_dispatch: - inputs: - sdk_branch: - description: "Server branch name to deploy (examples: 'master', 'rc', 'feature/sm')" - type: string - default: master pull_request: paths: - ".github/workflows/build-cli-docker.yml" @@ -111,7 +106,7 @@ jobs: platforms: | linux/amd64, linux/arm64/v8 - push: true + push: ${{ env.is_publish_branch }} tags: ${{ steps.tag-list.outputs.tags }} secrets: | "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index a6059a1d5..fa1ffc346 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -8,17 +8,19 @@ on: release_type: description: "Release Options" required: true - default: "Initial Release" + default: "Release" type: choice options: - - Initial Release - - Redeploy + - Release - Dry Run defaults: run: shell: bash +env: + _AZ_REGISTRY: bitwardenprod.azurecr.io + jobs: setup: name: Setup @@ -120,7 +122,7 @@ jobs: publish: name: Publish bws to crates.io - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: - setup steps: @@ -156,3 +158,78 @@ jobs: PUBLISH_GRACE_SLEEP: 10 CARGO_REGISTRY_TOKEN: ${{ steps.retrieve-secrets.outputs.cratesio-api-token }} run: cargo-release release publish -p bws --execute --no-confirm + + publish-docker: + name: Publish docker versioned and latest image + runs-on: ubuntu-22.04 + needs: setup + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Generate tag list + id: tag-list + env: + VERSION: ${{ needs.setup.outputs.release-version }} + DRY_RUN: ${{ inputs.release_type == 'Dry Run' }} + run: | + if [[ "${DRY_RUN}" == "true" ]]; then + REF=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}} + IMAGE_TAG=$(echo "${REF}" | sed "s#/#-#g") # slash safe branch name + echo "tags=$_AZ_REGISTRY/bws:${IMAGE_TAG},bitwarden/bws:${IMAGE_TAG}" >> $GITHUB_OUTPUT + else + echo "tags=$_AZ_REGISTRY/bws:${VERSION},bitwarden/bws:${VERSION},$_AZ_REGISTRY/bws:latest,bitwarden/bws:latest" >> $GITHUB_OUTPUT + fi + + ########## Set up Docker ########## + - name: Set up QEMU emulators + uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + + ########## Login to Docker registries ########## + - name: Login to Azure - Prod Subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Login to Azure ACR + run: az acr login -n ${_AZ_REGISTRY%.azurecr.io} + + - name: Login to Azure - CI Subscription + uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve github PAT secrets + id: retrieve-secret-pat + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: "bitwarden-ci" + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Setup Docker Trust + uses: bitwarden/gh-actions/setup-docker-trust@main + with: + azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + azure-keyvault-name: "bitwarden-ci" + + - name: Build and push Docker image + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 + with: + context: . + file: crates/bws/Dockerfile + platforms: | + linux/amd64, + linux/arm64/v8 + push: ${{ inputs.release_type != 'Dry Run' }} + tags: ${{ steps.tag-list.outputs.tags }} + secrets: | + "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" + + - name: Log out of Docker and disable Docker Notary + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + docker logout + echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV From 400a1739aafe8368d9de9e25319b81f0bcacf98c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 10:54:29 +0100 Subject: [PATCH 266/378] [PM-6104] Add locking support to bitwarden-json to improve bindings thread safety (#591) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective I've added the lock into bitwarden-json because we already do locking in bitwarden-wasm and this way we can remove it from there. --- Cargo.lock | 1 + crates/bitwarden-c/src/c.rs | 2 +- crates/bitwarden-c/src/macros/ffi.rs | 2 +- crates/bitwarden-json/Cargo.toml | 1 + crates/bitwarden-json/src/client.rs | 43 +++++++++++++++------------- crates/bitwarden-napi/src/client.rs | 2 +- crates/bitwarden-py/src/client.rs | 6 ++-- crates/bitwarden-wasm/src/client.rs | 18 ++++-------- 8 files changed, 37 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2728124b..c4b8d76d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -485,6 +485,7 @@ dependencies = [ name = "bitwarden-json" version = "0.3.0" dependencies = [ + "async-lock", "bitwarden", "log", "schemars", diff --git a/crates/bitwarden-c/src/c.rs b/crates/bitwarden-c/src/c.rs index f9ac57f30..934b20359 100644 --- a/crates/bitwarden-c/src/c.rs +++ b/crates/bitwarden-c/src/c.rs @@ -8,7 +8,7 @@ use crate::{box_ptr, ffi_ref}; #[tokio::main] pub async extern "C" fn run_command( c_str_ptr: *const c_char, - client_ptr: *mut Client, + client_ptr: *const Client, ) -> *mut c_char { let client = unsafe { ffi_ref!(client_ptr) }; let input_str = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr).to_bytes() }).unwrap(); diff --git a/crates/bitwarden-c/src/macros/ffi.rs b/crates/bitwarden-c/src/macros/ffi.rs index 3325838d1..d7384cd48 100644 --- a/crates/bitwarden-c/src/macros/ffi.rs +++ b/crates/bitwarden-c/src/macros/ffi.rs @@ -3,7 +3,7 @@ macro_rules! ffi_ref { ($name:ident) => {{ assert!(!$name.is_null()); - &mut *$name + &*$name }}; } diff --git a/crates/bitwarden-json/Cargo.toml b/crates/bitwarden-json/Cargo.toml index f7c0fd58d..1e0473c44 100644 --- a/crates/bitwarden-json/Cargo.toml +++ b/crates/bitwarden-json/Cargo.toml @@ -18,6 +18,7 @@ internal = ["bitwarden/internal"] # Internal testing methods secrets = ["bitwarden/secrets"] # Secrets manager API [dependencies] +async-lock = ">=3.3.0, <4.0" log = ">=0.4.18, <0.5" schemars = ">=0.8.12, <0.9" serde = { version = ">=1.0, <2.0", features = ["derive"] } diff --git a/crates/bitwarden-json/src/client.rs b/crates/bitwarden-json/src/client.rs index d484c7b50..ef9414f12 100644 --- a/crates/bitwarden-json/src/client.rs +++ b/crates/bitwarden-json/src/client.rs @@ -1,3 +1,4 @@ +use async_lock::Mutex; use bitwarden::client::client_settings::ClientSettings; #[cfg(feature = "secrets")] @@ -7,15 +8,15 @@ use crate::{ response::{Response, ResponseIntoString}, }; -pub struct Client(bitwarden::Client); +pub struct Client(Mutex); impl Client { pub fn new(settings_input: Option) -> Self { let settings = Self::parse_settings(settings_input); - Self(bitwarden::Client::new(settings)) + Self(Mutex::new(bitwarden::Client::new(settings))) } - pub async fn run_command(&mut self, input_str: &str) -> String { + pub async fn run_command(&self, input_str: &str) -> String { const SUBCOMMANDS_TO_CLEAN: &[&str] = &["Secrets"]; let mut cmd_value: serde_json::Value = match serde_json::from_str(input_str) { Ok(cmd) => cmd, @@ -44,41 +45,43 @@ impl Client { } }; + let mut client = self.0.lock().await; + match cmd { #[cfg(feature = "internal")] - Command::PasswordLogin(req) => self.0.auth().login_password(&req).await.into_string(), + Command::PasswordLogin(req) => client.auth().login_password(&req).await.into_string(), #[cfg(feature = "secrets")] Command::AccessTokenLogin(req) => { - self.0.auth().login_access_token(&req).await.into_string() + client.auth().login_access_token(&req).await.into_string() } #[cfg(feature = "internal")] - Command::GetUserApiKey(req) => self.0.get_user_api_key(&req).await.into_string(), + Command::GetUserApiKey(req) => client.get_user_api_key(&req).await.into_string(), #[cfg(feature = "internal")] - Command::ApiKeyLogin(req) => self.0.auth().login_api_key(&req).await.into_string(), + Command::ApiKeyLogin(req) => client.auth().login_api_key(&req).await.into_string(), #[cfg(feature = "internal")] - Command::Sync(req) => self.0.sync(&req).await.into_string(), + Command::Sync(req) => client.sync(&req).await.into_string(), #[cfg(feature = "internal")] - Command::Fingerprint(req) => self.0.platform().fingerprint(&req).into_string(), + Command::Fingerprint(req) => client.platform().fingerprint(&req).into_string(), #[cfg(feature = "secrets")] Command::Secrets(cmd) => match cmd { - SecretsCommand::Get(req) => self.0.secrets().get(&req).await.into_string(), + SecretsCommand::Get(req) => client.secrets().get(&req).await.into_string(), SecretsCommand::GetByIds(req) => { - self.0.secrets().get_by_ids(req).await.into_string() + client.secrets().get_by_ids(req).await.into_string() } - SecretsCommand::Create(req) => self.0.secrets().create(&req).await.into_string(), - SecretsCommand::List(req) => self.0.secrets().list(&req).await.into_string(), - SecretsCommand::Update(req) => self.0.secrets().update(&req).await.into_string(), - SecretsCommand::Delete(req) => self.0.secrets().delete(req).await.into_string(), + SecretsCommand::Create(req) => client.secrets().create(&req).await.into_string(), + SecretsCommand::List(req) => client.secrets().list(&req).await.into_string(), + SecretsCommand::Update(req) => client.secrets().update(&req).await.into_string(), + SecretsCommand::Delete(req) => client.secrets().delete(req).await.into_string(), }, #[cfg(feature = "secrets")] Command::Projects(cmd) => match cmd { - ProjectsCommand::Get(req) => self.0.projects().get(&req).await.into_string(), - ProjectsCommand::Create(req) => self.0.projects().create(&req).await.into_string(), - ProjectsCommand::List(req) => self.0.projects().list(&req).await.into_string(), - ProjectsCommand::Update(req) => self.0.projects().update(&req).await.into_string(), - ProjectsCommand::Delete(req) => self.0.projects().delete(req).await.into_string(), + ProjectsCommand::Get(req) => client.projects().get(&req).await.into_string(), + ProjectsCommand::Create(req) => client.projects().create(&req).await.into_string(), + ProjectsCommand::List(req) => client.projects().list(&req).await.into_string(), + ProjectsCommand::Update(req) => client.projects().update(&req).await.into_string(), + ProjectsCommand::Delete(req) => client.projects().delete(req).await.into_string(), }, } } diff --git a/crates/bitwarden-napi/src/client.rs b/crates/bitwarden-napi/src/client.rs index 712cd4ffd..f41d5c351 100644 --- a/crates/bitwarden-napi/src/client.rs +++ b/crates/bitwarden-napi/src/client.rs @@ -38,7 +38,7 @@ impl BitwardenClient { } #[napi] - pub async unsafe fn run_command(&mut self, command_input: String) -> String { + pub async fn run_command(&self, command_input: String) -> String { self.0.run_command(&command_input).await } } diff --git a/crates/bitwarden-py/src/client.rs b/crates/bitwarden-py/src/client.rs index 1cfd078bb..f1d282b41 100644 --- a/crates/bitwarden-py/src/client.rs +++ b/crates/bitwarden-py/src/client.rs @@ -13,12 +13,12 @@ impl BitwardenClient { } #[pyo3(text_signature = "($self, command_input)")] - fn run_command(&mut self, command_input: String) -> String { - run_command(&mut self.0, &command_input) + fn run_command(&self, command_input: String) -> String { + run_command(&self.0, &command_input) } } #[tokio::main] -async fn run_command(client: &mut JsonClient, input_str: &str) -> String { +async fn run_command(client: &JsonClient, input_str: &str) -> String { client.run_command(input_str).await } diff --git a/crates/bitwarden-wasm/src/client.rs b/crates/bitwarden-wasm/src/client.rs index b9f6723a6..542759731 100644 --- a/crates/bitwarden-wasm/src/client.rs +++ b/crates/bitwarden-wasm/src/client.rs @@ -1,5 +1,5 @@ extern crate console_error_panic_hook; -use std::{rc::Rc, sync::RwLock}; +use std::rc::Rc; use bitwarden_json::client::Client as JsonClient; use js_sys::Promise; @@ -26,10 +26,10 @@ fn convert_level(level: LogLevel) -> Level { } } -// Rc> is to avoid needing to take ownership of the Client during our async run_command +// Rc<...> is to avoid needing to take ownership of the Client during our async run_command // function https://github.com/rustwasm/wasm-bindgen/issues/2195#issuecomment-799588401 #[wasm_bindgen] -pub struct BitwardenClient(Rc>); +pub struct BitwardenClient(Rc); #[wasm_bindgen] impl BitwardenClient { @@ -42,20 +42,14 @@ impl BitwardenClient { panic!("failed to initialize logger: {:?}", e); } - Self(Rc::new(RwLock::new(bitwarden_json::client::Client::new( - settings_input, - )))) + Self(Rc::new(bitwarden_json::client::Client::new(settings_input))) } #[wasm_bindgen] - pub fn run_command(&mut self, js_input: String) -> Promise { + pub fn run_command(&self, js_input: String) -> Promise { let rc = self.0.clone(); - // TODO: We should probably switch to an async-aware RwLock here, - // but it probably doesn't matter much in a single threaded environment - #[allow(clippy::await_holding_lock)] future_to_promise(async move { - let mut client = rc.write().unwrap(); - let result = client.run_command(&js_input).await; + let result = rc.run_command(&js_input).await; Ok(result.into()) }) } From 575dd19f46aba09927226a0bbf0aafd6eb04fd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 11:05:26 +0100 Subject: [PATCH 267/378] [SM-1086] Improve TS bindings (#398) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement support for projects, accesstokenlogin and response unwrapping. Also added a small example --- languages/js/example/index.js | 32 ++++ languages/js/example/package-lock.json | 34 ++++ languages/js/example/package.json | 11 ++ languages/js/sdk-client/src/client.ts | 185 +++++++++++-------- languages/js/sdk-client/src/logging_level.ts | 7 - languages/js/sdk-client/tsconfig.json | 2 +- 6 files changed, 189 insertions(+), 82 deletions(-) create mode 100644 languages/js/example/index.js create mode 100644 languages/js/example/package-lock.json create mode 100644 languages/js/example/package.json delete mode 100644 languages/js/sdk-client/src/logging_level.ts diff --git a/languages/js/example/index.js b/languages/js/example/index.js new file mode 100644 index 000000000..8da3fc582 --- /dev/null +++ b/languages/js/example/index.js @@ -0,0 +1,32 @@ +const { BitwardenClient: BitwardenClientWasm, LogLevel } = require("@bitwarden/sdk-wasm"); +const sdk = require("@bitwarden/sdk-client"); + +async function main() { + const settings = { + apiUrl: process.env.API_URL, + identityUrl: process.env.IDENTITY_URL, + }; + + const client = new sdk.BitwardenClient( + new BitwardenClientWasm(JSON.stringify(settings), LogLevel.Debug), + ); + + const organization_id = process.env.ORGANIZATION_ID; + await client.accessTokenLogin(process.env.ACCESS_TOKEN); + + const project = await client.projects().create("test", organization_id); + const projects = await client.projects().list(organization_id); + console.log(projects.data); + + const secret = await client + .secrets() + .create("test-secret", "My secret!", "This is my secret", [project.id], organization_id); + const secrets = await client.secrets().list(organization_id); + console.log(secrets.data); + + console.log(project, secret); + + await client.projects().delete([project.id]); + await client.secrets().delete([secret.id]); +} +main(); diff --git a/languages/js/example/package-lock.json b/languages/js/example/package-lock.json new file mode 100644 index 000000000..f6cab6536 --- /dev/null +++ b/languages/js/example/package-lock.json @@ -0,0 +1,34 @@ +{ + "name": "sdk-example", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sdk-example", + "dependencies": { + "@bitwarden/sdk-client": "../sdk-client", + "@bitwarden/sdk-wasm": "../wasm" + } + }, + "../sdk-client": { + "name": "@bitwarden/sdk-client", + "devDependencies": { + "@types/node": "^18.15.11", + "rimraf": "^5.0.0", + "typescript": "^5.0.3" + } + }, + "../wasm": { + "name": "@bitwarden/sdk-wasm", + "version": "0.1.0" + }, + "node_modules/@bitwarden/sdk-client": { + "resolved": "../sdk-client", + "link": true + }, + "node_modules/@bitwarden/sdk-wasm": { + "resolved": "../wasm", + "link": true + } + } +} diff --git a/languages/js/example/package.json b/languages/js/example/package.json new file mode 100644 index 000000000..836e53085 --- /dev/null +++ b/languages/js/example/package.json @@ -0,0 +1,11 @@ +{ + "name": "sdk-example", + "main": "index.js", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "@bitwarden/sdk-client": "../sdk-client", + "@bitwarden/sdk-wasm": "../wasm" + } +} diff --git a/languages/js/sdk-client/src/client.ts b/languages/js/sdk-client/src/client.ts index f77ba1420..0f06889c1 100644 --- a/languages/js/sdk-client/src/client.ts +++ b/languages/js/sdk-client/src/client.ts @@ -1,18 +1,24 @@ import { Convert, - ResponseForFingerprintResponse, - ResponseForPasswordLoginResponse, - ResponseForSecretIdentifiersResponse, - ResponseForSecretResponse, - ResponseForSecretsDeleteResponse, - ResponseForSyncResponse, - ResponseForUserAPIKeyResponse, + ProjectResponse, + ProjectsDeleteResponse, + ProjectsResponse, + SecretIdentifiersResponse, + SecretResponse, + SecretsDeleteResponse, } from "./schemas"; interface BitwardenSDKClient { run_command(js_input: string): Promise; } +function handleResponse(response: { success: boolean; errorMessage?: string; data?: T }): T { + if (!response.success) { + throw new Error(response.errorMessage); + } + return response.data as T; +} + export class BitwardenClient { client: BitwardenSDKClient; @@ -20,64 +26,25 @@ export class BitwardenClient { this.client = client; } - async login(email: string, password: string, pbkdf_iter: number): Promise { + async accessTokenLogin(accessToken: string): Promise { const response = await this.client.run_command( Convert.commandToJson({ - passwordLogin: { - email: email, - password: password, - kdf: { - pBKDF2: { - iterations: pbkdf_iter, - } - }, + accessTokenLogin: { + accessToken, }, - }) + }), ); - return Convert.toResponseForPasswordLoginResponse(response); + handleResponse(Convert.toResponseForAccessTokenLoginResponse(response)); } - async getUserApiKey( - secret: string, - isOtp: boolean = false - ): Promise { - const response = await this.client.run_command( - Convert.commandToJson({ - getUserApiKey: { - masterPassword: isOtp ? null : secret, - otp: isOtp ? secret : null, - }, - }) - ); - - return Convert.toResponseForUserAPIKeyResponse(response); + secrets(): SecretsClient { + return new SecretsClient(this.client); } - async sync(excludeSubdomains: boolean = false): Promise { - const response = await this.client.run_command( - Convert.commandToJson({ - sync: { - excludeSubdomains, - }, - }) - ); - - return Convert.toResponseForSyncResponse(response); + projects(): ProjectsClient { + return new ProjectsClient(this.client); } - - async fingerprint(fingerprintMaterial: string, publicKey: string): Promise { - const response = await this.client.run_command( - Convert.commandToJson({ - fingerprint: { - fingerprintMaterial: fingerprintMaterial, - publicKey: publicKey, - } - }) - ) - - return Convert.toResponseForFingerprintResponse(response).data.fingerprint; - }; } export class SecretsClient { @@ -87,74 +54,144 @@ export class SecretsClient { this.client = client; } - async get(id: string): Promise { + async get(id: string): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { get: { id }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } async create( key: string, + value: string, note: string, + projectIds: string[], organizationId: string, - value: string - ): Promise { + ): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - create: { key, note, organizationId, value }, + create: { key, value, note, projectIds, organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } - async list(organizationId: string): Promise { + async list(organizationId: string): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { list: { organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretIdentifiersResponse(response); + return handleResponse(Convert.toResponseForSecretIdentifiersResponse(response)); } async update( id: string, key: string, + value: string, note: string, + projectIds: string[], organizationId: string, - value: string - ): Promise { + ): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { - update: { id, key, note, organizationId, value }, + update: { id, key, value, note, projectIds, organizationId }, }, - }) + }), ); - return Convert.toResponseForSecretResponse(response); + return handleResponse(Convert.toResponseForSecretResponse(response)); } - async delete(ids: string[]): Promise { + async delete(ids: string[]): Promise { const response = await this.client.run_command( Convert.commandToJson({ secrets: { delete: { ids }, }, - }) + }), + ); + + return handleResponse(Convert.toResponseForSecretsDeleteResponse(response)); + } +} + +export class ProjectsClient { + client: BitwardenSDKClient; + + constructor(client: BitwardenSDKClient) { + this.client = client; + } + + async get(id: string): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + get: { id }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async create(name: string, organizationId: string): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + create: { name, organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async list(organizationId: string): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + list: { organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectsResponse(response)); + } + + async update(id: string, name: string, organizationId: string): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + update: { id, name, organizationId }, + }, + }), + ); + + return handleResponse(Convert.toResponseForProjectResponse(response)); + } + + async delete(ids: string[]): Promise { + const response = await this.client.run_command( + Convert.commandToJson({ + projects: { + delete: { ids }, + }, + }), ); - return Convert.toResponseForSecretsDeleteResponse(response); + return handleResponse(Convert.toResponseForProjectsDeleteResponse(response)); } } diff --git a/languages/js/sdk-client/src/logging_level.ts b/languages/js/sdk-client/src/logging_level.ts deleted file mode 100644 index 2453b1eb6..000000000 --- a/languages/js/sdk-client/src/logging_level.ts +++ /dev/null @@ -1,7 +0,0 @@ -export enum LoggingLevel { - Trace, - Debug, - Info, - Warn, - Error, -} diff --git a/languages/js/sdk-client/tsconfig.json b/languages/js/sdk-client/tsconfig.json index 453623d5f..987e8d679 100644 --- a/languages/js/sdk-client/tsconfig.json +++ b/languages/js/sdk-client/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "outDir": "./dist/", - "module": "esnext", + "module": "commonjs", "target": "es5", "moduleResolution": "node", "sourceMap": true, From f16189c240f32a4dc71190de53794dff29310964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 13:13:15 +0100 Subject: [PATCH 268/378] Update swagger generated API crates (#590) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update swagger generator to version 7.2.0, pull in the new templates and generate the new API crates. I've also updated the build instructions to use .NET 8, as is required in the latest server code. The version of the server code used to generate this is https://github.com/bitwarden/server/commit/fc1d7c70592cfbc65e61c047bcc138850d91a55b I've had to make some small modifications to the server code to get it working, ~~and I'll link the PR here shortly.~~ https://github.com/bitwarden/server/pull/3760 To make this easier to review, I've split this into three commits: - b42f189924a770aa127b88478876548e8beb3879: Update the swagger and dotnet versions, and pull in the new templates as-is. Note that this won't generate working code. - 9727d462924f9e533c0e3608ff0ba8aaeb0a2124: Patched the provided templates to make it work with our code. This is in a separate commit to make it easier to see what we've changed and hopefully make it easier in the future to update these templates. The changes are: - Ignore warnings by default - Use Uuids instead of strings - Use serde_repr to support int enums - Disabled default features for reqwest (to remove default tls) - Removing double optionals (This could be reverted once we're better at marking everything as required in the server) - ~~f9b63606477d0f0f987b8534ef6e6755c76003a2: New autogenerated swagger code, no manually edited files here.~~ Moved to a separate PR (#593) --- README.md | 4 +- openapitools.json | 2 +- support/openapi-template/Cargo.mustache | 55 ++++++++--- support/openapi-template/git_push.sh.mustache | 0 support/openapi-template/hyper/api.mustache | 16 ++-- support/openapi-template/model.mustache | 2 +- support/openapi-template/request.rs | 93 +++++++++---------- support/openapi-template/reqwest/api.mustache | 29 +++++- .../openapi-template/reqwest/api_mod.mustache | 56 ++++++++++- .../reqwest/configuration.mustache | 6 +- 10 files changed, 175 insertions(+), 88 deletions(-) mode change 100644 => 100755 support/openapi-template/git_push.sh.mustache diff --git a/README.md b/README.md index 2de94b09c..dbf4e4f2c 100644 --- a/README.md +++ b/README.md @@ -57,10 +57,10 @@ The first step is to generate the swagger documents from the server repository. ```bash # src/Api -dotnet swagger tofile --output ../../api.json ./bin/Debug/net6.0/Api.dll internal +dotnet swagger tofile --output ../../api.json ./bin/Debug/net8.0/Api.dll internal # src/Identity -ASPNETCORE_ENVIRONMENT=development dotnet swagger tofile --output ../../identity.json ./bin/Debug/net6.0/Identity.dll v1 +ASPNETCORE_ENVIRONMENT=development dotnet swagger tofile --output ../../identity.json ./bin/Debug/net8.0/Identity.dll v1 ``` ### OpenApi Generator diff --git a/openapitools.json b/openapitools.json index a3883a34f..e73b97583 100644 --- a/openapitools.json +++ b/openapitools.json @@ -2,6 +2,6 @@ "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", "spaces": 2, "generator-cli": { - "version": "6.5.0" + "version": "7.2.0" } } diff --git a/support/openapi-template/Cargo.mustache b/support/openapi-template/Cargo.mustache index 3b89aa079..6417d15cd 100644 --- a/support/openapi-template/Cargo.mustache +++ b/support/openapi-template/Cargo.mustache @@ -1,42 +1,71 @@ [package] name = "{{{packageName}}}" version = "{{#lambdaVersion}}{{{packageVersion}}}{{/lambdaVersion}}" +{{#infoEmail}} +authors = ["{{{.}}}"] +{{/infoEmail}} +{{^infoEmail}} authors = ["OpenAPI Generator team and contributors"] +{{/infoEmail}} +{{#appDescription}} +description = "{{{.}}}" +{{/appDescription}} +{{#licenseInfo}} +license = "{{.}}" +{{/licenseInfo}} +{{^licenseInfo}} +# Override this license by providing a License Object in the OpenAPI. +license = "Unlicense" +{{/licenseInfo}} edition = "2018" +{{#publishRustRegistry}} +publish = ["{{.}}"] +{{/publishRustRegistry}} +{{#repositoryUrl}} +repository = "{{.}}" +{{/repositoryUrl}} +{{#documentationUrl}} +documentation = "{{.}}" +{{/documentationUrl}} +{{#homePageUrl}} +homepage = "{{.}} +{{/homePageUrl}} [dependencies] serde = "^1.0" serde_derive = "^1.0" +{{#serdeWith}} +serde_with = "^2.0" +{{/serdeWith}} serde_json = "^1.0" serde_repr = "^0.1" url = "^2.2" -uuid = { version = "^1.0", features = ["serde"] } +uuid = { version = "^1.0", features = ["serde", "v4"] } {{#hyper}} hyper = { version = "~0.14", features = ["full"] } hyper-tls = "~0.5" http = "~0.2" -serde_yaml = "0.7" base64 = "~0.7.0" futures = "^0.3" {{/hyper}} +{{#withAWSV4Signature}} +aws-sigv4 = "0.3.0" +http = "0.2.5" +secrecy = "0.8.0" +{{/withAWSV4Signature}} {{#reqwest}} {{^supportAsync}} -reqwest = "~0.9" +[dependencies.reqwest] +version = "^0.11" +features = ["json", "blocking", "multipart"] {{/supportAsync}} {{#supportAsync}} +{{#supportMiddleware}} +reqwest-middleware = "0.2.0" +{{/supportMiddleware}} [dependencies.reqwest] version = "^0.11" features = ["json", "multipart"] default-features = false {{/supportAsync}} {{/reqwest}} -{{#withAWSV4Signature}} -aws-sigv4 = "0.3.0" -http = "0.2.5" -secrecy = "0.8.0" -{{/withAWSV4Signature}} - -[dev-dependencies] -{{#hyper}} -tokio-core = "*" -{{/hyper}} diff --git a/support/openapi-template/git_push.sh.mustache b/support/openapi-template/git_push.sh.mustache old mode 100644 new mode 100755 diff --git a/support/openapi-template/hyper/api.mustache b/support/openapi-template/hyper/api.mustache index 03ea90ad0..dffab3ce8 100644 --- a/support/openapi-template/hyper/api.mustache +++ b/support/openapi-template/hyper/api.mustache @@ -28,7 +28,7 @@ impl {{{classname}}}Client pub trait {{{classname}}} { {{#operations}} {{#operation}} - fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}&str{{/isString}}{{#isUuid}}uuid::Uuid{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin>>>; + fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin>>>; {{/operation}} {{/operations}} } @@ -38,7 +38,7 @@ impl{{{classname}}} for {{{classname}}}Clien {{#operations}} {{#operation}} #[allow(unused_mut)] - fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}&str{{/isString}}{{#isUuid}}uuid::Uuid{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin>>> { + fn {{{operationId}}}(&self, {{#allParams}}{{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{^isUuid}}&str{{/isUuid}}{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) -> Pin>>> { let mut req = __internal_request::Request::new(hyper::Method::{{{httpMethod.toUpperCase}}}, "{{{path}}}".to_string()) {{#hasAuthMethods}} {{#authMethods}} @@ -49,9 +49,9 @@ impl{{{classname}}} for {{{classname}}}Clien param_name: "{{{keyParamName}}}".to_owned(), })) {{/isApiKey}} - {{#isBasic}} + {{#isBasicBasic}} .with_auth(__internal_request::Auth::Basic) - {{/isBasic}} + {{/isBasicBasic}} {{#isOAuth}} .with_auth(__internal_request::Auth::Oauth) {{/isOAuth}} @@ -66,7 +66,7 @@ impl{{{classname}}} for {{{classname}}}Clien {{#isNullable}} match {{{paramName}}} { Some(param_value) => { req = req.with_query_param("{{{baseName}}}".to_string(), param_value{{#isArray}}.join(","){{/isArray}}.to_string()); }, - None => { req = req.with_query_param("{{{baseName}}}".to_string(), String::new()); }, + None => { req = req.with_query_param("{{{baseName}}}".to_string(), "".to_string()); }, } {{/isNullable}} {{/required}} @@ -85,7 +85,7 @@ impl{{{classname}}} for {{{classname}}}Clien {{#isNullable}} match {{{paramName}}} { Some(param_value) => { req = req.with_path_param("{{{baseName}}}".to_string(), param_value{{#isArray}}.join(","){{/isArray}}.to_string()); }, - None => { req = req.with_path_param("{{{baseName}}}".to_string(), String::new()); }, + None => { req = req.with_path_param("{{{baseName}}}".to_string(), "".to_string()); }, } {{/isNullable}} {{/required}} @@ -104,7 +104,7 @@ impl{{{classname}}} for {{{classname}}}Clien {{#isNullable}} match {{{paramName}}} { Some(param_value) => { req = req.with_header_param("{{{baseName}}}".to_string(), param_value{{#isArray}}.join(","){{/isArray}}.to_string()); }, - None => { req = req.with_header_param("{{{baseName}}}".to_string(), String::new()); }, + None => { req = req.with_header_param("{{{baseName}}}".to_string(), "".to_string()); }, } {{/isNullable}} {{/required}} @@ -143,7 +143,7 @@ impl{{{classname}}} for {{{classname}}}Clien {{#isNullable}} match {{{paramName}}} { Some(param_value) => { req = req.with_form_param("{{{baseName}}}".to_string(), param_value{{#isArray}}.join(","){{/isArray}}.to_string()); }, - None => { req = req.with_form_param("{{{baseName}}}".to_string(), String::new()); }, + None => { req = req.with_form_param("{{{baseName}}}".to_string(), "".to_string()); }, } {{/isNullable}} {{/required}} diff --git a/support/openapi-template/model.mustache b/support/openapi-template/model.mustache index 233c88010..4a22118a8 100644 --- a/support/openapi-template/model.mustache +++ b/support/openapi-template/model.mustache @@ -100,7 +100,7 @@ pub enum {{{classname}}} { {{!-- for non-enum schemas --}} {{^isEnum}} {{^discriminator}} -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct {{{classname}}} { {{#vars}} {{#description}} diff --git a/support/openapi-template/request.rs b/support/openapi-template/request.rs index 6e534abaa..81497706a 100644 --- a/support/openapi-template/request.rs +++ b/support/openapi-template/request.rs @@ -2,10 +2,10 @@ use std::collections::HashMap; use std::pin::Pin; use futures; -use futures::future::*; use futures::Future; +use futures::future::*; use hyper; -use hyper::header::{HeaderValue, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT}; +use hyper::header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, HeaderValue, USER_AGENT}; use serde; use serde_json; @@ -50,6 +50,7 @@ pub(crate) struct Request { serialized_body: Option, } +#[allow(dead_code)] impl Request { pub fn new(method: hyper::Method, path: String) -> Self { Request { @@ -75,16 +76,19 @@ impl Request { self } + #[allow(unused)] pub fn with_query_param(mut self, basename: String, param: String) -> Self { self.query_params.insert(basename, param); self } + #[allow(unused)] pub fn with_path_param(mut self, basename: String, param: String) -> Self { self.path_params.insert(basename, param); self } + #[allow(unused)] pub fn with_form_param(mut self, basename: String, param: String) -> Self { self.form_params.insert(basename, param); self @@ -103,13 +107,13 @@ impl Request { pub fn execute<'a, C, U>( self, conf: &configuration::Configuration, - ) -> Pin> + 'a>> - where - C: hyper::client::connect::Connect + Clone + std::marker::Send + Sync, - U: Sized + std::marker::Send + 'a, - for<'de> U: serde::Deserialize<'de>, + ) -> Pin> + 'a>> + where + C: hyper::client::connect::Connect + Clone + std::marker::Send + Sync, + U: Sized + std::marker::Send + 'a, + for<'de> U: serde::Deserialize<'de>, { - let mut query_string = ::url::form_urlencoded::Serializer::new(String::new()); + let mut query_string = ::url::form_urlencoded::Serializer::new("".to_owned()); let mut path = self.path; for (k, v) in self.path_params { @@ -133,7 +137,9 @@ impl Request { Ok(u) => u, }; - let mut req_builder = hyper::Request::builder().uri(uri).method(self.method); + let mut req_builder = hyper::Request::builder() + .uri(uri) + .method(self.method); // Detect the authorization type if it hasn't been set. let auth = self.auth.unwrap_or_else(|| @@ -180,13 +186,10 @@ impl Request { } if let Some(ref user_agent) = conf.user_agent { - req_builder = req_builder.header( - USER_AGENT, - match HeaderValue::from_str(user_agent) { - Ok(header_value) => header_value, - Err(e) => return Box::pin(futures::future::err(super::Error::Header(e))), - }, - ); + req_builder = req_builder.header(USER_AGENT, match HeaderValue::from_str(user_agent) { + Ok(header_value) => header_value, + Err(e) => return Box::pin(futures::future::err(super::Error::Header(e))) + }); } for (k, v) in self.header_params { @@ -195,11 +198,8 @@ impl Request { let req_headers = req_builder.headers_mut().unwrap(); let request_result = if self.form_params.len() > 0 { - req_headers.insert( - CONTENT_TYPE, - HeaderValue::from_static("application/ x-www-form-urlencoded"), - ); - let mut enc = ::url::form_urlencoded::Serializer::new(String::new()); + req_headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/x-www-form-urlencoded")); + let mut enc = ::url::form_urlencoded::Serializer::new("".to_owned()); for (k, v) in self.form_params { enc.append_pair(&k, &v); } @@ -213,37 +213,30 @@ impl Request { }; let request = match request_result { Ok(request) => request, - Err(e) => return Box::pin(futures::future::err(Error::from(e))), + Err(e) => return Box::pin(futures::future::err(Error::from(e))) }; let no_return_type = self.no_return_type; - Box::pin( - conf.client - .request(request) - .map_err(Error::from) - .and_then(move |response| { - let status = response.status(); - if !status.is_success() { - futures::future::err::(Error::from(( - status, - response.into_body(), - ))) - .boxed() - } else if no_return_type { - // This is a hack; if there's no_ret_type, U is (), but serde_json gives an - // error when deserializing "" into (), so deserialize 'null' into it - // instead. - // An alternate option would be to require U: Default, and then return - // U::default() here instead since () implements that, but then we'd - // need to impl default for all models. - futures::future::ok::(serde_json::Value::Null).boxed() - } else { - hyper::body::to_bytes(response.into_body()) - .map(|bytes| serde_json::from_slice(&bytes.unwrap())) - .map_err(Error::from) - .boxed() - } - }), - ) + Box::pin(conf.client + .request(request) + .map_err(|e| Error::from(e)) + .and_then(move |response| { + let status = response.status(); + if !status.is_success() { + futures::future::err::(Error::from((status, response.into_body()))).boxed() + } else if no_return_type { + // This is a hack; if there's no_ret_type, U is (), but serde_json gives an + // error when deserializing "" into (), so deserialize 'null' into it + // instead. + // An alternate option would be to require U: Default, and then return + // U::default() here instead since () implements that, but then we'd + // need to impl default for all models. + futures::future::ok::(serde_json::from_str("null").expect("serde null value")).boxed() + } else { + hyper::body::to_bytes(response.into_body()) + .map(|bytes| serde_json::from_slice(&bytes.unwrap())) + .map_err(|e| Error::from(e)).boxed() + } + })) } } diff --git a/support/openapi-template/reqwest/api.mustache b/support/openapi-template/reqwest/api.mustache index b1a2ec245..8128244a2 100644 --- a/support/openapi-template/reqwest/api.mustache +++ b/support/openapi-template/reqwest/api.mustache @@ -11,13 +11,13 @@ use super::{Error, configuration}; {{#allParams}} {{#-first}} /// struct for passing parameters to the method [`{{operationId}}`] -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct {{{operationIdCamelCase}}}Params { {{/-first}} {{#description}} /// {{{.}}} {{/description}} - pub {{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{#isString}}{{#isArray}}Vec<{{/isArray}}String{{#isArray}}>{{/isArray}}{{/isString}}{{#isUuid}}{{#isArray}}Vec<{{/isArray}}uuid::Uuid{{#isArray}}>{{/isArray}}{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}crate::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}},{{/-last}} + pub {{{paramName}}}: {{^required}}Option<{{/required}}{{#required}}{{#isNullable}}Option<{{/isNullable}}{{/required}}{{^isUuid}}{{#isString}}{{#isArray}}Vec<{{/isArray}}String{{#isArray}}>{{/isArray}}{{/isString}}{{/isUuid}}{{#isUuid}}{{#isArray}}Vec<{{/isArray}}uuid::Uuid{{#isArray}}>{{/isArray}}{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}{{#isBodyParam}}crate::models::{{/isBodyParam}}{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{^required}}>{{/required}}{{#required}}{{#isNullable}}>{{/isNullable}}{{/required}}{{^-last}},{{/-last}} {{#-last}} } @@ -103,12 +103,27 @@ pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration: {{#required}} {{#isArray}} local_var_req_builder = match "{{collectionFormat}}" { - "multi" => local_var_req_builder.query(&{{{paramName}}}.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p)).collect::>()), + "multi" => local_var_req_builder.query(&{{{paramName}}}.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p.to_string())).collect::>()), _ => local_var_req_builder.query(&[("{{{baseName}}}", &{{{paramName}}}.into_iter().map(|p| p.to_string()).collect::>().join(",").to_string())]), }; {{/isArray}} {{^isArray}} + {{^isNullable}} local_var_req_builder = local_var_req_builder.query(&[("{{{baseName}}}", &{{{paramName}}}.to_string())]); + {{/isNullable}} + {{#isNullable}} + {{#isDeepObject}} + if let Some(ref local_var_str) = {{{paramName}}} { + let params = crate::apis::parse_deep_object("{{{baseName}}}", local_var_str); + local_var_req_builder = local_var_req_builder.query(¶ms); + }; + {{/isDeepObject}} + {{^isDeepObject}} + if let Some(ref local_var_str) = {{{paramName}}} { + local_var_req_builder = local_var_req_builder.query(&[("{{{baseName}}}", &local_var_str.to_string())]); + }; + {{/isDeepObject}} + {{/isNullable}} {{/isArray}} {{/required}} {{^required}} @@ -120,7 +135,13 @@ pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration: }; {{/isArray}} {{^isArray}} + {{#isDeepObject}} + let params = crate::apis::parse_deep_object("{{{baseName}}}", local_var_str); + local_var_req_builder = local_var_req_builder.query(¶ms); + {{/isDeepObject}} + {{^isDeepObject}} local_var_req_builder = local_var_req_builder.query(&[("{{{baseName}}}", &local_var_str.to_string())]); + {{/isDeepObject}} {{/isArray}} } {{/required}} @@ -223,7 +244,7 @@ pub {{#supportAsync}}async {{/supportAsync}}fn {{{operationId}}}(configuration: {{/hasAuthMethods}} {{#isMultipart}} {{#hasFormParams}} - let mut local_var_form = reqwest::multipart::Form::new(); + let mut local_var_form = reqwest{{^supportAsync}}::blocking{{/supportAsync}}::multipart::Form::new(); {{#formParams}} {{#isFile}} {{^supportAsync}} diff --git a/support/openapi-template/reqwest/api_mod.mustache b/support/openapi-template/reqwest/api_mod.mustache index 628ec898a..347f33379 100644 --- a/support/openapi-template/reqwest/api_mod.mustache +++ b/support/openapi-template/reqwest/api_mod.mustache @@ -14,6 +14,9 @@ pub struct ResponseContent { #[derive(Debug)] pub enum Error { Reqwest(reqwest::Error), + {{#supportMiddleware}} + ReqwestMiddleware(reqwest_middleware::Error), + {{/supportMiddleware}} Serde(serde_json::Error), Io(std::io::Error), ResponseError(ResponseContent), @@ -26,12 +29,15 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (module, e) = match self { Error::Reqwest(e) => ("reqwest", e.to_string()), + {{#supportMiddleware}} + Error::ReqwestMiddleware(e) => ("reqwest-middleware", e.to_string()), + {{/supportMiddleware}} Error::Serde(e) => ("serde", e.to_string()), Error::Io(e) => ("IO", e.to_string()), Error::ResponseError(e) => ("response", format!("status code {}", e.status)), - {{#withAWSV4Signature}} + {{#withAWSV4Signature}} Error::AWSV4SignatureError(e) => ("aws v4 signature", e.to_string()), - {{/withAWSV4Signature}} + {{/withAWSV4Signature}} }; write!(f, "error in {}: {}", module, e) } @@ -41,12 +47,15 @@ impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(match self { Error::Reqwest(e) => e, + {{#supportMiddleware}} + Error::ReqwestMiddleware(e) => e, + {{/supportMiddleware}} Error::Serde(e) => e, Error::Io(e) => e, Error::ResponseError(_) => return None, - {{#withAWSV4Signature}} - Error::AWSV4SignatureError(_) => return None, - {{/withAWSV4Signature}} + {{#withAWSV4Signature}} + Error::AWSV4SignatureError(_) => return None, + {{/withAWSV4Signature}} }) } } @@ -57,6 +66,14 @@ impl From for Error { } } +{{#supportMiddleware}} +impl From for Error { + fn from(e: reqwest_middleware::Error) -> Self { + Error::ReqwestMiddleware(e) + } +} + +{{/supportMiddleware}} impl From for Error { fn from(e: serde_json::Error) -> Self { Error::Serde(e) @@ -73,6 +90,35 @@ pub fn urlencode>(s: T) -> String { ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect() } +pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> { + if let serde_json::Value::Object(object) = value { + let mut params = vec![]; + + for (key, value) in object { + match value { + serde_json::Value::Object(_) => params.append(&mut parse_deep_object( + &format!("{}[{}]", prefix, key), + value, + )), + serde_json::Value::Array(array) => { + for (i, value) in array.iter().enumerate() { + params.append(&mut parse_deep_object( + &format!("{}[{}][{}]", prefix, key, i), + value, + )); + } + }, + serde_json::Value::String(s) => params.push((format!("{}[{}]", prefix, key), s.clone())), + _ => params.push((format!("{}[{}]", prefix, key), value.to_string())), + } + } + + return params; + } + + unimplemented!("Only objects are supported with style=deepObject") +} + {{#apiInfo}} {{#apis}} pub mod {{{classFilename}}}; diff --git a/support/openapi-template/reqwest/configuration.mustache b/support/openapi-template/reqwest/configuration.mustache index cbc21644e..0de2884a8 100644 --- a/support/openapi-template/reqwest/configuration.mustache +++ b/support/openapi-template/reqwest/configuration.mustache @@ -1,7 +1,5 @@ {{>partial_header}} -use reqwest; - {{#withAWSV4Signature}} use std::time::SystemTime; use aws_sigv4::http_request::{sign, SigningSettings, SigningParams, SignableRequest}; @@ -13,7 +11,7 @@ use secrecy::{SecretString, ExposeSecret}; pub struct Configuration { pub base_path: String, pub user_agent: Option, - pub client: reqwest::Client, + pub client: {{#supportMiddleware}}reqwest_middleware::ClientWithMiddleware{{/supportMiddleware}}{{^supportMiddleware}}reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client{{/supportMiddleware}}, pub basic_auth: Option, pub oauth_access_token: Option, pub bearer_access_token: Option, @@ -82,7 +80,7 @@ impl Default for Configuration { Configuration { base_path: "{{{basePath}}}".to_owned(), user_agent: {{#httpUserAgent}}Some("{{{.}}}".to_owned()){{/httpUserAgent}}{{^httpUserAgent}}Some("OpenAPI-Generator/{{{version}}}/rust".to_owned()){{/httpUserAgent}}, - client: reqwest::Client::new(), + client: {{#supportMiddleware}}reqwest_middleware::ClientBuilder::new(reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client::new()).build(){{/supportMiddleware}}{{^supportMiddleware}}reqwest{{^supportAsync}}::blocking{{/supportAsync}}::Client::new(){{/supportMiddleware}}, basic_auth: None, oauth_access_token: None, bearer_access_token: None, From 2f9a9f6f3fd210ea4f7c2fcf03741930e8b65395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 13:14:04 +0100 Subject: [PATCH 269/378] Update autogenerated swagger files (#593) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Extracted the autogenerated code from #590 --- .../.openapi-generator/FILES | 38 +- .../.openapi-generator/VERSION | 2 +- crates/bitwarden-api-api/README.md | 63 +++- .../src/apis/access_policies_api.rs | 144 +++++++- .../src/apis/accounts_api.rs | 48 --- .../bitwarden-api-api/src/apis/ciphers_api.rs | 40 +-- .../src/apis/collections_api.rs | 69 +++- .../src/apis/configuration.rs | 2 - .../bitwarden-api-api/src/apis/devices_api.rs | 16 +- .../bitwarden-api-api/src/apis/groups_api.rs | 2 +- crates/bitwarden-api-api/src/apis/mod.rs | 33 ++ .../src/apis/organization_domain_api.rs | 20 +- .../src/apis/organization_users_api.rs | 2 +- .../src/apis/organizations_api.rs | 164 +++++++++ .../bitwarden-api-api/src/apis/plans_api.rs | 92 ----- .../src/apis/policies_api.rs | 62 +++- .../src/apis/secrets_manager_events_api.rs | 82 +++++ .../src/apis/web_authn_api.rs | 324 ++++++++++++++++++ .../models/access_policies_create_request.rs | 2 +- .../src/models/access_policy_request.rs | 2 +- .../models/access_policy_update_request.rs | 2 +- .../access_token_create_request_model.rs | 2 +- .../access_token_creation_response_model.rs | 2 +- .../src/models/access_token_response_model.rs | 2 +- ...oken_response_model_list_response_model.rs | 2 +- ...admin_auth_request_update_request_model.rs | 2 +- .../bitwarden-api-api/src/models/algorithm.rs | 54 +++ .../src/models/api_key_response_model.rs | 2 +- .../src/models/assertion_options.rs | 44 +++ .../src/models/assertion_response.rs | 32 ++ .../src/models/attachment_request_model.rs | 2 +- .../src/models/attachment_response_model.rs | 2 +- .../attachment_upload_data_response_model.rs | 2 +- .../attestation_conveyance_preference.rs | 36 ++ .../auth_request_create_request_model.rs | 2 +- .../src/models/auth_request_response_model.rs | 2 +- ...uest_response_model_list_response_model.rs | 2 +- .../auth_request_update_request_model.rs | 2 +- ...authentication_extensions_client_inputs.rs | 35 ++ ...uthentication_extensions_client_outputs.rs | 2 +- .../authenticator_assertion_raw_response.rs | 35 ++ .../src/models/authenticator_attachment.rs | 33 ++ .../authenticator_attestation_raw_response.rs | 2 +- .../src/models/authenticator_selection.rs | 32 ++ .../src/models/authenticator_transport.rs | 39 +++ .../base_access_policy_response_model.rs | 2 +- .../src/models/base_secret_response_model.rs | 2 +- ...cret_response_model_list_response_model.rs | 2 +- .../src/models/billing_customer_discount.rs | 8 +- .../models/billing_history_response_model.rs | 2 +- .../src/models/billing_invoice.rs | 2 +- .../models/billing_payment_response_model.rs | 2 +- .../src/models/billing_response_model.rs | 2 +- .../src/models/billing_source.rs | 2 +- .../src/models/billing_subscription.rs | 2 +- .../src/models/billing_subscription_item.rs | 8 +- .../billing_subscription_upcoming_invoice.rs | 2 +- .../src/models/billing_transaction.rs | 2 +- .../models/bit_pay_invoice_request_model.rs | 2 +- .../bulk_collection_access_request_model.rs | 29 ++ .../src/models/bulk_delete_response_model.rs | 2 +- ...lete_response_model_list_response_model.rs | 2 +- ...k_deny_admin_auth_request_request_model.rs | 2 +- .../src/models/cipher_attachment_model.rs | 2 +- .../cipher_bulk_delete_request_model.rs | 2 +- .../models/cipher_bulk_move_request_model.rs | 2 +- .../cipher_bulk_restore_request_model.rs | 2 +- .../models/cipher_bulk_share_request_model.rs | 2 +- .../src/models/cipher_card_model.rs | 2 +- .../cipher_collections_request_model.rs | 2 +- .../src/models/cipher_create_request_model.rs | 2 +- .../models/cipher_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../models/cipher_fido2_credential_model.rs | 59 ++++ .../src/models/cipher_field_model.rs | 2 +- .../src/models/cipher_identity_model.rs | 2 +- .../src/models/cipher_login_model.rs | 5 +- .../src/models/cipher_login_uri_model.rs | 5 +- .../cipher_mini_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../src/models/cipher_mini_response_model.rs | 2 +- ...mini_response_model_list_response_model.rs | 2 +- .../models/cipher_partial_request_model.rs | 2 +- .../models/cipher_password_history_model.rs | 2 +- .../src/models/cipher_request_model.rs | 2 +- .../src/models/cipher_response_model.rs | 2 +- .../src/models/cipher_secure_note_model.rs | 2 +- .../src/models/cipher_share_request_model.rs | 2 +- .../models/cipher_with_id_request_model.rs | 2 +- ...ollection_access_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../collection_bulk_delete_request_model.rs | 13 +- .../collection_details_response_model.rs | 5 +- ...ails_response_model_list_response_model.rs | 2 +- .../src/models/collection_request_model.rs | 2 +- .../src/models/collection_response_model.rs | 2 +- ...tion_response_model_list_response_model.rs | 2 +- .../collection_with_id_request_model.rs | 2 +- .../src/models/config_response_model.rs | 2 +- .../src/models/credential_create_options.rs | 56 +++ .../models/delete_recover_request_model.rs | 2 +- .../src/models/device_keys_request_model.rs | 2 +- .../device_keys_update_request_model.rs | 2 +- .../src/models/device_request_model.rs | 2 +- .../src/models/device_response_model.rs | 2 +- ...vice_response_model_list_response_model.rs | 2 +- .../src/models/device_token_request_model.rs | 2 +- .../src/models/device_type.rs | 6 + .../device_verification_request_model.rs | 2 +- .../device_verification_response_model.rs | 2 +- .../src/models/domains_response_model.rs | 2 +- .../src/models/email_request_model.rs | 2 +- .../src/models/email_token_request_model.rs | 2 +- ...y_access_grantee_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- ...y_access_grantor_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../emergency_access_invite_request_model.rs | 2 +- ...emergency_access_password_request_model.rs | 2 +- ...mergency_access_takeover_response_model.rs | 2 +- .../emergency_access_update_request_model.rs | 2 +- .../emergency_access_view_response_model.rs | 2 +- .../emergency_access_with_id_request_model.rs | 36 ++ .../environment_config_response_model.rs | 2 +- .../src/models/event_response_model.rs | 2 +- ...vent_response_model_list_response_model.rs | 2 +- .../src/models/event_type.rs | 2 + .../src/models/fido2_user.rs | 29 ++ .../src/models/folder_request_model.rs | 2 +- .../src/models/folder_response_model.rs | 2 +- ...lder_response_model_list_response_model.rs | 2 +- .../models/folder_with_id_request_model.rs | 2 +- .../src/models/get_secrets_request_model.rs | 2 +- .../src/models/global_domains.rs | 2 +- .../models/granted_access_policy_request.rs | 2 +- crates/bitwarden-api-api/src/models/group.rs | 2 +- .../src/models/group_bulk_request_model.rs | 2 +- .../models/group_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- ...up_project_access_policy_response_model.rs | 2 +- .../src/models/group_request_model.rs | 2 +- .../src/models/group_response_model.rs | 2 +- ...ce_account_access_policy_response_model.rs | 2 +- .../models/import_ciphers_request_model.rs | 2 +- ...port_organization_ciphers_request_model.rs | 2 +- ...import_organization_users_request_model.rs | 2 +- .../inner_project_export_response_model.rs | 2 +- .../inner_project_import_request_model.rs | 2 +- .../inner_secret_export_response_model.rs | 2 +- .../inner_secret_import_request_model.rs | 2 +- .../src/models/installation_request_model.rs | 2 +- .../src/models/installation_response_model.rs | 2 +- .../src/models/int32_int32_key_value_pair.rs | 2 +- .../src/models/kdf_request_model.rs | 2 +- .../bitwarden-api-api/src/models/key_model.rs | 2 +- .../src/models/keys_request_model.rs | 2 +- .../src/models/keys_response_model.rs | 2 +- .../master_password_policy_response_model.rs | 2 +- crates/bitwarden-api-api/src/models/mod.rs | 72 +++- .../organization_api_key_information.rs | 2 +- ...api_key_information_list_response_model.rs | 2 +- .../organization_api_key_request_model.rs | 2 +- ...ation_auto_enroll_status_response_model.rs | 2 +- ...lection_management_update_request_model.rs | 32 ++ .../organization_connection_request_model.rs | 2 +- .../organization_connection_response_model.rs | 2 +- .../organization_create_request_model.rs | 8 +- .../organization_domain_request_model.rs | 2 +- .../organization_domain_response_model.rs | 2 +- ...main_response_model_list_response_model.rs | 2 +- ...zation_domain_sso_details_request_model.rs | 2 +- ...ation_domain_sso_details_response_model.rs | 2 +- .../models/organization_keys_request_model.rs | 2 +- .../organization_keys_response_model.rs | 2 +- .../src/models/organization_license.rs | 26 +- .../organization_public_key_response_model.rs | 2 +- .../src/models/organization_response_model.rs | 20 +- ...sks_subscription_failure_response_model.rs | 32 ++ .../models/organization_seat_request_model.rs | 2 +- ...zation_sponsorship_create_request_model.rs | 2 +- ...zation_sponsorship_redeem_request_model.rs | 2 +- .../organization_sponsorship_request_model.rs | 2 +- ...organization_sponsorship_response_model.rs | 2 +- ...nization_sponsorship_sync_request_model.rs | 2 +- ...ization_sponsorship_sync_response_model.rs | 2 +- .../models/organization_sso_request_model.rs | 2 +- .../models/organization_sso_response_model.rs | 2 +- ...rganization_subscription_response_model.rs | 29 +- ...ation_subscription_update_request_model.rs | 2 +- ...anization_tax_info_update_request_model.rs | 2 +- .../organization_update_request_model.rs | 2 +- .../organization_upgrade_request_model.rs | 2 +- ...nization_user_accept_init_request_model.rs | 2 +- .../organization_user_accept_request_model.rs | 2 +- ...ization_user_bulk_confirm_request_model.rs | 2 +- ...n_user_bulk_confirm_request_model_entry.rs | 2 +- .../organization_user_bulk_request_model.rs | 2 +- .../organization_user_bulk_response_model.rs | 2 +- ...bulk_response_model_list_response_model.rs | 2 +- ...organization_user_confirm_request_model.rs | 2 +- ...rganization_user_details_response_model.rs | 2 +- .../organization_user_invite_request_model.rs | 2 +- ...nization_user_public_key_response_model.rs | 2 +- ..._key_response_model_list_response_model.rs | 2 +- ...r_reset_password_details_response_model.rs | 2 +- ...reset_password_enrollment_request_model.rs | 2 +- ...ation_user_reset_password_request_model.rs | 2 +- ...zation_user_update_groups_request_model.rs | 2 +- .../organization_user_update_request_model.rs | 2 +- ...zation_user_user_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../organization_verify_bank_request_model.rs | 2 +- .../other_device_keys_update_request_model.rs | 2 +- .../src/models/password_hint_request_model.rs | 2 +- ...rd_manager_plan_features_response_model.rs | 98 ++++++ .../src/models/password_request_model.rs | 2 +- .../src/models/payment_method_type.rs | 4 - .../src/models/payment_request_model.rs | 2 +- .../src/models/payment_response_model.rs | 2 +- ...rganization_auth_request_response_model.rs | 2 +- ...uest_response_model_list_response_model.rs | 2 +- .../people_access_policies_request_model.rs | 32 ++ .../src/models/permissions.rs | 2 +- .../src/models/plan_response_model.rs | 119 +------ ...plan_response_model_list_response_model.rs | 2 +- .../bitwarden-api-api/src/models/plan_type.rs | 10 + .../src/models/policy_request_model.rs | 2 +- .../src/models/policy_response_model.rs | 2 +- ...licy_response_model_list_response_model.rs | 2 +- .../potential_grantee_response_model.rs | 8 +- ...ntee_response_model_list_response_model.rs | 2 +- .../src/models/prelogin_request_model.rs | 2 +- .../src/models/prelogin_response_model.rs | 2 +- .../src/models/product_type.rs | 2 + .../profile_organization_response_model.rs | 20 +- ...tion_response_model_list_response_model.rs | 2 +- ...le_provider_organization_response_model.rs | 20 +- .../models/profile_provider_response_model.rs | 2 +- .../src/models/profile_response_model.rs | 5 +- .../project_access_policies_response_model.rs | 2 +- .../models/project_create_request_model.rs | 2 +- ...t_people_access_policies_response_model.rs | 32 ++ .../src/models/project_response_model.rs | 2 +- ...ject_response_model_list_response_model.rs | 2 +- .../models/project_update_request_model.rs | 2 +- .../models/protected_device_response_model.rs | 2 +- ...provider_organization_add_request_model.rs | 2 +- ...vider_organization_create_request_model.rs | 2 +- ...ion_organization_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../provider_organization_response_model.rs | 2 +- .../src/models/provider_response_model.rs | 5 +- .../models/provider_setup_request_model.rs | 2 +- .../models/provider_update_request_model.rs | 2 +- .../provider_user_accept_request_model.rs | 2 +- ...rovider_user_bulk_confirm_request_model.rs | 2 +- ...r_user_bulk_confirm_request_model_entry.rs | 2 +- .../provider_user_bulk_request_model.rs | 2 +- .../provider_user_bulk_response_model.rs | 2 +- ...bulk_response_model_list_response_model.rs | 2 +- .../provider_user_confirm_request_model.rs | 2 +- .../provider_user_invite_request_model.rs | 2 +- ...provider_user_public_key_response_model.rs | 2 +- ..._key_response_model_list_response_model.rs | 2 +- .../models/provider_user_response_model.rs | 2 +- .../provider_user_update_request_model.rs | 2 +- ...ovider_user_user_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../src/models/pub_key_cred_param.rs | 26 ++ .../public_key_credential_descriptor.rs | 29 ++ .../models/public_key_credential_rp_entity.rs | 29 ++ .../models/push_registration_request_model.rs | 2 +- .../src/models/push_send_request_model.rs | 2 +- .../src/models/push_update_request_model.rs | 2 +- .../src/models/register_request_model.rs | 2 +- .../src/models/register_response_model.rs | 2 +- ...eset_password_with_org_id_request_model.rs | 26 ++ .../src/models/response_data.rs | 2 +- .../models/revoke_access_tokens_request.rs | 2 +- .../src/models/secret_create_request_model.rs | 2 +- .../models/secret_response_inner_project.rs | 2 +- .../src/models/secret_response_model.rs | 2 +- .../src/models/secret_update_request_model.rs | 2 +- .../secret_verification_request_model.rs | 2 +- .../secret_with_projects_inner_project.rs | 2 +- ...ecret_with_projects_list_response_model.rs | 2 +- ...ts_manager_plan_features_response_model.rs | 86 +++++ ...secrets_manager_subscribe_request_model.rs | 2 +- ...nager_subscription_update_request_model.rs | 2 +- .../secrets_with_projects_inner_secret.rs | 2 +- .../selection_read_only_request_model.rs | 9 +- .../selection_read_only_response_model.rs | 5 +- ...sted_organization_license_request_model.rs | 2 +- .../src/models/send_access_request_model.rs | 2 +- .../src/models/send_file_model.rs | 2 +- .../send_file_upload_data_response_model.rs | 2 +- .../src/models/send_request_model.rs | 2 +- .../src/models/send_response_model.rs | 2 +- ...send_response_model_list_response_model.rs | 2 +- .../src/models/send_text_model.rs | 2 +- .../src/models/send_with_id_request_model.rs | 2 +- .../models/server_config_response_model.rs | 2 +- .../service_account_create_request_model.rs | 2 +- ...t_people_access_policies_response_model.rs | 34 ++ ...nt_project_access_policy_response_model.rs | 2 +- ...licy_response_model_list_response_model.rs | 2 +- .../models/service_account_response_model.rs | 2 +- ..._account_secrets_details_response_model.rs | 2 +- ...ails_response_model_list_response_model.rs | 2 +- .../service_account_update_request_model.rs | 2 +- .../set_key_connector_key_request_model.rs | 2 +- .../src/models/set_password_request_model.rs | 9 +- .../src/models/sm_export_response_model.rs | 2 +- .../src/models/sm_import_request_model.rs | 2 +- .../src/models/sso_configuration_data.rs | 5 +- .../models/sso_configuration_data_request.rs | 5 +- .../bitwarden-api-api/src/models/sso_urls.rs | 5 +- .../src/models/storage_request_model.rs | 2 +- .../src/models/subscription_response_model.rs | 8 +- .../src/models/sync_response_model.rs | 2 +- .../src/models/tax_info_response_model.rs | 2 +- .../models/tax_info_update_request_model.rs | 2 +- .../src/models/tax_rate_response_model.rs | 2 +- ...rate_response_model_list_response_model.rs | 2 +- ...two_factor_authenticator_response_model.rs | 2 +- .../models/two_factor_duo_response_model.rs | 2 +- .../models/two_factor_email_request_model.rs | 2 +- .../models/two_factor_email_response_model.rs | 2 +- .../two_factor_provider_request_model.rs | 2 +- .../two_factor_provider_response_model.rs | 2 +- ...ider_response_model_list_response_model.rs | 2 +- .../two_factor_recover_response_model.rs | 2 +- .../two_factor_recovery_request_model.rs | 2 +- ...o_factor_web_authn_delete_request_model.rs | 2 +- .../two_factor_web_authn_request_model.rs | 2 +- .../two_factor_web_authn_response_model.rs | 2 +- .../two_factor_yubi_key_response_model.rs | 2 +- .../src/models/update_avatar_request_model.rs | 2 +- .../update_devices_trust_request_model.rs | 2 +- .../models/update_domains_request_model.rs | 2 +- .../src/models/update_key_request_model.rs | 39 ++- .../models/update_profile_request_model.rs | 2 +- .../update_temp_password_request_model.rs | 2 +- ..._two_factor_authenticator_request_model.rs | 2 +- .../update_two_factor_duo_request_model.rs | 2 +- .../update_two_factor_email_request_model.rs | 2 +- ...ate_two_factor_yubico_otp_request_model.rs | 2 +- crates/bitwarden-api-api/src/models/user.rs | 2 +- .../src/models/user_key_response_model.rs | 2 +- .../src/models/user_license.rs | 2 +- ...er_project_access_policy_response_model.rs | 5 +- ...ce_account_access_policy_response_model.rs | 5 +- .../models/user_verification_requirement.rs | 36 ++ .../verify_delete_recover_request_model.rs | 2 +- .../src/models/verify_email_request_model.rs | 2 +- .../src/models/verify_otp_request_model.rs | 2 +- ...redential_create_options_response_model.rs | 29 ++ .../web_authn_credential_response_model.rs | 32 ++ ...tial_response_model_list_response_model.rs | 29 ++ ..._login_assertion_options_response_model.rs | 29 ++ ...n_login_credential_create_request_model.rs | 49 +++ ...n_login_credential_update_request_model.rs | 41 +++ .../src/models/web_authn_prf_status.rs | 36 ++ .../.openapi-generator/FILES | 7 + .../.openapi-generator/VERSION | 2 +- crates/bitwarden-api-identity/README.md | 38 +- .../src/apis/accounts_api.rs | 49 +++ .../src/apis/configuration.rs | 2 - crates/bitwarden-api-identity/src/apis/mod.rs | 31 ++ .../src/models/assertion_options.rs | 44 +++ ...authentication_extensions_client_inputs.rs | 35 ++ .../src/models/authenticator_transport.rs | 39 +++ .../src/models/keys_request_model.rs | 2 +- .../bitwarden-api-identity/src/models/mod.rs | 14 + .../src/models/prelogin_request_model.rs | 2 +- .../src/models/prelogin_response_model.rs | 2 +- .../public_key_credential_descriptor.rs | 29 ++ .../src/models/public_key_credential_type.rs | 30 ++ .../src/models/register_request_model.rs | 2 +- .../src/models/register_response_model.rs | 2 +- .../models/user_verification_requirement.rs | 36 ++ ..._login_assertion_options_response_model.rs | 29 ++ 382 files changed, 3217 insertions(+), 722 deletions(-) create mode 100644 crates/bitwarden-api-api/src/apis/secrets_manager_events_api.rs create mode 100644 crates/bitwarden-api-api/src/apis/web_authn_api.rs create mode 100644 crates/bitwarden-api-api/src/models/algorithm.rs create mode 100644 crates/bitwarden-api-api/src/models/assertion_options.rs create mode 100644 crates/bitwarden-api-api/src/models/assertion_response.rs create mode 100644 crates/bitwarden-api-api/src/models/attestation_conveyance_preference.rs create mode 100644 crates/bitwarden-api-api/src/models/authentication_extensions_client_inputs.rs create mode 100644 crates/bitwarden-api-api/src/models/authenticator_assertion_raw_response.rs create mode 100644 crates/bitwarden-api-api/src/models/authenticator_attachment.rs create mode 100644 crates/bitwarden-api-api/src/models/authenticator_selection.rs create mode 100644 crates/bitwarden-api-api/src/models/authenticator_transport.rs create mode 100644 crates/bitwarden-api-api/src/models/bulk_collection_access_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/cipher_fido2_credential_model.rs create mode 100644 crates/bitwarden-api-api/src/models/credential_create_options.rs create mode 100644 crates/bitwarden-api-api/src/models/emergency_access_with_id_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/fido2_user.rs create mode 100644 crates/bitwarden-api-api/src/models/organization_collection_management_update_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/organization_risks_subscription_failure_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/password_manager_plan_features_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/people_access_policies_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/project_people_access_policies_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/pub_key_cred_param.rs create mode 100644 crates/bitwarden-api-api/src/models/public_key_credential_descriptor.rs create mode 100644 crates/bitwarden-api-api/src/models/public_key_credential_rp_entity.rs create mode 100644 crates/bitwarden-api-api/src/models/reset_password_with_org_id_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/secrets_manager_plan_features_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/service_account_people_access_policies_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/user_verification_requirement.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_credential_create_options_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_credential_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_credential_response_model_list_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_login_assertion_options_response_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_login_credential_create_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_login_credential_update_request_model.rs create mode 100644 crates/bitwarden-api-api/src/models/web_authn_prf_status.rs create mode 100644 crates/bitwarden-api-identity/src/models/assertion_options.rs create mode 100644 crates/bitwarden-api-identity/src/models/authentication_extensions_client_inputs.rs create mode 100644 crates/bitwarden-api-identity/src/models/authenticator_transport.rs create mode 100644 crates/bitwarden-api-identity/src/models/public_key_credential_descriptor.rs create mode 100644 crates/bitwarden-api-identity/src/models/public_key_credential_type.rs create mode 100644 crates/bitwarden-api-identity/src/models/user_verification_requirement.rs create mode 100644 crates/bitwarden-api-identity/src/models/web_authn_login_assertion_options_response_model.rs diff --git a/crates/bitwarden-api-api/.openapi-generator/FILES b/crates/bitwarden-api-api/.openapi-generator/FILES index 586d4f2db..4566fa01c 100644 --- a/crates/bitwarden-api-api/.openapi-generator/FILES +++ b/crates/bitwarden-api-api/.openapi-generator/FILES @@ -36,6 +36,7 @@ src/apis/provider_users_api.rs src/apis/providers_api.rs src/apis/push_api.rs src/apis/secrets_api.rs +src/apis/secrets_manager_events_api.rs src/apis/secrets_manager_porting_api.rs src/apis/self_hosted_organization_licenses_api.rs src/apis/self_hosted_organization_sponsorships_api.rs @@ -46,6 +47,7 @@ src/apis/sync_api.rs src/apis/trash_api.rs src/apis/two_factor_api.rs src/apis/users_api.rs +src/apis/web_authn_api.rs src/lib.rs src/models/access_policies_create_request.rs src/models/access_policy_request.rs @@ -55,17 +57,26 @@ src/models/access_token_creation_response_model.rs src/models/access_token_response_model.rs src/models/access_token_response_model_list_response_model.rs src/models/admin_auth_request_update_request_model.rs +src/models/algorithm.rs src/models/api_key_response_model.rs +src/models/assertion_options.rs +src/models/assertion_response.rs src/models/attachment_request_model.rs src/models/attachment_response_model.rs src/models/attachment_upload_data_response_model.rs +src/models/attestation_conveyance_preference.rs src/models/auth_request_create_request_model.rs src/models/auth_request_response_model.rs src/models/auth_request_response_model_list_response_model.rs src/models/auth_request_type.rs src/models/auth_request_update_request_model.rs +src/models/authentication_extensions_client_inputs.rs src/models/authentication_extensions_client_outputs.rs +src/models/authenticator_assertion_raw_response.rs +src/models/authenticator_attachment.rs src/models/authenticator_attestation_raw_response.rs +src/models/authenticator_selection.rs +src/models/authenticator_transport.rs src/models/base_access_policy_response_model.rs src/models/base_secret_response_model.rs src/models/base_secret_response_model_list_response_model.rs @@ -80,7 +91,7 @@ src/models/billing_subscription_item.rs src/models/billing_subscription_upcoming_invoice.rs src/models/billing_transaction.rs src/models/bit_pay_invoice_request_model.rs -src/models/bitwarden_product_type.rs +src/models/bulk_collection_access_request_model.rs src/models/bulk_delete_response_model.rs src/models/bulk_delete_response_model_list_response_model.rs src/models/bulk_deny_admin_auth_request_request_model.rs @@ -94,6 +105,7 @@ src/models/cipher_collections_request_model.rs src/models/cipher_create_request_model.rs src/models/cipher_details_response_model.rs src/models/cipher_details_response_model_list_response_model.rs +src/models/cipher_fido2_credential_model.rs src/models/cipher_field_model.rs src/models/cipher_identity_model.rs src/models/cipher_login_model.rs @@ -121,6 +133,7 @@ src/models/collection_response_model.rs src/models/collection_response_model_list_response_model.rs src/models/collection_with_id_request_model.rs src/models/config_response_model.rs +src/models/credential_create_options.rs src/models/delete_recover_request_model.rs src/models/device_keys_request_model.rs src/models/device_keys_update_request_model.rs @@ -145,11 +158,13 @@ src/models/emergency_access_takeover_response_model.rs src/models/emergency_access_type.rs src/models/emergency_access_update_request_model.rs src/models/emergency_access_view_response_model.rs +src/models/emergency_access_with_id_request_model.rs src/models/environment_config_response_model.rs src/models/event_response_model.rs src/models/event_response_model_list_response_model.rs src/models/event_system_user.rs src/models/event_type.rs +src/models/fido2_user.rs src/models/field_type.rs src/models/file_upload_type.rs src/models/folder_request_model.rs @@ -168,7 +183,6 @@ src/models/group_project_access_policy_response_model.rs src/models/group_request_model.rs src/models/group_response_model.rs src/models/group_service_account_access_policy_response_model.rs -src/models/iap_check_request_model.rs src/models/import_ciphers_request_model.rs src/models/import_organization_ciphers_request_model.rs src/models/import_organization_users_request_model.rs @@ -194,6 +208,7 @@ src/models/organization_api_key_information_list_response_model.rs src/models/organization_api_key_request_model.rs src/models/organization_api_key_type.rs src/models/organization_auto_enroll_status_response_model.rs +src/models/organization_collection_management_update_request_model.rs src/models/organization_connection_request_model.rs src/models/organization_connection_response_model.rs src/models/organization_connection_type.rs @@ -208,6 +223,7 @@ src/models/organization_keys_response_model.rs src/models/organization_license.rs src/models/organization_public_key_response_model.rs src/models/organization_response_model.rs +src/models/organization_risks_subscription_failure_response_model.rs src/models/organization_seat_request_model.rs src/models/organization_sponsorship_create_request_model.rs src/models/organization_sponsorship_redeem_request_model.rs @@ -245,12 +261,14 @@ src/models/organization_user_user_details_response_model_list_response_model.rs src/models/organization_verify_bank_request_model.rs src/models/other_device_keys_update_request_model.rs src/models/password_hint_request_model.rs +src/models/password_manager_plan_features_response_model.rs src/models/password_request_model.rs src/models/payment_method_type.rs src/models/payment_request_model.rs src/models/payment_response_model.rs src/models/pending_organization_auth_request_response_model.rs src/models/pending_organization_auth_request_response_model_list_response_model.rs +src/models/people_access_policies_request_model.rs src/models/permissions.rs src/models/plan_response_model.rs src/models/plan_response_model_list_response_model.rs @@ -272,6 +290,7 @@ src/models/profile_provider_response_model.rs src/models/profile_response_model.rs src/models/project_access_policies_response_model.rs src/models/project_create_request_model.rs +src/models/project_people_access_policies_response_model.rs src/models/project_response_model.rs src/models/project_response_model_list_response_model.rs src/models/project_update_request_model.rs @@ -301,6 +320,9 @@ src/models/provider_user_type.rs src/models/provider_user_update_request_model.rs src/models/provider_user_user_details_response_model.rs src/models/provider_user_user_details_response_model_list_response_model.rs +src/models/pub_key_cred_param.rs +src/models/public_key_credential_descriptor.rs +src/models/public_key_credential_rp_entity.rs src/models/public_key_credential_type.rs src/models/push_registration_request_model.rs src/models/push_send_request_model.rs @@ -308,6 +330,7 @@ src/models/push_type.rs src/models/push_update_request_model.rs src/models/register_request_model.rs src/models/register_response_model.rs +src/models/reset_password_with_org_id_request_model.rs src/models/response_data.rs src/models/revoke_access_tokens_request.rs src/models/saml2_binding_type.rs @@ -320,6 +343,7 @@ src/models/secret_update_request_model.rs src/models/secret_verification_request_model.rs src/models/secret_with_projects_inner_project.rs src/models/secret_with_projects_list_response_model.rs +src/models/secrets_manager_plan_features_response_model.rs src/models/secrets_manager_subscribe_request_model.rs src/models/secrets_manager_subscription_update_request_model.rs src/models/secrets_with_projects_inner_secret.rs @@ -337,8 +361,8 @@ src/models/send_text_model.rs src/models/send_type.rs src/models/send_with_id_request_model.rs src/models/server_config_response_model.rs -src/models/service_account_access_policies_response_model.rs src/models/service_account_create_request_model.rs +src/models/service_account_people_access_policies_response_model.rs src/models/service_account_project_access_policy_response_model.rs src/models/service_account_project_access_policy_response_model_list_response_model.rs src/models/service_account_response_model.rs @@ -391,6 +415,14 @@ src/models/user_key_response_model.rs src/models/user_license.rs src/models/user_project_access_policy_response_model.rs src/models/user_service_account_access_policy_response_model.rs +src/models/user_verification_requirement.rs src/models/verify_delete_recover_request_model.rs src/models/verify_email_request_model.rs src/models/verify_otp_request_model.rs +src/models/web_authn_credential_create_options_response_model.rs +src/models/web_authn_credential_response_model.rs +src/models/web_authn_credential_response_model_list_response_model.rs +src/models/web_authn_login_assertion_options_response_model.rs +src/models/web_authn_login_credential_create_request_model.rs +src/models/web_authn_login_credential_update_request_model.rs +src/models/web_authn_prf_status.rs diff --git a/crates/bitwarden-api-api/.openapi-generator/VERSION b/crates/bitwarden-api-api/.openapi-generator/VERSION index 4be2c727a..4b49d9bb6 100644 --- a/crates/bitwarden-api-api/.openapi-generator/VERSION +++ b/crates/bitwarden-api-api/.openapi-generator/VERSION @@ -1 +1 @@ -6.5.0 \ No newline at end of file +7.2.0 \ No newline at end of file diff --git a/crates/bitwarden-api-api/README.md b/crates/bitwarden-api-api/README.md index 43cbc40e8..b4dac8d9f 100644 --- a/crates/bitwarden-api-api/README.md +++ b/crates/bitwarden-api-api/README.md @@ -26,17 +26,19 @@ bitwarden-api-api = { path = "./bitwarden-api-api" } All URIs are relative to _http://localhost_ -| Class | Method | HTTP request | Description | -| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | +| Class | Method | HTTP request | Description | +| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | _AccessPoliciesApi_ | [**access_policies_id_delete**](docs/AccessPoliciesApi.md#access_policies_id_delete) | **DELETE** /access-policies/{id} | | _AccessPoliciesApi_ | [**access_policies_id_put**](docs/AccessPoliciesApi.md#access_policies_id_put) | **PUT** /access-policies/{id} | | _AccessPoliciesApi_ | [**organizations_id_access_policies_people_potential_grantees_get**](docs/AccessPoliciesApi.md#organizations_id_access_policies_people_potential_grantees_get) | **GET** /organizations/{id}/access-policies/people/potential-grantees | | _AccessPoliciesApi_ | [**organizations_id_access_policies_projects_potential_grantees_get**](docs/AccessPoliciesApi.md#organizations_id_access_policies_projects_potential_grantees_get) | **GET** /organizations/{id}/access-policies/projects/potential-grantees | | _AccessPoliciesApi_ | [**organizations_id_access_policies_service_accounts_potential_grantees_get**](docs/AccessPoliciesApi.md#organizations_id_access_policies_service_accounts_potential_grantees_get) | **GET** /organizations/{id}/access-policies/service-accounts/potential-grantees | | _AccessPoliciesApi_ | [**projects_id_access_policies_get**](docs/AccessPoliciesApi.md#projects_id_access_policies_get) | **GET** /projects/{id}/access-policies | +| _AccessPoliciesApi_ | [**projects_id_access_policies_people_get**](docs/AccessPoliciesApi.md#projects_id_access_policies_people_get) | **GET** /projects/{id}/access-policies/people | +| _AccessPoliciesApi_ | [**projects_id_access_policies_people_put**](docs/AccessPoliciesApi.md#projects_id_access_policies_people_put) | **PUT** /projects/{id}/access-policies/people | | _AccessPoliciesApi_ | [**projects_id_access_policies_post**](docs/AccessPoliciesApi.md#projects_id_access_policies_post) | **POST** /projects/{id}/access-policies | -| _AccessPoliciesApi_ | [**service_accounts_id_access_policies_get**](docs/AccessPoliciesApi.md#service_accounts_id_access_policies_get) | **GET** /service-accounts/{id}/access-policies | -| _AccessPoliciesApi_ | [**service_accounts_id_access_policies_post**](docs/AccessPoliciesApi.md#service_accounts_id_access_policies_post) | **POST** /service-accounts/{id}/access-policies | +| _AccessPoliciesApi_ | [**service_accounts_id_access_policies_people_get**](docs/AccessPoliciesApi.md#service_accounts_id_access_policies_people_get) | **GET** /service-accounts/{id}/access-policies/people | +| _AccessPoliciesApi_ | [**service_accounts_id_access_policies_people_put**](docs/AccessPoliciesApi.md#service_accounts_id_access_policies_people_put) | **PUT** /service-accounts/{id}/access-policies/people | | _AccessPoliciesApi_ | [**service_accounts_id_granted_policies_get**](docs/AccessPoliciesApi.md#service_accounts_id_granted_policies_get) | **GET** /service-accounts/{id}/granted-policies | | _AccessPoliciesApi_ | [**service_accounts_id_granted_policies_post**](docs/AccessPoliciesApi.md#service_accounts_id_granted_policies_post) | **POST** /service-accounts/{id}/granted-policies | | _AccountsApi_ | [**accounts_api_key_post**](docs/AccountsApi.md#accounts_api_key_post) | **POST** /accounts/api-key | @@ -50,7 +52,6 @@ All URIs are relative to _http://localhost_ | _AccountsApi_ | [**accounts_delete_recover_token_post**](docs/AccountsApi.md#accounts_delete_recover_token_post) | **POST** /accounts/delete-recover-token | | _AccountsApi_ | [**accounts_email_post**](docs/AccountsApi.md#accounts_email_post) | **POST** /accounts/email | | _AccountsApi_ | [**accounts_email_token_post**](docs/AccountsApi.md#accounts_email_token_post) | **POST** /accounts/email-token | -| _AccountsApi_ | [**accounts_iap_check_post**](docs/AccountsApi.md#accounts_iap_check_post) | **POST** /accounts/iap-check | | _AccountsApi_ | [**accounts_kdf_post**](docs/AccountsApi.md#accounts_kdf_post) | **POST** /accounts/kdf | | _AccountsApi_ | [**accounts_key_post**](docs/AccountsApi.md#accounts_key_post) | **POST** /accounts/key | | _AccountsApi_ | [**accounts_keys_get**](docs/AccountsApi.md#accounts_keys_get) | **GET** /accounts/keys | @@ -147,6 +148,7 @@ All URIs are relative to _http://localhost_ | _CiphersApi_ | [**ciphers_share_post**](docs/CiphersApi.md#ciphers_share_post) | **POST** /ciphers/share | | _CiphersApi_ | [**ciphers_share_put**](docs/CiphersApi.md#ciphers_share_put) | **PUT** /ciphers/share | | _CollectionsApi_ | [**collections_get**](docs/CollectionsApi.md#collections_get) | **GET** /collections | +| _CollectionsApi_ | [**organizations_org_id_collections_bulk_access_post**](docs/CollectionsApi.md#organizations_org_id_collections_bulk_access_post) | **POST** /organizations/{orgId}/collections/bulk-access | | _CollectionsApi_ | [**organizations_org_id_collections_delete**](docs/CollectionsApi.md#organizations_org_id_collections_delete) | **DELETE** /organizations/{orgId}/collections | | _CollectionsApi_ | [**organizations_org_id_collections_delete_post**](docs/CollectionsApi.md#organizations_org_id_collections_delete_post) | **POST** /organizations/{orgId}/collections/delete | | _CollectionsApi_ | [**organizations_org_id_collections_details_get**](docs/CollectionsApi.md#organizations_org_id_collections_details_get) | **GET** /organizations/{orgId}/collections/details | @@ -236,7 +238,7 @@ All URIs are relative to _http://localhost_ | _InfoApi_ | [**version_get**](docs/InfoApi.md#version_get) | **GET** /version | | _InstallationsApi_ | [**installations_id_get**](docs/InstallationsApi.md#installations_id_get) | **GET** /installations/{id} | | _InstallationsApi_ | [**installations_post**](docs/InstallationsApi.md#installations_post) | **POST** /installations | -| _LicensesApi_ | [**licenses_organization_id_get**](docs/LicensesApi.md#licenses_organization_id_get) | **GET** /licenses/organization/{id} | Used by self-hosted installations to get an updated license file | +| _LicensesApi_ | [**licenses_organization_id_get**](docs/LicensesApi.md#licenses_organization_id_get) | **GET** /licenses/organization/{id} | Used by self-hosted installations to get an updated license file | | _LicensesApi_ | [**licenses_user_id_get**](docs/LicensesApi.md#licenses_user_id_get) | **GET** /licenses/user/{id} | | _MiscApi_ | [**bitpay_invoice_post**](docs/MiscApi.md#bitpay_invoice_post) | **POST** /bitpay-invoice | | _MiscApi_ | [**setup_payment_post**](docs/MiscApi.md#setup_payment_post) | **POST** /setup-payment | @@ -304,8 +306,10 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_api_key_post**](docs/OrganizationsApi.md#organizations_id_api_key_post) | **POST** /organizations/{id}/api-key | | _OrganizationsApi_ | [**organizations_id_billing_get**](docs/OrganizationsApi.md#organizations_id_billing_get) | **GET** /organizations/{id}/billing | | _OrganizationsApi_ | [**organizations_id_cancel_post**](docs/OrganizationsApi.md#organizations_id_cancel_post) | **POST** /organizations/{id}/cancel | +| _OrganizationsApi_ | [**organizations_id_collection_management_put**](docs/OrganizationsApi.md#organizations_id_collection_management_put) | **PUT** /organizations/{id}/collection-management | | _OrganizationsApi_ | [**organizations_id_delete**](docs/OrganizationsApi.md#organizations_id_delete) | **DELETE** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_delete_post**](docs/OrganizationsApi.md#organizations_id_delete_post) | **POST** /organizations/{id}/delete | +| _OrganizationsApi_ | [**organizations_id_enable_collection_enhancements_post**](docs/OrganizationsApi.md#organizations_id_enable_collection_enhancements_post) | **POST** /organizations/{id}/enable-collection-enhancements | Migrates user, collection, and group data to the new Flexible Collections permissions scheme, then sets organization.FlexibleCollections to true to enable these new features for the organization. This is irreversible. | | _OrganizationsApi_ | [**organizations_id_get**](docs/OrganizationsApi.md#organizations_id_get) | **GET** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_import_post**](docs/OrganizationsApi.md#organizations_id_import_post) | **POST** /organizations/{id}/import | | _OrganizationsApi_ | [**organizations_id_keys_get**](docs/OrganizationsApi.md#organizations_id_keys_get) | **GET** /organizations/{id}/keys | @@ -317,6 +321,7 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_public_key_get**](docs/OrganizationsApi.md#organizations_id_public_key_get) | **GET** /organizations/{id}/public-key | | _OrganizationsApi_ | [**organizations_id_put**](docs/OrganizationsApi.md#organizations_id_put) | **PUT** /organizations/{id} | | _OrganizationsApi_ | [**organizations_id_reinstate_post**](docs/OrganizationsApi.md#organizations_id_reinstate_post) | **POST** /organizations/{id}/reinstate | +| _OrganizationsApi_ | [**organizations_id_risks_subscription_failure_get**](docs/OrganizationsApi.md#organizations_id_risks_subscription_failure_get) | **GET** /organizations/{id}/risks-subscription-failure | | _OrganizationsApi_ | [**organizations_id_rotate_api_key_post**](docs/OrganizationsApi.md#organizations_id_rotate_api_key_post) | **POST** /organizations/{id}/rotate-api-key | | _OrganizationsApi_ | [**organizations_id_seat_post**](docs/OrganizationsApi.md#organizations_id_seat_post) | **POST** /organizations/{id}/seat | | _OrganizationsApi_ | [**organizations_id_sm_subscription_post**](docs/OrganizationsApi.md#organizations_id_sm_subscription_post) | **POST** /organizations/{id}/sm-subscription | @@ -332,12 +337,11 @@ All URIs are relative to _http://localhost_ | _OrganizationsApi_ | [**organizations_id_verify_bank_post**](docs/OrganizationsApi.md#organizations_id_verify_bank_post) | **POST** /organizations/{id}/verify-bank | | _OrganizationsApi_ | [**organizations_identifier_auto_enroll_status_get**](docs/OrganizationsApi.md#organizations_identifier_auto_enroll_status_get) | **GET** /organizations/{identifier}/auto-enroll-status | | _OrganizationsApi_ | [**organizations_post**](docs/OrganizationsApi.md#organizations_post) | **POST** /organizations | -| _PlansApi_ | [**plans_all_get**](docs/PlansApi.md#plans_all_get) | **GET** /plans/all | | _PlansApi_ | [**plans_get**](docs/PlansApi.md#plans_get) | **GET** /plans | | _PlansApi_ | [**plans_sales_tax_rates_get**](docs/PlansApi.md#plans_sales_tax_rates_get) | **GET** /plans/sales-tax-rates | -| _PlansApi_ | [**plans_sm_plans_get**](docs/PlansApi.md#plans_sm_plans_get) | **GET** /plans/sm-plans | | _PoliciesApi_ | [**organizations_org_id_policies_get**](docs/PoliciesApi.md#organizations_org_id_policies_get) | **GET** /organizations/{orgId}/policies | | _PoliciesApi_ | [**organizations_org_id_policies_invited_user_get**](docs/PoliciesApi.md#organizations_org_id_policies_invited_user_get) | **GET** /organizations/{orgId}/policies/invited-user | +| _PoliciesApi_ | [**organizations_org_id_policies_master_password_get**](docs/PoliciesApi.md#organizations_org_id_policies_master_password_get) | **GET** /organizations/{orgId}/policies/master-password | | _PoliciesApi_ | [**organizations_org_id_policies_token_get**](docs/PoliciesApi.md#organizations_org_id_policies_token_get) | **GET** /organizations/{orgId}/policies/token | | _PoliciesApi_ | [**organizations_org_id_policies_type_get**](docs/PoliciesApi.md#organizations_org_id_policies_type_get) | **GET** /organizations/{orgId}/policies/{type} | | _PoliciesApi_ | [**organizations_org_id_policies_type_put**](docs/PoliciesApi.md#organizations_org_id_policies_type_put) | **PUT** /organizations/{orgId}/policies/{type} | @@ -382,6 +386,7 @@ All URIs are relative to _http://localhost_ | _SecretsApi_ | [**secrets_get_by_ids_post**](docs/SecretsApi.md#secrets_get_by_ids_post) | **POST** /secrets/get-by-ids | | _SecretsApi_ | [**secrets_id_get**](docs/SecretsApi.md#secrets_id_get) | **GET** /secrets/{id} | | _SecretsApi_ | [**secrets_id_put**](docs/SecretsApi.md#secrets_id_put) | **PUT** /secrets/{id} | +| _SecretsManagerEventsApi_ | [**sm_events_service_accounts_service_account_id_get**](docs/SecretsManagerEventsApi.md#sm_events_service_accounts_service_account_id_get) | **GET** /sm/events/service-accounts/{serviceAccountId} | | _SecretsManagerPortingApi_ | [**sm_organization_id_export_get**](docs/SecretsManagerPortingApi.md#sm_organization_id_export_get) | **GET** /sm/{organizationId}/export | | _SecretsManagerPortingApi_ | [**sm_organization_id_import_post**](docs/SecretsManagerPortingApi.md#sm_organization_id_import_post) | **POST** /sm/{organizationId}/import | | _SelfHostedOrganizationLicensesApi_ | [**organizations_licenses_self_hosted_id_post**](docs/SelfHostedOrganizationLicensesApi.md#organizations_licenses_self_hosted_id_post) | **POST** /organizations/licenses/self-hosted/{id} | @@ -450,6 +455,12 @@ All URIs are relative to _http://localhost_ | _TwoFactorApi_ | [**two_factor_yubikey_post**](docs/TwoFactorApi.md#two_factor_yubikey_post) | **POST** /two-factor/yubikey | | _TwoFactorApi_ | [**two_factor_yubikey_put**](docs/TwoFactorApi.md#two_factor_yubikey_put) | **PUT** /two-factor/yubikey | | _UsersApi_ | [**users_id_public_key_get**](docs/UsersApi.md#users_id_public_key_get) | **GET** /users/{id}/public-key | +| _WebAuthnApi_ | [**webauthn_assertion_options_post**](docs/WebAuthnApi.md#webauthn_assertion_options_post) | **POST** /webauthn/assertion-options | +| _WebAuthnApi_ | [**webauthn_attestation_options_post**](docs/WebAuthnApi.md#webauthn_attestation_options_post) | **POST** /webauthn/attestation-options | +| _WebAuthnApi_ | [**webauthn_get**](docs/WebAuthnApi.md#webauthn_get) | **GET** /webauthn | +| _WebAuthnApi_ | [**webauthn_id_delete_post**](docs/WebAuthnApi.md#webauthn_id_delete_post) | **POST** /webauthn/{id}/delete | +| _WebAuthnApi_ | [**webauthn_post**](docs/WebAuthnApi.md#webauthn_post) | **POST** /webauthn | +| _WebAuthnApi_ | [**webauthn_put**](docs/WebAuthnApi.md#webauthn_put) | **PUT** /webauthn | ## Documentation For Models @@ -461,17 +472,26 @@ All URIs are relative to _http://localhost_ - [AccessTokenResponseModel](docs/AccessTokenResponseModel.md) - [AccessTokenResponseModelListResponseModel](docs/AccessTokenResponseModelListResponseModel.md) - [AdminAuthRequestUpdateRequestModel](docs/AdminAuthRequestUpdateRequestModel.md) +- [Algorithm](docs/Algorithm.md) - [ApiKeyResponseModel](docs/ApiKeyResponseModel.md) +- [AssertionOptions](docs/AssertionOptions.md) +- [AssertionResponse](docs/AssertionResponse.md) - [AttachmentRequestModel](docs/AttachmentRequestModel.md) - [AttachmentResponseModel](docs/AttachmentResponseModel.md) - [AttachmentUploadDataResponseModel](docs/AttachmentUploadDataResponseModel.md) +- [AttestationConveyancePreference](docs/AttestationConveyancePreference.md) - [AuthRequestCreateRequestModel](docs/AuthRequestCreateRequestModel.md) - [AuthRequestResponseModel](docs/AuthRequestResponseModel.md) - [AuthRequestResponseModelListResponseModel](docs/AuthRequestResponseModelListResponseModel.md) - [AuthRequestType](docs/AuthRequestType.md) - [AuthRequestUpdateRequestModel](docs/AuthRequestUpdateRequestModel.md) +- [AuthenticationExtensionsClientInputs](docs/AuthenticationExtensionsClientInputs.md) - [AuthenticationExtensionsClientOutputs](docs/AuthenticationExtensionsClientOutputs.md) +- [AuthenticatorAssertionRawResponse](docs/AuthenticatorAssertionRawResponse.md) +- [AuthenticatorAttachment](docs/AuthenticatorAttachment.md) - [AuthenticatorAttestationRawResponse](docs/AuthenticatorAttestationRawResponse.md) +- [AuthenticatorSelection](docs/AuthenticatorSelection.md) +- [AuthenticatorTransport](docs/AuthenticatorTransport.md) - [BaseAccessPolicyResponseModel](docs/BaseAccessPolicyResponseModel.md) - [BaseSecretResponseModel](docs/BaseSecretResponseModel.md) - [BaseSecretResponseModelListResponseModel](docs/BaseSecretResponseModelListResponseModel.md) @@ -486,7 +506,7 @@ All URIs are relative to _http://localhost_ - [BillingSubscriptionUpcomingInvoice](docs/BillingSubscriptionUpcomingInvoice.md) - [BillingTransaction](docs/BillingTransaction.md) - [BitPayInvoiceRequestModel](docs/BitPayInvoiceRequestModel.md) -- [BitwardenProductType](docs/BitwardenProductType.md) +- [BulkCollectionAccessRequestModel](docs/BulkCollectionAccessRequestModel.md) - [BulkDeleteResponseModel](docs/BulkDeleteResponseModel.md) - [BulkDeleteResponseModelListResponseModel](docs/BulkDeleteResponseModelListResponseModel.md) - [BulkDenyAdminAuthRequestRequestModel](docs/BulkDenyAdminAuthRequestRequestModel.md) @@ -500,6 +520,7 @@ All URIs are relative to _http://localhost_ - [CipherCreateRequestModel](docs/CipherCreateRequestModel.md) - [CipherDetailsResponseModel](docs/CipherDetailsResponseModel.md) - [CipherDetailsResponseModelListResponseModel](docs/CipherDetailsResponseModelListResponseModel.md) +- [CipherFido2CredentialModel](docs/CipherFido2CredentialModel.md) - [CipherFieldModel](docs/CipherFieldModel.md) - [CipherIdentityModel](docs/CipherIdentityModel.md) - [CipherLoginModel](docs/CipherLoginModel.md) @@ -527,6 +548,7 @@ All URIs are relative to _http://localhost_ - [CollectionResponseModelListResponseModel](docs/CollectionResponseModelListResponseModel.md) - [CollectionWithIdRequestModel](docs/CollectionWithIdRequestModel.md) - [ConfigResponseModel](docs/ConfigResponseModel.md) +- [CredentialCreateOptions](docs/CredentialCreateOptions.md) - [DeleteRecoverRequestModel](docs/DeleteRecoverRequestModel.md) - [DeviceKeysRequestModel](docs/DeviceKeysRequestModel.md) - [DeviceKeysUpdateRequestModel](docs/DeviceKeysUpdateRequestModel.md) @@ -551,11 +573,13 @@ All URIs are relative to _http://localhost_ - [EmergencyAccessType](docs/EmergencyAccessType.md) - [EmergencyAccessUpdateRequestModel](docs/EmergencyAccessUpdateRequestModel.md) - [EmergencyAccessViewResponseModel](docs/EmergencyAccessViewResponseModel.md) +- [EmergencyAccessWithIdRequestModel](docs/EmergencyAccessWithIdRequestModel.md) - [EnvironmentConfigResponseModel](docs/EnvironmentConfigResponseModel.md) - [EventResponseModel](docs/EventResponseModel.md) - [EventResponseModelListResponseModel](docs/EventResponseModelListResponseModel.md) - [EventSystemUser](docs/EventSystemUser.md) - [EventType](docs/EventType.md) +- [Fido2User](docs/Fido2User.md) - [FieldType](docs/FieldType.md) - [FileUploadType](docs/FileUploadType.md) - [FolderRequestModel](docs/FolderRequestModel.md) @@ -574,7 +598,6 @@ All URIs are relative to _http://localhost_ - [GroupRequestModel](docs/GroupRequestModel.md) - [GroupResponseModel](docs/GroupResponseModel.md) - [GroupServiceAccountAccessPolicyResponseModel](docs/GroupServiceAccountAccessPolicyResponseModel.md) -- [IapCheckRequestModel](docs/IapCheckRequestModel.md) - [ImportCiphersRequestModel](docs/ImportCiphersRequestModel.md) - [ImportOrganizationCiphersRequestModel](docs/ImportOrganizationCiphersRequestModel.md) - [ImportOrganizationUsersRequestModel](docs/ImportOrganizationUsersRequestModel.md) @@ -599,6 +622,7 @@ All URIs are relative to _http://localhost_ - [OrganizationApiKeyRequestModel](docs/OrganizationApiKeyRequestModel.md) - [OrganizationApiKeyType](docs/OrganizationApiKeyType.md) - [OrganizationAutoEnrollStatusResponseModel](docs/OrganizationAutoEnrollStatusResponseModel.md) +- [OrganizationCollectionManagementUpdateRequestModel](docs/OrganizationCollectionManagementUpdateRequestModel.md) - [OrganizationConnectionRequestModel](docs/OrganizationConnectionRequestModel.md) - [OrganizationConnectionResponseModel](docs/OrganizationConnectionResponseModel.md) - [OrganizationConnectionType](docs/OrganizationConnectionType.md) @@ -613,6 +637,7 @@ All URIs are relative to _http://localhost_ - [OrganizationLicense](docs/OrganizationLicense.md) - [OrganizationPublicKeyResponseModel](docs/OrganizationPublicKeyResponseModel.md) - [OrganizationResponseModel](docs/OrganizationResponseModel.md) +- [OrganizationRisksSubscriptionFailureResponseModel](docs/OrganizationRisksSubscriptionFailureResponseModel.md) - [OrganizationSeatRequestModel](docs/OrganizationSeatRequestModel.md) - [OrganizationSponsorshipCreateRequestModel](docs/OrganizationSponsorshipCreateRequestModel.md) - [OrganizationSponsorshipRedeemRequestModel](docs/OrganizationSponsorshipRedeemRequestModel.md) @@ -651,12 +676,14 @@ All URIs are relative to _http://localhost_ - [OrganizationVerifyBankRequestModel](docs/OrganizationVerifyBankRequestModel.md) - [OtherDeviceKeysUpdateRequestModel](docs/OtherDeviceKeysUpdateRequestModel.md) - [PasswordHintRequestModel](docs/PasswordHintRequestModel.md) +- [PasswordManagerPlanFeaturesResponseModel](docs/PasswordManagerPlanFeaturesResponseModel.md) - [PasswordRequestModel](docs/PasswordRequestModel.md) - [PaymentMethodType](docs/PaymentMethodType.md) - [PaymentRequestModel](docs/PaymentRequestModel.md) - [PaymentResponseModel](docs/PaymentResponseModel.md) - [PendingOrganizationAuthRequestResponseModel](docs/PendingOrganizationAuthRequestResponseModel.md) - [PendingOrganizationAuthRequestResponseModelListResponseModel](docs/PendingOrganizationAuthRequestResponseModelListResponseModel.md) +- [PeopleAccessPoliciesRequestModel](docs/PeopleAccessPoliciesRequestModel.md) - [Permissions](docs/Permissions.md) - [PlanResponseModel](docs/PlanResponseModel.md) - [PlanResponseModelListResponseModel](docs/PlanResponseModelListResponseModel.md) @@ -678,6 +705,7 @@ All URIs are relative to _http://localhost_ - [ProfileResponseModel](docs/ProfileResponseModel.md) - [ProjectAccessPoliciesResponseModel](docs/ProjectAccessPoliciesResponseModel.md) - [ProjectCreateRequestModel](docs/ProjectCreateRequestModel.md) +- [ProjectPeopleAccessPoliciesResponseModel](docs/ProjectPeopleAccessPoliciesResponseModel.md) - [ProjectResponseModel](docs/ProjectResponseModel.md) - [ProjectResponseModelListResponseModel](docs/ProjectResponseModelListResponseModel.md) - [ProjectUpdateRequestModel](docs/ProjectUpdateRequestModel.md) @@ -707,6 +735,9 @@ All URIs are relative to _http://localhost_ - [ProviderUserUpdateRequestModel](docs/ProviderUserUpdateRequestModel.md) - [ProviderUserUserDetailsResponseModel](docs/ProviderUserUserDetailsResponseModel.md) - [ProviderUserUserDetailsResponseModelListResponseModel](docs/ProviderUserUserDetailsResponseModelListResponseModel.md) +- [PubKeyCredParam](docs/PubKeyCredParam.md) +- [PublicKeyCredentialDescriptor](docs/PublicKeyCredentialDescriptor.md) +- [PublicKeyCredentialRpEntity](docs/PublicKeyCredentialRpEntity.md) - [PublicKeyCredentialType](docs/PublicKeyCredentialType.md) - [PushRegistrationRequestModel](docs/PushRegistrationRequestModel.md) - [PushSendRequestModel](docs/PushSendRequestModel.md) @@ -714,6 +745,7 @@ All URIs are relative to _http://localhost_ - [PushUpdateRequestModel](docs/PushUpdateRequestModel.md) - [RegisterRequestModel](docs/RegisterRequestModel.md) - [RegisterResponseModel](docs/RegisterResponseModel.md) +- [ResetPasswordWithOrgIdRequestModel](docs/ResetPasswordWithOrgIdRequestModel.md) - [ResponseData](docs/ResponseData.md) - [RevokeAccessTokensRequest](docs/RevokeAccessTokensRequest.md) - [Saml2BindingType](docs/Saml2BindingType.md) @@ -726,6 +758,7 @@ All URIs are relative to _http://localhost_ - [SecretVerificationRequestModel](docs/SecretVerificationRequestModel.md) - [SecretWithProjectsInnerProject](docs/SecretWithProjectsInnerProject.md) - [SecretWithProjectsListResponseModel](docs/SecretWithProjectsListResponseModel.md) +- [SecretsManagerPlanFeaturesResponseModel](docs/SecretsManagerPlanFeaturesResponseModel.md) - [SecretsManagerSubscribeRequestModel](docs/SecretsManagerSubscribeRequestModel.md) - [SecretsManagerSubscriptionUpdateRequestModel](docs/SecretsManagerSubscriptionUpdateRequestModel.md) - [SecretsWithProjectsInnerSecret](docs/SecretsWithProjectsInnerSecret.md) @@ -743,8 +776,8 @@ All URIs are relative to _http://localhost_ - [SendType](docs/SendType.md) - [SendWithIdRequestModel](docs/SendWithIdRequestModel.md) - [ServerConfigResponseModel](docs/ServerConfigResponseModel.md) -- [ServiceAccountAccessPoliciesResponseModel](docs/ServiceAccountAccessPoliciesResponseModel.md) - [ServiceAccountCreateRequestModel](docs/ServiceAccountCreateRequestModel.md) +- [ServiceAccountPeopleAccessPoliciesResponseModel](docs/ServiceAccountPeopleAccessPoliciesResponseModel.md) - [ServiceAccountProjectAccessPolicyResponseModel](docs/ServiceAccountProjectAccessPolicyResponseModel.md) - [ServiceAccountProjectAccessPolicyResponseModelListResponseModel](docs/ServiceAccountProjectAccessPolicyResponseModelListResponseModel.md) - [ServiceAccountResponseModel](docs/ServiceAccountResponseModel.md) @@ -797,9 +830,17 @@ All URIs are relative to _http://localhost_ - [UserLicense](docs/UserLicense.md) - [UserProjectAccessPolicyResponseModel](docs/UserProjectAccessPolicyResponseModel.md) - [UserServiceAccountAccessPolicyResponseModel](docs/UserServiceAccountAccessPolicyResponseModel.md) +- [UserVerificationRequirement](docs/UserVerificationRequirement.md) - [VerifyDeleteRecoverRequestModel](docs/VerifyDeleteRecoverRequestModel.md) - [VerifyEmailRequestModel](docs/VerifyEmailRequestModel.md) - [VerifyOtpRequestModel](docs/VerifyOtpRequestModel.md) +- [WebAuthnCredentialCreateOptionsResponseModel](docs/WebAuthnCredentialCreateOptionsResponseModel.md) +- [WebAuthnCredentialResponseModel](docs/WebAuthnCredentialResponseModel.md) +- [WebAuthnCredentialResponseModelListResponseModel](docs/WebAuthnCredentialResponseModelListResponseModel.md) +- [WebAuthnLoginAssertionOptionsResponseModel](docs/WebAuthnLoginAssertionOptionsResponseModel.md) +- [WebAuthnLoginCredentialCreateRequestModel](docs/WebAuthnLoginCredentialCreateRequestModel.md) +- [WebAuthnLoginCredentialUpdateRequestModel](docs/WebAuthnLoginCredentialUpdateRequestModel.md) +- [WebAuthnPrfStatus](docs/WebAuthnPrfStatus.md) To get access to the crate's generated documentation, use: diff --git a/crates/bitwarden-api-api/src/apis/access_policies_api.rs b/crates/bitwarden-api-api/src/apis/access_policies_api.rs index 9eb40719d..9f1135beb 100644 --- a/crates/bitwarden-api-api/src/apis/access_policies_api.rs +++ b/crates/bitwarden-api-api/src/apis/access_policies_api.rs @@ -58,6 +58,20 @@ pub enum ProjectsIdAccessPoliciesGetError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`projects_id_access_policies_people_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ProjectsIdAccessPoliciesPeopleGetError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`projects_id_access_policies_people_put`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ProjectsIdAccessPoliciesPeoplePutError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`projects_id_access_policies_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -65,17 +79,17 @@ pub enum ProjectsIdAccessPoliciesPostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`service_accounts_id_access_policies_get`] +/// struct for typed errors of method [`service_accounts_id_access_policies_people_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum ServiceAccountsIdAccessPoliciesGetError { +pub enum ServiceAccountsIdAccessPoliciesPeopleGetError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`service_accounts_id_access_policies_post`] +/// struct for typed errors of method [`service_accounts_id_access_policies_people_put`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum ServiceAccountsIdAccessPoliciesPostError { +pub enum ServiceAccountsIdAccessPoliciesPeoplePutError { UnknownValue(serde_json::Value), } @@ -373,6 +387,102 @@ pub async fn projects_id_access_policies_get( } } +pub async fn projects_id_access_policies_people_get( + configuration: &configuration::Configuration, + id: uuid::Uuid, +) -> Result< + crate::models::ProjectPeopleAccessPoliciesResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/projects/{id}/access-policies/people", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn projects_id_access_policies_people_put( + configuration: &configuration::Configuration, + id: uuid::Uuid, + people_access_policies_request_model: Option, +) -> Result< + crate::models::ProjectPeopleAccessPoliciesResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/projects/{id}/access-policies/people", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::PUT, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&people_access_policies_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn projects_id_access_policies_post( configuration: &configuration::Configuration, id: uuid::Uuid, @@ -422,19 +532,19 @@ pub async fn projects_id_access_policies_post( } } -pub async fn service_accounts_id_access_policies_get( +pub async fn service_accounts_id_access_policies_people_get( configuration: &configuration::Configuration, id: uuid::Uuid, ) -> Result< - crate::models::ServiceAccountAccessPoliciesResponseModel, - Error, + crate::models::ServiceAccountPeopleAccessPoliciesResponseModel, + Error, > { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/service-accounts/{id}/access-policies", + "{}/service-accounts/{id}/access-policies/people", local_var_configuration.base_path, id = crate::apis::urlencode(id.to_string()) ); @@ -458,7 +568,7 @@ pub async fn service_accounts_id_access_policies_get( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -469,25 +579,25 @@ pub async fn service_accounts_id_access_policies_get( } } -pub async fn service_accounts_id_access_policies_post( +pub async fn service_accounts_id_access_policies_people_put( configuration: &configuration::Configuration, id: uuid::Uuid, - access_policies_create_request: Option, + people_access_policies_request_model: Option, ) -> Result< - crate::models::ServiceAccountAccessPoliciesResponseModel, - Error, + crate::models::ServiceAccountPeopleAccessPoliciesResponseModel, + Error, > { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/service-accounts/{id}/access-policies", + "{}/service-accounts/{id}/access-policies/people", local_var_configuration.base_path, id = crate::apis::urlencode(id.to_string()) ); let mut local_var_req_builder = - local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + local_var_client.request(reqwest::Method::PUT, local_var_uri_str.as_str()); if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { local_var_req_builder = @@ -496,7 +606,7 @@ pub async fn service_accounts_id_access_policies_post( if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); }; - local_var_req_builder = local_var_req_builder.json(&access_policies_create_request); + local_var_req_builder = local_var_req_builder.json(&people_access_policies_request_model); let local_var_req = local_var_req_builder.build()?; let local_var_resp = local_var_client.execute(local_var_req).await?; @@ -507,7 +617,7 @@ pub async fn service_accounts_id_access_policies_post( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/crates/bitwarden-api-api/src/apis/accounts_api.rs b/crates/bitwarden-api-api/src/apis/accounts_api.rs index 9e3349409..23b1c1d85 100644 --- a/crates/bitwarden-api-api/src/apis/accounts_api.rs +++ b/crates/bitwarden-api-api/src/apis/accounts_api.rs @@ -90,13 +90,6 @@ pub enum AccountsEmailTokenPostError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`accounts_iap_check_post`] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum AccountsIapCheckPostError { - UnknownValue(serde_json::Value), -} - /// struct for typed errors of method [`accounts_kdf_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -787,47 +780,6 @@ pub async fn accounts_email_token_post( } } -pub async fn accounts_iap_check_post( - configuration: &configuration::Configuration, - iap_check_request_model: Option, -) -> Result<(), Error> { - let local_var_configuration = configuration; - - let local_var_client = &local_var_configuration.client; - - let local_var_uri_str = format!("{}/accounts/iap-check", local_var_configuration.base_path); - let mut local_var_req_builder = - local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); - - if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { - local_var_req_builder = - local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); - } - if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { - local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); - }; - local_var_req_builder = local_var_req_builder.json(&iap_check_request_model); - - let local_var_req = local_var_req_builder.build()?; - let local_var_resp = local_var_client.execute(local_var_req).await?; - - let local_var_status = local_var_resp.status(); - let local_var_content = local_var_resp.text().await?; - - if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - Ok(()) - } else { - let local_var_entity: Option = - serde_json::from_str(&local_var_content).ok(); - let local_var_error = ResponseContent { - status: local_var_status, - content: local_var_content, - entity: local_var_entity, - }; - Err(Error::ResponseError(local_var_error)) - } -} - pub async fn accounts_kdf_post( configuration: &configuration::Configuration, kdf_request_model: Option, diff --git a/crates/bitwarden-api-api/src/apis/ciphers_api.rs b/crates/bitwarden-api-api/src/apis/ciphers_api.rs index 4ca7f4969..5a1466c75 100644 --- a/crates/bitwarden-api-api/src/apis/ciphers_api.rs +++ b/crates/bitwarden-api-api/src/apis/ciphers_api.rs @@ -1072,7 +1072,7 @@ pub async fn ciphers_id_attachment_attachment_id_admin_delete( pub async fn ciphers_id_attachment_attachment_id_delete( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_id: &str, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1164,7 +1164,7 @@ pub async fn ciphers_id_attachment_attachment_id_delete_admin_post( pub async fn ciphers_id_attachment_attachment_id_delete_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_id: &str, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1210,7 +1210,7 @@ pub async fn ciphers_id_attachment_attachment_id_delete_post( pub async fn ciphers_id_attachment_attachment_id_get( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_id: &str, ) -> Result> { @@ -1257,7 +1257,7 @@ pub async fn ciphers_id_attachment_attachment_id_get( pub async fn ciphers_id_attachment_attachment_id_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_id: &str, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1303,7 +1303,7 @@ pub async fn ciphers_id_attachment_attachment_id_post( pub async fn ciphers_id_attachment_attachment_id_renew_get( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_id: &str, ) -> Result< crate::models::AttachmentUploadDataResponseModel, @@ -1403,7 +1403,7 @@ pub async fn ciphers_id_attachment_attachment_id_share_post( pub async fn ciphers_id_attachment_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -1447,7 +1447,7 @@ pub async fn ciphers_id_attachment_post( pub async fn ciphers_id_attachment_v2_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, attachment_request_model: Option, ) -> Result> { @@ -1586,7 +1586,7 @@ pub async fn ciphers_id_collections_admin_put( pub async fn ciphers_id_collections_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_collections_request_model: Option, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1632,7 +1632,7 @@ pub async fn ciphers_id_collections_post( pub async fn ciphers_id_collections_put( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_collections_request_model: Option, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1678,7 +1678,7 @@ pub async fn ciphers_id_collections_put( pub async fn ciphers_id_delete( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1810,7 +1810,7 @@ pub async fn ciphers_id_delete_admin_put( pub async fn ciphers_id_delete_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1854,7 +1854,7 @@ pub async fn ciphers_id_delete_post( pub async fn ciphers_id_delete_put( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -1898,7 +1898,7 @@ pub async fn ciphers_id_delete_put( pub async fn ciphers_id_details_get( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -1942,7 +1942,7 @@ pub async fn ciphers_id_details_get( pub async fn ciphers_id_full_details_get( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -1986,7 +1986,7 @@ pub async fn ciphers_id_full_details_get( pub async fn ciphers_id_get( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -2030,7 +2030,7 @@ pub async fn ciphers_id_get( pub async fn ciphers_id_partial_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_partial_request_model: Option, ) -> Result> { let local_var_configuration = configuration; @@ -2076,7 +2076,7 @@ pub async fn ciphers_id_partial_post( pub async fn ciphers_id_partial_put( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_partial_request_model: Option, ) -> Result> { let local_var_configuration = configuration; @@ -2258,7 +2258,7 @@ pub async fn ciphers_id_restore_admin_put( pub async fn ciphers_id_restore_put( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -2302,7 +2302,7 @@ pub async fn ciphers_id_restore_put( pub async fn ciphers_id_share_post( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_share_request_model: Option, ) -> Result> { let local_var_configuration = configuration; @@ -2348,7 +2348,7 @@ pub async fn ciphers_id_share_post( pub async fn ciphers_id_share_put( configuration: &configuration::Configuration, - id: &str, + id: uuid::Uuid, cipher_share_request_model: Option, ) -> Result> { let local_var_configuration = configuration; diff --git a/crates/bitwarden-api-api/src/apis/collections_api.rs b/crates/bitwarden-api-api/src/apis/collections_api.rs index c95ac5529..d6c302538 100644 --- a/crates/bitwarden-api-api/src/apis/collections_api.rs +++ b/crates/bitwarden-api-api/src/apis/collections_api.rs @@ -20,6 +20,13 @@ pub enum CollectionsGetError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_org_id_collections_bulk_access_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsOrgIdCollectionsBulkAccessPostError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_org_id_collections_delete`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -169,9 +176,55 @@ pub async fn collections_get( } } +pub async fn organizations_org_id_collections_bulk_access_post( + configuration: &configuration::Configuration, + org_id: uuid::Uuid, + bulk_collection_access_request_model: Option, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{orgId}/collections/bulk-access", + local_var_configuration.base_path, + orgId = crate::apis::urlencode(org_id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&bulk_collection_access_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_org_id_collections_delete( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, collection_bulk_delete_request_model: Option, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -217,7 +270,7 @@ pub async fn organizations_org_id_collections_delete( pub async fn organizations_org_id_collections_delete_post( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, collection_bulk_delete_request_model: Option, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -449,9 +502,9 @@ pub async fn organizations_org_id_collections_id_delete_post( pub async fn organizations_org_id_collections_id_delete_user_org_user_id_post( configuration: &configuration::Configuration, - org_id: &str, - id: &str, - org_user_id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, + org_user_id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -691,9 +744,9 @@ pub async fn organizations_org_id_collections_id_put( pub async fn organizations_org_id_collections_id_user_org_user_id_delete( configuration: &configuration::Configuration, - org_id: &str, - id: &str, - org_user_id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, + org_user_id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; diff --git a/crates/bitwarden-api-api/src/apis/configuration.rs b/crates/bitwarden-api-api/src/apis/configuration.rs index 6b5e1c3a3..83d56c8a5 100644 --- a/crates/bitwarden-api-api/src/apis/configuration.rs +++ b/crates/bitwarden-api-api/src/apis/configuration.rs @@ -8,8 +8,6 @@ * Generated by: https://openapi-generator.tech */ -use reqwest; - #[derive(Debug, Clone)] pub struct Configuration { pub base_path: String, diff --git a/crates/bitwarden-api-api/src/apis/devices_api.rs b/crates/bitwarden-api-api/src/apis/devices_api.rs index 95564464a..71cfdaade 100644 --- a/crates/bitwarden-api-api/src/apis/devices_api.rs +++ b/crates/bitwarden-api-api/src/apis/devices_api.rs @@ -815,8 +815,8 @@ pub async fn devices_knowndevice_email_identifier_get( pub async fn devices_knowndevice_get( configuration: &configuration::Configuration, - x_request_email: Option<&str>, - x_device_identifier: Option<&str>, + x_request_email: &str, + x_device_identifier: &str, ) -> Result> { let local_var_configuration = configuration; @@ -830,14 +830,10 @@ pub async fn devices_knowndevice_get( local_var_req_builder = local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } - if let Some(local_var_param_value) = x_request_email { - local_var_req_builder = - local_var_req_builder.header("x-Request-Email", local_var_param_value.to_string()); - } - if let Some(local_var_param_value) = x_device_identifier { - local_var_req_builder = - local_var_req_builder.header("x-Device-Identifier", local_var_param_value.to_string()); - } + local_var_req_builder = + local_var_req_builder.header("x-Request-Email", x_request_email.to_string()); + local_var_req_builder = + local_var_req_builder.header("x-Device-Identifier", x_device_identifier.to_string()); if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); }; diff --git a/crates/bitwarden-api-api/src/apis/groups_api.rs b/crates/bitwarden-api-api/src/apis/groups_api.rs index d52fcd200..5918989f4 100644 --- a/crates/bitwarden-api-api/src/apis/groups_api.rs +++ b/crates/bitwarden-api-api/src/apis/groups_api.rs @@ -206,7 +206,7 @@ pub async fn organizations_org_id_groups_delete_post( pub async fn organizations_org_id_groups_get( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, ) -> Result< crate::models::GroupDetailsResponseModelListResponseModel, Error, diff --git a/crates/bitwarden-api-api/src/apis/mod.rs b/crates/bitwarden-api-api/src/apis/mod.rs index 492680582..b99dc592d 100644 --- a/crates/bitwarden-api-api/src/apis/mod.rs +++ b/crates/bitwarden-api-api/src/apis/mod.rs @@ -60,6 +60,37 @@ pub fn urlencode>(s: T) -> String { ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect() } +pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> { + if let serde_json::Value::Object(object) = value { + let mut params = vec![]; + + for (key, value) in object { + match value { + serde_json::Value::Object(_) => params.append(&mut parse_deep_object( + &format!("{}[{}]", prefix, key), + value, + )), + serde_json::Value::Array(array) => { + for (i, value) in array.iter().enumerate() { + params.append(&mut parse_deep_object( + &format!("{}[{}][{}]", prefix, key, i), + value, + )); + } + } + serde_json::Value::String(s) => { + params.push((format!("{}[{}]", prefix, key), s.clone())) + } + _ => params.push((format!("{}[{}]", prefix, key), value.to_string())), + } + } + + return params; + } + + unimplemented!("Only objects are supported with style=deepObject") +} + pub mod access_policies_api; pub mod accounts_api; pub mod accounts_billing_api; @@ -93,6 +124,7 @@ pub mod provider_users_api; pub mod providers_api; pub mod push_api; pub mod secrets_api; +pub mod secrets_manager_events_api; pub mod secrets_manager_porting_api; pub mod self_hosted_organization_licenses_api; pub mod self_hosted_organization_sponsorships_api; @@ -103,5 +135,6 @@ pub mod sync_api; pub mod trash_api; pub mod two_factor_api; pub mod users_api; +pub mod web_authn_api; pub mod configuration; diff --git a/crates/bitwarden-api-api/src/apis/organization_domain_api.rs b/crates/bitwarden-api-api/src/apis/organization_domain_api.rs index 4e10ff78f..c55e95f2a 100644 --- a/crates/bitwarden-api-api/src/apis/organization_domain_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_domain_api.rs @@ -114,7 +114,7 @@ pub async fn organizations_domain_sso_details_post( pub async fn organizations_org_id_domain_get( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, ) -> Result< crate::models::OrganizationDomainResponseModelListResponseModel, Error, @@ -161,8 +161,8 @@ pub async fn organizations_org_id_domain_get( pub async fn organizations_org_id_domain_id_delete( configuration: &configuration::Configuration, - org_id: &str, - id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -207,8 +207,8 @@ pub async fn organizations_org_id_domain_id_delete( pub async fn organizations_org_id_domain_id_get( configuration: &configuration::Configuration, - org_id: &str, - id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, ) -> Result> { let local_var_configuration = configuration; @@ -254,8 +254,8 @@ pub async fn organizations_org_id_domain_id_get( pub async fn organizations_org_id_domain_id_remove_post( configuration: &configuration::Configuration, - org_id: &str, - id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, ) -> Result<(), Error> { let local_var_configuration = configuration; @@ -300,8 +300,8 @@ pub async fn organizations_org_id_domain_id_remove_post( pub async fn organizations_org_id_domain_id_verify_post( configuration: &configuration::Configuration, - org_id: &str, - id: &str, + org_id: uuid::Uuid, + id: uuid::Uuid, ) -> Result< crate::models::OrganizationDomainResponseModel, Error, @@ -349,7 +349,7 @@ pub async fn organizations_org_id_domain_id_verify_post( pub async fn organizations_org_id_domain_post( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, organization_domain_request_model: Option, ) -> Result> { diff --git a/crates/bitwarden-api-api/src/apis/organization_users_api.rs b/crates/bitwarden-api-api/src/apis/organization_users_api.rs index 804a29019..ef9fd864f 100644 --- a/crates/bitwarden-api-api/src/apis/organization_users_api.rs +++ b/crates/bitwarden-api-api/src/apis/organization_users_api.rs @@ -484,7 +484,7 @@ pub async fn organizations_org_id_users_enable_secrets_manager_put( pub async fn organizations_org_id_users_get( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, include_groups: Option, include_collections: Option, ) -> Result< diff --git a/crates/bitwarden-api-api/src/apis/organizations_api.rs b/crates/bitwarden-api-api/src/apis/organizations_api.rs index 6377ef6bf..cd9c3326a 100644 --- a/crates/bitwarden-api-api/src/apis/organizations_api.rs +++ b/crates/bitwarden-api-api/src/apis/organizations_api.rs @@ -48,6 +48,13 @@ pub enum OrganizationsIdCancelPostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_id_collection_management_put`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsIdCollectionManagementPutError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_id_delete`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -62,6 +69,13 @@ pub enum OrganizationsIdDeletePostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_id_enable_collection_enhancements_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsIdEnableCollectionEnhancementsPostError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_id_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -139,6 +153,13 @@ pub enum OrganizationsIdReinstatePostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_id_risks_subscription_failure_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsIdRisksSubscriptionFailureGetError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_id_rotate_api_key_post`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -464,6 +485,58 @@ pub async fn organizations_id_cancel_post( } } +pub async fn organizations_id_collection_management_put( + configuration: &configuration::Configuration, + id: uuid::Uuid, + organization_collection_management_update_request_model: Option< + crate::models::OrganizationCollectionManagementUpdateRequestModel, + >, +) -> Result< + crate::models::OrganizationResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{id}/collection-management", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::PUT, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = + local_var_req_builder.json(&organization_collection_management_update_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_id_delete( configuration: &configuration::Configuration, id: &str, @@ -556,6 +629,50 @@ pub async fn organizations_id_delete_post( } } +pub async fn organizations_id_enable_collection_enhancements_post( + configuration: &configuration::Configuration, + id: uuid::Uuid, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{id}/enable-collection-enhancements", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_id_get( configuration: &configuration::Configuration, id: &str, @@ -1060,6 +1177,53 @@ pub async fn organizations_id_reinstate_post( } } +pub async fn organizations_id_risks_subscription_failure_get( + configuration: &configuration::Configuration, + id: uuid::Uuid, +) -> Result< + crate::models::OrganizationRisksSubscriptionFailureResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{id}/risks-subscription-failure", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_id_rotate_api_key_post( configuration: &configuration::Configuration, id: &str, diff --git a/crates/bitwarden-api-api/src/apis/plans_api.rs b/crates/bitwarden-api-api/src/apis/plans_api.rs index 83a9da2b9..e0430ac66 100644 --- a/crates/bitwarden-api-api/src/apis/plans_api.rs +++ b/crates/bitwarden-api-api/src/apis/plans_api.rs @@ -13,13 +13,6 @@ use reqwest; use super::{configuration, Error}; use crate::apis::ResponseContent; -/// struct for typed errors of method [`plans_all_get`] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum PlansAllGetError { - UnknownValue(serde_json::Value), -} - /// struct for typed errors of method [`plans_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -34,52 +27,6 @@ pub enum PlansSalesTaxRatesGetError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`plans_sm_plans_get`] -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(untagged)] -pub enum PlansSmPlansGetError { - UnknownValue(serde_json::Value), -} - -pub async fn plans_all_get( - configuration: &configuration::Configuration, -) -> Result> { - let local_var_configuration = configuration; - - let local_var_client = &local_var_configuration.client; - - let local_var_uri_str = format!("{}/plans/all", local_var_configuration.base_path); - let mut local_var_req_builder = - local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); - - if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { - local_var_req_builder = - local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); - } - if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { - local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); - }; - - let local_var_req = local_var_req_builder.build()?; - let local_var_resp = local_var_client.execute(local_var_req).await?; - - let local_var_status = local_var_resp.status(); - let local_var_content = local_var_resp.text().await?; - - if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - serde_json::from_str(&local_var_content).map_err(Error::from) - } else { - let local_var_entity: Option = - serde_json::from_str(&local_var_content).ok(); - let local_var_error = ResponseContent { - status: local_var_status, - content: local_var_content, - entity: local_var_entity, - }; - Err(Error::ResponseError(local_var_error)) - } -} - pub async fn plans_get( configuration: &configuration::Configuration, ) -> Result> { @@ -160,42 +107,3 @@ pub async fn plans_sales_tax_rates_get( Err(Error::ResponseError(local_var_error)) } } - -pub async fn plans_sm_plans_get( - configuration: &configuration::Configuration, -) -> Result> { - let local_var_configuration = configuration; - - let local_var_client = &local_var_configuration.client; - - let local_var_uri_str = format!("{}/plans/sm-plans", local_var_configuration.base_path); - let mut local_var_req_builder = - local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); - - if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { - local_var_req_builder = - local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); - } - if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { - local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); - }; - - let local_var_req = local_var_req_builder.build()?; - let local_var_resp = local_var_client.execute(local_var_req).await?; - - let local_var_status = local_var_resp.status(); - let local_var_content = local_var_resp.text().await?; - - if !local_var_status.is_client_error() && !local_var_status.is_server_error() { - serde_json::from_str(&local_var_content).map_err(Error::from) - } else { - let local_var_entity: Option = - serde_json::from_str(&local_var_content).ok(); - let local_var_error = ResponseContent { - status: local_var_status, - content: local_var_content, - entity: local_var_entity, - }; - Err(Error::ResponseError(local_var_error)) - } -} diff --git a/crates/bitwarden-api-api/src/apis/policies_api.rs b/crates/bitwarden-api-api/src/apis/policies_api.rs index bfec61923..1ac26b251 100644 --- a/crates/bitwarden-api-api/src/apis/policies_api.rs +++ b/crates/bitwarden-api-api/src/apis/policies_api.rs @@ -27,6 +27,13 @@ pub enum OrganizationsOrgIdPoliciesInvitedUserGetError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`organizations_org_id_policies_master_password_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum OrganizationsOrgIdPoliciesMasterPasswordGetError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`organizations_org_id_policies_token_get`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -97,8 +104,8 @@ pub async fn organizations_org_id_policies_get( pub async fn organizations_org_id_policies_invited_user_get( configuration: &configuration::Configuration, - org_id: &str, - user_id: Option<&str>, + org_id: uuid::Uuid, + user_id: Option, ) -> Result< crate::models::PolicyResponseModelListResponseModel, Error, @@ -147,12 +154,59 @@ pub async fn organizations_org_id_policies_invited_user_get( } } +pub async fn organizations_org_id_policies_master_password_get( + configuration: &configuration::Configuration, + org_id: uuid::Uuid, +) -> Result< + crate::models::PolicyResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/organizations/{orgId}/policies/master-password", + local_var_configuration.base_path, + orgId = crate::apis::urlencode(org_id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn organizations_org_id_policies_token_get( configuration: &configuration::Configuration, - org_id: &str, + org_id: uuid::Uuid, email: Option<&str>, token: Option<&str>, - organization_user_id: Option<&str>, + organization_user_id: Option, ) -> Result< crate::models::PolicyResponseModelListResponseModel, Error, diff --git a/crates/bitwarden-api-api/src/apis/secrets_manager_events_api.rs b/crates/bitwarden-api-api/src/apis/secrets_manager_events_api.rs new file mode 100644 index 000000000..d651ac32f --- /dev/null +++ b/crates/bitwarden-api-api/src/apis/secrets_manager_events_api.rs @@ -0,0 +1,82 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +use reqwest; + +use super::{configuration, Error}; +use crate::apis::ResponseContent; + +/// struct for typed errors of method [`sm_events_service_accounts_service_account_id_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum SmEventsServiceAccountsServiceAccountIdGetError { + UnknownValue(serde_json::Value), +} + +pub async fn sm_events_service_accounts_service_account_id_get( + configuration: &configuration::Configuration, + service_account_id: uuid::Uuid, + start: Option, + end: Option, + continuation_token: Option<&str>, +) -> Result< + crate::models::EventResponseModelListResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/sm/events/service-accounts/{serviceAccountId}", + local_var_configuration.base_path, + serviceAccountId = crate::apis::urlencode(service_account_id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_str) = start { + local_var_req_builder = + local_var_req_builder.query(&[("start", &local_var_str.to_string())]); + } + if let Some(ref local_var_str) = end { + local_var_req_builder = local_var_req_builder.query(&[("end", &local_var_str.to_string())]); + } + if let Some(ref local_var_str) = continuation_token { + local_var_req_builder = + local_var_req_builder.query(&[("continuationToken", &local_var_str.to_string())]); + } + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} diff --git a/crates/bitwarden-api-api/src/apis/web_authn_api.rs b/crates/bitwarden-api-api/src/apis/web_authn_api.rs new file mode 100644 index 000000000..8c269d783 --- /dev/null +++ b/crates/bitwarden-api-api/src/apis/web_authn_api.rs @@ -0,0 +1,324 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +use reqwest; + +use super::{configuration, Error}; +use crate::apis::ResponseContent; + +/// struct for typed errors of method [`webauthn_assertion_options_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnAssertionOptionsPostError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`webauthn_attestation_options_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnAttestationOptionsPostError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`webauthn_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnGetError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`webauthn_id_delete_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnIdDeletePostError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`webauthn_post`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnPostError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`webauthn_put`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum WebauthnPutError { + UnknownValue(serde_json::Value), +} + +pub async fn webauthn_assertion_options_post( + configuration: &configuration::Configuration, + secret_verification_request_model: Option, +) -> Result< + crate::models::WebAuthnLoginAssertionOptionsResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/webauthn/assertion-options", + local_var_configuration.base_path + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&secret_verification_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn webauthn_attestation_options_post( + configuration: &configuration::Configuration, + secret_verification_request_model: Option, +) -> Result< + crate::models::WebAuthnCredentialCreateOptionsResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/webauthn/attestation-options", + local_var_configuration.base_path + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&secret_verification_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn webauthn_get( + configuration: &configuration::Configuration, +) -> Result> +{ + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/webauthn", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn webauthn_id_delete_post( + configuration: &configuration::Configuration, + id: uuid::Uuid, + secret_verification_request_model: Option, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/webauthn/{id}/delete", + local_var_configuration.base_path, + id = crate::apis::urlencode(id.to_string()) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = local_var_req_builder.json(&secret_verification_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn webauthn_post( + configuration: &configuration::Configuration, + web_authn_login_credential_create_request_model: Option< + crate::models::WebAuthnLoginCredentialCreateRequestModel, + >, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/webauthn", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = + local_var_req_builder.json(&web_authn_login_credential_create_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +pub async fn webauthn_put( + configuration: &configuration::Configuration, + web_authn_login_credential_update_request_model: Option< + crate::models::WebAuthnLoginCredentialUpdateRequestModel, + >, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/webauthn", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::PUT, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + if let Some(ref local_var_token) = local_var_configuration.oauth_access_token { + local_var_req_builder = local_var_req_builder.bearer_auth(local_var_token.to_owned()); + }; + local_var_req_builder = + local_var_req_builder.json(&web_authn_login_credential_update_request_model); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} diff --git a/crates/bitwarden-api-api/src/models/access_policies_create_request.rs b/crates/bitwarden-api-api/src/models/access_policies_create_request.rs index 0b55b52f1..59a11774e 100644 --- a/crates/bitwarden-api-api/src/models/access_policies_create_request.rs +++ b/crates/bitwarden-api-api/src/models/access_policies_create_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessPoliciesCreateRequest { #[serde( rename = "userAccessPolicyRequests", diff --git a/crates/bitwarden-api-api/src/models/access_policy_request.rs b/crates/bitwarden-api-api/src/models/access_policy_request.rs index 7ec692135..81065c5b5 100644 --- a/crates/bitwarden-api-api/src/models/access_policy_request.rs +++ b/crates/bitwarden-api-api/src/models/access_policy_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessPolicyRequest { #[serde(rename = "granteeId")] pub grantee_id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/access_policy_update_request.rs b/crates/bitwarden-api-api/src/models/access_policy_update_request.rs index a783d2a2e..38d7852b0 100644 --- a/crates/bitwarden-api-api/src/models/access_policy_update_request.rs +++ b/crates/bitwarden-api-api/src/models/access_policy_update_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessPolicyUpdateRequest { #[serde(rename = "read")] pub read: bool, diff --git a/crates/bitwarden-api-api/src/models/access_token_create_request_model.rs b/crates/bitwarden-api-api/src/models/access_token_create_request_model.rs index c3c55258b..00a3dfa15 100644 --- a/crates/bitwarden-api-api/src/models/access_token_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/access_token_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessTokenCreateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/access_token_creation_response_model.rs b/crates/bitwarden-api-api/src/models/access_token_creation_response_model.rs index 319108e6a..e5b91a94a 100644 --- a/crates/bitwarden-api-api/src/models/access_token_creation_response_model.rs +++ b/crates/bitwarden-api-api/src/models/access_token_creation_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessTokenCreationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/access_token_response_model.rs b/crates/bitwarden-api-api/src/models/access_token_response_model.rs index 766dfa42b..eb06b0108 100644 --- a/crates/bitwarden-api-api/src/models/access_token_response_model.rs +++ b/crates/bitwarden-api-api/src/models/access_token_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessTokenResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/access_token_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/access_token_response_model_list_response_model.rs index eeb65cc65..2b6fa6d82 100644 --- a/crates/bitwarden-api-api/src/models/access_token_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/access_token_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AccessTokenResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/admin_auth_request_update_request_model.rs b/crates/bitwarden-api-api/src/models/admin_auth_request_update_request_model.rs index ba7f199ce..b3629d3a5 100644 --- a/crates/bitwarden-api-api/src/models/admin_auth_request_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/admin_auth_request_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AdminAuthRequestUpdateRequestModel { #[serde(rename = "encryptedUserKey", skip_serializing_if = "Option::is_none")] pub encrypted_user_key: Option, diff --git a/crates/bitwarden-api-api/src/models/algorithm.rs b/crates/bitwarden-api-api/src/models/algorithm.rs new file mode 100644 index 000000000..315879d54 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/algorithm.rs @@ -0,0 +1,54 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[repr(i64)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, +)] +pub enum Algorithm { + Variant65535 = -65535, + Variant259 = -259, + Variant258 = -258, + Variant257 = -257, + Variant47 = -47, + Variant39 = -39, + Variant38 = -38, + Variant37 = -37, + Variant36 = -36, + Variant35 = -35, + Variant8 = -8, + Variant7 = -7, +} + +impl ToString for Algorithm { + fn to_string(&self) -> String { + match self { + Self::Variant65535 => String::from("-65535"), + Self::Variant259 => String::from("-259"), + Self::Variant258 => String::from("-258"), + Self::Variant257 => String::from("-257"), + Self::Variant47 => String::from("-47"), + Self::Variant39 => String::from("-39"), + Self::Variant38 => String::from("-38"), + Self::Variant37 => String::from("-37"), + Self::Variant36 => String::from("-36"), + Self::Variant35 => String::from("-35"), + Self::Variant8 => String::from("-8"), + Self::Variant7 => String::from("-7"), + } + } +} + +impl Default for Algorithm { + fn default() -> Algorithm { + Self::Variant65535 + } +} diff --git a/crates/bitwarden-api-api/src/models/api_key_response_model.rs b/crates/bitwarden-api-api/src/models/api_key_response_model.rs index 5e28ae677..6c7cde826 100644 --- a/crates/bitwarden-api-api/src/models/api_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/api_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ApiKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/assertion_options.rs b/crates/bitwarden-api-api/src/models/assertion_options.rs new file mode 100644 index 000000000..a7772e88d --- /dev/null +++ b/crates/bitwarden-api-api/src/models/assertion_options.rs @@ -0,0 +1,44 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AssertionOptions { + #[serde(rename = "status", skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(rename = "errorMessage", skip_serializing_if = "Option::is_none")] + pub error_message: Option, + #[serde(rename = "challenge", skip_serializing_if = "Option::is_none")] + pub challenge: Option, + #[serde(rename = "timeout", skip_serializing_if = "Option::is_none")] + pub timeout: Option, + #[serde(rename = "rpId", skip_serializing_if = "Option::is_none")] + pub rp_id: Option, + #[serde(rename = "allowCredentials", skip_serializing_if = "Option::is_none")] + pub allow_credentials: Option>, + #[serde(rename = "userVerification", skip_serializing_if = "Option::is_none")] + pub user_verification: Option, + #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] + pub extensions: Option>, +} + +impl AssertionOptions { + pub fn new() -> AssertionOptions { + AssertionOptions { + status: None, + error_message: None, + challenge: None, + timeout: None, + rp_id: None, + allow_credentials: None, + user_verification: None, + extensions: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/assertion_response.rs b/crates/bitwarden-api-api/src/models/assertion_response.rs new file mode 100644 index 000000000..bf5f1e792 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/assertion_response.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AssertionResponse { + #[serde(rename = "authenticatorData", skip_serializing_if = "Option::is_none")] + pub authenticator_data: Option, + #[serde(rename = "signature", skip_serializing_if = "Option::is_none")] + pub signature: Option, + #[serde(rename = "clientDataJSON", skip_serializing_if = "Option::is_none")] + pub client_data_json: Option, + #[serde(rename = "userHandle", skip_serializing_if = "Option::is_none")] + pub user_handle: Option, +} + +impl AssertionResponse { + pub fn new() -> AssertionResponse { + AssertionResponse { + authenticator_data: None, + signature: None, + client_data_json: None, + user_handle: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/attachment_request_model.rs b/crates/bitwarden-api-api/src/models/attachment_request_model.rs index 9925ee618..8eeedb507 100644 --- a/crates/bitwarden-api-api/src/models/attachment_request_model.rs +++ b/crates/bitwarden-api-api/src/models/attachment_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AttachmentRequestModel { #[serde(rename = "key", skip_serializing_if = "Option::is_none")] pub key: Option, diff --git a/crates/bitwarden-api-api/src/models/attachment_response_model.rs b/crates/bitwarden-api-api/src/models/attachment_response_model.rs index c9066488d..e0616818f 100644 --- a/crates/bitwarden-api-api/src/models/attachment_response_model.rs +++ b/crates/bitwarden-api-api/src/models/attachment_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AttachmentResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/attachment_upload_data_response_model.rs b/crates/bitwarden-api-api/src/models/attachment_upload_data_response_model.rs index 4b9f61825..9a78e5807 100644 --- a/crates/bitwarden-api-api/src/models/attachment_upload_data_response_model.rs +++ b/crates/bitwarden-api-api/src/models/attachment_upload_data_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AttachmentUploadDataResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/attestation_conveyance_preference.rs b/crates/bitwarden-api-api/src/models/attestation_conveyance_preference.rs new file mode 100644 index 000000000..0b8a76151 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/attestation_conveyance_preference.rs @@ -0,0 +1,36 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum AttestationConveyancePreference { + #[serde(rename = "none")] + None, + #[serde(rename = "indirect")] + Indirect, + #[serde(rename = "direct")] + Direct, +} + +impl ToString for AttestationConveyancePreference { + fn to_string(&self) -> String { + match self { + Self::None => String::from("none"), + Self::Indirect => String::from("indirect"), + Self::Direct => String::from("direct"), + } + } +} + +impl Default for AttestationConveyancePreference { + fn default() -> AttestationConveyancePreference { + Self::None + } +} diff --git a/crates/bitwarden-api-api/src/models/auth_request_create_request_model.rs b/crates/bitwarden-api-api/src/models/auth_request_create_request_model.rs index 54eee561c..c092ae47d 100644 --- a/crates/bitwarden-api-api/src/models/auth_request_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/auth_request_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthRequestCreateRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/auth_request_response_model.rs b/crates/bitwarden-api-api/src/models/auth_request_response_model.rs index 8409b4f6c..b6a7438b7 100644 --- a/crates/bitwarden-api-api/src/models/auth_request_response_model.rs +++ b/crates/bitwarden-api-api/src/models/auth_request_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthRequestResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/auth_request_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/auth_request_response_model_list_response_model.rs index 70d96a2ed..32e953d28 100644 --- a/crates/bitwarden-api-api/src/models/auth_request_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/auth_request_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthRequestResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/auth_request_update_request_model.rs b/crates/bitwarden-api-api/src/models/auth_request_update_request_model.rs index 6baf69f8a..9799a5fc7 100644 --- a/crates/bitwarden-api-api/src/models/auth_request_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/auth_request_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthRequestUpdateRequestModel { #[serde(rename = "key", skip_serializing_if = "Option::is_none")] pub key: Option, diff --git a/crates/bitwarden-api-api/src/models/authentication_extensions_client_inputs.rs b/crates/bitwarden-api-api/src/models/authentication_extensions_client_inputs.rs new file mode 100644 index 000000000..cd98f01d1 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/authentication_extensions_client_inputs.rs @@ -0,0 +1,35 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AuthenticationExtensionsClientInputs { + #[serde(rename = "example.extension", skip_serializing_if = "Option::is_none")] + pub example_period_extension: Option, + #[serde(rename = "appid", skip_serializing_if = "Option::is_none")] + pub appid: Option, + #[serde(rename = "authnSel", skip_serializing_if = "Option::is_none")] + pub authn_sel: Option>, + #[serde(rename = "exts", skip_serializing_if = "Option::is_none")] + pub exts: Option, + #[serde(rename = "uvm", skip_serializing_if = "Option::is_none")] + pub uvm: Option, +} + +impl AuthenticationExtensionsClientInputs { + pub fn new() -> AuthenticationExtensionsClientInputs { + AuthenticationExtensionsClientInputs { + example_period_extension: None, + appid: None, + authn_sel: None, + exts: None, + uvm: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/authentication_extensions_client_outputs.rs b/crates/bitwarden-api-api/src/models/authentication_extensions_client_outputs.rs index af7deb6da..2af5ed7c5 100644 --- a/crates/bitwarden-api-api/src/models/authentication_extensions_client_outputs.rs +++ b/crates/bitwarden-api-api/src/models/authentication_extensions_client_outputs.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthenticationExtensionsClientOutputs { #[serde(rename = "example.extension", skip_serializing_if = "Option::is_none")] pub example_period_extension: Option, diff --git a/crates/bitwarden-api-api/src/models/authenticator_assertion_raw_response.rs b/crates/bitwarden-api-api/src/models/authenticator_assertion_raw_response.rs new file mode 100644 index 000000000..ea39efeab --- /dev/null +++ b/crates/bitwarden-api-api/src/models/authenticator_assertion_raw_response.rs @@ -0,0 +1,35 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AuthenticatorAssertionRawResponse { + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "rawId", skip_serializing_if = "Option::is_none")] + pub raw_id: Option, + #[serde(rename = "response", skip_serializing_if = "Option::is_none")] + pub response: Option>, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, + #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] + pub extensions: Option>, +} + +impl AuthenticatorAssertionRawResponse { + pub fn new() -> AuthenticatorAssertionRawResponse { + AuthenticatorAssertionRawResponse { + id: None, + raw_id: None, + response: None, + r#type: None, + extensions: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/authenticator_attachment.rs b/crates/bitwarden-api-api/src/models/authenticator_attachment.rs new file mode 100644 index 000000000..8e2d2df19 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/authenticator_attachment.rs @@ -0,0 +1,33 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum AuthenticatorAttachment { + #[serde(rename = "platform")] + Platform, + #[serde(rename = "cross-platform")] + CrossPlatform, +} + +impl ToString for AuthenticatorAttachment { + fn to_string(&self) -> String { + match self { + Self::Platform => String::from("platform"), + Self::CrossPlatform => String::from("cross-platform"), + } + } +} + +impl Default for AuthenticatorAttachment { + fn default() -> AuthenticatorAttachment { + Self::Platform + } +} diff --git a/crates/bitwarden-api-api/src/models/authenticator_attestation_raw_response.rs b/crates/bitwarden-api-api/src/models/authenticator_attestation_raw_response.rs index 3e2b4c05c..8763ab261 100644 --- a/crates/bitwarden-api-api/src/models/authenticator_attestation_raw_response.rs +++ b/crates/bitwarden-api-api/src/models/authenticator_attestation_raw_response.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct AuthenticatorAttestationRawResponse { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/authenticator_selection.rs b/crates/bitwarden-api-api/src/models/authenticator_selection.rs new file mode 100644 index 000000000..4159eddde --- /dev/null +++ b/crates/bitwarden-api-api/src/models/authenticator_selection.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AuthenticatorSelection { + #[serde( + rename = "authenticatorAttachment", + skip_serializing_if = "Option::is_none" + )] + pub authenticator_attachment: Option, + #[serde(rename = "requireResidentKey", skip_serializing_if = "Option::is_none")] + pub require_resident_key: Option, + #[serde(rename = "userVerification", skip_serializing_if = "Option::is_none")] + pub user_verification: Option, +} + +impl AuthenticatorSelection { + pub fn new() -> AuthenticatorSelection { + AuthenticatorSelection { + authenticator_attachment: None, + require_resident_key: None, + user_verification: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/authenticator_transport.rs b/crates/bitwarden-api-api/src/models/authenticator_transport.rs new file mode 100644 index 000000000..0773f8138 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/authenticator_transport.rs @@ -0,0 +1,39 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum AuthenticatorTransport { + #[serde(rename = "usb")] + Usb, + #[serde(rename = "nfc")] + Nfc, + #[serde(rename = "ble")] + Ble, + #[serde(rename = "internal")] + Internal, +} + +impl ToString for AuthenticatorTransport { + fn to_string(&self) -> String { + match self { + Self::Usb => String::from("usb"), + Self::Nfc => String::from("nfc"), + Self::Ble => String::from("ble"), + Self::Internal => String::from("internal"), + } + } +} + +impl Default for AuthenticatorTransport { + fn default() -> AuthenticatorTransport { + Self::Usb + } +} diff --git a/crates/bitwarden-api-api/src/models/base_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/base_access_policy_response_model.rs index 39efd3242..cb15dde0b 100644 --- a/crates/bitwarden-api-api/src/models/base_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/base_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BaseAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/base_secret_response_model.rs b/crates/bitwarden-api-api/src/models/base_secret_response_model.rs index d2db29bc7..2b486020f 100644 --- a/crates/bitwarden-api-api/src/models/base_secret_response_model.rs +++ b/crates/bitwarden-api-api/src/models/base_secret_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BaseSecretResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/base_secret_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/base_secret_response_model_list_response_model.rs index f65cb215d..650333a80 100644 --- a/crates/bitwarden-api-api/src/models/base_secret_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/base_secret_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BaseSecretResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_customer_discount.rs b/crates/bitwarden-api-api/src/models/billing_customer_discount.rs index 61f695d70..71fc4f46d 100644 --- a/crates/bitwarden-api-api/src/models/billing_customer_discount.rs +++ b/crates/bitwarden-api-api/src/models/billing_customer_discount.rs @@ -8,12 +8,16 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingCustomerDiscount { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, #[serde(rename = "active", skip_serializing_if = "Option::is_none")] pub active: Option, + #[serde(rename = "percentOff", skip_serializing_if = "Option::is_none")] + pub percent_off: Option, + #[serde(rename = "appliesTo", skip_serializing_if = "Option::is_none")] + pub applies_to: Option>, } impl BillingCustomerDiscount { @@ -21,6 +25,8 @@ impl BillingCustomerDiscount { BillingCustomerDiscount { id: None, active: None, + percent_off: None, + applies_to: None, } } } diff --git a/crates/bitwarden-api-api/src/models/billing_history_response_model.rs b/crates/bitwarden-api-api/src/models/billing_history_response_model.rs index 54f00397f..f1550bcae 100644 --- a/crates/bitwarden-api-api/src/models/billing_history_response_model.rs +++ b/crates/bitwarden-api-api/src/models/billing_history_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingHistoryResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_invoice.rs b/crates/bitwarden-api-api/src/models/billing_invoice.rs index 893930723..23dcb17d2 100644 --- a/crates/bitwarden-api-api/src/models/billing_invoice.rs +++ b/crates/bitwarden-api-api/src/models/billing_invoice.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingInvoice { #[serde(rename = "amount", skip_serializing_if = "Option::is_none")] pub amount: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_payment_response_model.rs b/crates/bitwarden-api-api/src/models/billing_payment_response_model.rs index eb7bc10db..2b1f929a7 100644 --- a/crates/bitwarden-api-api/src/models/billing_payment_response_model.rs +++ b/crates/bitwarden-api-api/src/models/billing_payment_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingPaymentResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_response_model.rs b/crates/bitwarden-api-api/src/models/billing_response_model.rs index 7637917e1..4a3cbea6e 100644 --- a/crates/bitwarden-api-api/src/models/billing_response_model.rs +++ b/crates/bitwarden-api-api/src/models/billing_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_source.rs b/crates/bitwarden-api-api/src/models/billing_source.rs index da231d360..cff096377 100644 --- a/crates/bitwarden-api-api/src/models/billing_source.rs +++ b/crates/bitwarden-api-api/src/models/billing_source.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingSource { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_subscription.rs b/crates/bitwarden-api-api/src/models/billing_subscription.rs index 0c89977ed..8a0c3aec0 100644 --- a/crates/bitwarden-api-api/src/models/billing_subscription.rs +++ b/crates/bitwarden-api-api/src/models/billing_subscription.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingSubscription { #[serde(rename = "trialStartDate", skip_serializing_if = "Option::is_none")] pub trial_start_date: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_subscription_item.rs b/crates/bitwarden-api-api/src/models/billing_subscription_item.rs index 7a9693eb2..0e40278c5 100644 --- a/crates/bitwarden-api-api/src/models/billing_subscription_item.rs +++ b/crates/bitwarden-api-api/src/models/billing_subscription_item.rs @@ -8,8 +8,10 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingSubscriptionItem { + #[serde(rename = "productId", skip_serializing_if = "Option::is_none")] + pub product_id: Option, #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, #[serde(rename = "amount", skip_serializing_if = "Option::is_none")] @@ -28,20 +30,18 @@ pub struct BillingSubscriptionItem { skip_serializing_if = "Option::is_none" )] pub addon_subscription_item: Option, - #[serde(rename = "bitwardenProduct", skip_serializing_if = "Option::is_none")] - pub bitwarden_product: Option, } impl BillingSubscriptionItem { pub fn new() -> BillingSubscriptionItem { BillingSubscriptionItem { + product_id: None, name: None, amount: None, quantity: None, interval: None, sponsored_subscription_item: None, addon_subscription_item: None, - bitwarden_product: None, } } } diff --git a/crates/bitwarden-api-api/src/models/billing_subscription_upcoming_invoice.rs b/crates/bitwarden-api-api/src/models/billing_subscription_upcoming_invoice.rs index c4b741a7a..a2e183a94 100644 --- a/crates/bitwarden-api-api/src/models/billing_subscription_upcoming_invoice.rs +++ b/crates/bitwarden-api-api/src/models/billing_subscription_upcoming_invoice.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingSubscriptionUpcomingInvoice { #[serde(rename = "amount", skip_serializing_if = "Option::is_none")] pub amount: Option, diff --git a/crates/bitwarden-api-api/src/models/billing_transaction.rs b/crates/bitwarden-api-api/src/models/billing_transaction.rs index 2343afb8b..666d13919 100644 --- a/crates/bitwarden-api-api/src/models/billing_transaction.rs +++ b/crates/bitwarden-api-api/src/models/billing_transaction.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BillingTransaction { #[serde(rename = "createdDate", skip_serializing_if = "Option::is_none")] pub created_date: Option, diff --git a/crates/bitwarden-api-api/src/models/bit_pay_invoice_request_model.rs b/crates/bitwarden-api-api/src/models/bit_pay_invoice_request_model.rs index c94e9d565..9491aabb0 100644 --- a/crates/bitwarden-api-api/src/models/bit_pay_invoice_request_model.rs +++ b/crates/bitwarden-api-api/src/models/bit_pay_invoice_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BitPayInvoiceRequestModel { #[serde(rename = "userId", skip_serializing_if = "Option::is_none")] pub user_id: Option, diff --git a/crates/bitwarden-api-api/src/models/bulk_collection_access_request_model.rs b/crates/bitwarden-api-api/src/models/bulk_collection_access_request_model.rs new file mode 100644 index 000000000..a7fd75d85 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/bulk_collection_access_request_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct BulkCollectionAccessRequestModel { + #[serde(rename = "collectionIds", skip_serializing_if = "Option::is_none")] + pub collection_ids: Option>, + #[serde(rename = "groups", skip_serializing_if = "Option::is_none")] + pub groups: Option>, + #[serde(rename = "users", skip_serializing_if = "Option::is_none")] + pub users: Option>, +} + +impl BulkCollectionAccessRequestModel { + pub fn new() -> BulkCollectionAccessRequestModel { + BulkCollectionAccessRequestModel { + collection_ids: None, + groups: None, + users: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/bulk_delete_response_model.rs b/crates/bitwarden-api-api/src/models/bulk_delete_response_model.rs index 8bab4b18a..0d9b9e074 100644 --- a/crates/bitwarden-api-api/src/models/bulk_delete_response_model.rs +++ b/crates/bitwarden-api-api/src/models/bulk_delete_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BulkDeleteResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/bulk_delete_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/bulk_delete_response_model_list_response_model.rs index 94d644d0b..800ffeb32 100644 --- a/crates/bitwarden-api-api/src/models/bulk_delete_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/bulk_delete_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BulkDeleteResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/bulk_deny_admin_auth_request_request_model.rs b/crates/bitwarden-api-api/src/models/bulk_deny_admin_auth_request_request_model.rs index 5108fb419..b870cc77b 100644 --- a/crates/bitwarden-api-api/src/models/bulk_deny_admin_auth_request_request_model.rs +++ b/crates/bitwarden-api-api/src/models/bulk_deny_admin_auth_request_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct BulkDenyAdminAuthRequestRequestModel { #[serde(rename = "ids", skip_serializing_if = "Option::is_none")] pub ids: Option>, diff --git a/crates/bitwarden-api-api/src/models/cipher_attachment_model.rs b/crates/bitwarden-api-api/src/models/cipher_attachment_model.rs index 7d55716dd..93beabc99 100644 --- a/crates/bitwarden-api-api/src/models/cipher_attachment_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_attachment_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherAttachmentModel { #[serde(rename = "fileName", skip_serializing_if = "Option::is_none")] pub file_name: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_bulk_delete_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_bulk_delete_request_model.rs index 22202fcaf..b709c5622 100644 --- a/crates/bitwarden-api-api/src/models/cipher_bulk_delete_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_bulk_delete_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherBulkDeleteRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_bulk_move_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_bulk_move_request_model.rs index eca93c3a7..b9e2b61f5 100644 --- a/crates/bitwarden-api-api/src/models/cipher_bulk_move_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_bulk_move_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherBulkMoveRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_bulk_restore_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_bulk_restore_request_model.rs index 9fe99c9ce..3d6ad9338 100644 --- a/crates/bitwarden-api-api/src/models/cipher_bulk_restore_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_bulk_restore_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherBulkRestoreRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_bulk_share_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_bulk_share_request_model.rs index c5d906e0f..92dff066c 100644 --- a/crates/bitwarden-api-api/src/models/cipher_bulk_share_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_bulk_share_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherBulkShareRequestModel { #[serde(rename = "collectionIds")] pub collection_ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_card_model.rs b/crates/bitwarden-api-api/src/models/cipher_card_model.rs index 173e4e55c..eae29bc84 100644 --- a/crates/bitwarden-api-api/src/models/cipher_card_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_card_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherCardModel { #[serde(rename = "cardholderName", skip_serializing_if = "Option::is_none")] pub cardholder_name: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_collections_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_collections_request_model.rs index cdd2649a9..8bdf4be41 100644 --- a/crates/bitwarden-api-api/src/models/cipher_collections_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_collections_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherCollectionsRequestModel { #[serde(rename = "collectionIds")] pub collection_ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_create_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_create_request_model.rs index 272343066..bbfdf3c03 100644 --- a/crates/bitwarden-api-api/src/models/cipher_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherCreateRequestModel { #[serde(rename = "collectionIds", skip_serializing_if = "Option::is_none")] pub collection_ids: Option>, diff --git a/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs index 289169e41..1dd69ecd9 100644 --- a/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_details_response_model_list_response_model.rs index 9e840e978..8da076327 100644 --- a/crates/bitwarden-api-api/src/models/cipher_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_fido2_credential_model.rs b/crates/bitwarden-api-api/src/models/cipher_fido2_credential_model.rs new file mode 100644 index 000000000..95de4bc28 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/cipher_fido2_credential_model.rs @@ -0,0 +1,59 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct CipherFido2CredentialModel { + #[serde(rename = "credentialId", skip_serializing_if = "Option::is_none")] + pub credential_id: Option, + #[serde(rename = "keyType", skip_serializing_if = "Option::is_none")] + pub key_type: Option, + #[serde(rename = "keyAlgorithm", skip_serializing_if = "Option::is_none")] + pub key_algorithm: Option, + #[serde(rename = "keyCurve", skip_serializing_if = "Option::is_none")] + pub key_curve: Option, + #[serde(rename = "keyValue", skip_serializing_if = "Option::is_none")] + pub key_value: Option, + #[serde(rename = "rpId", skip_serializing_if = "Option::is_none")] + pub rp_id: Option, + #[serde(rename = "rpName", skip_serializing_if = "Option::is_none")] + pub rp_name: Option, + #[serde(rename = "userHandle", skip_serializing_if = "Option::is_none")] + pub user_handle: Option, + #[serde(rename = "userName", skip_serializing_if = "Option::is_none")] + pub user_name: Option, + #[serde(rename = "userDisplayName", skip_serializing_if = "Option::is_none")] + pub user_display_name: Option, + #[serde(rename = "counter", skip_serializing_if = "Option::is_none")] + pub counter: Option, + #[serde(rename = "discoverable", skip_serializing_if = "Option::is_none")] + pub discoverable: Option, + #[serde(rename = "creationDate")] + pub creation_date: String, +} + +impl CipherFido2CredentialModel { + pub fn new(creation_date: String) -> CipherFido2CredentialModel { + CipherFido2CredentialModel { + credential_id: None, + key_type: None, + key_algorithm: None, + key_curve: None, + key_value: None, + rp_id: None, + rp_name: None, + user_handle: None, + user_name: None, + user_display_name: None, + counter: None, + discoverable: None, + creation_date, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/cipher_field_model.rs b/crates/bitwarden-api-api/src/models/cipher_field_model.rs index 937e52e33..3b1700dd6 100644 --- a/crates/bitwarden-api-api/src/models/cipher_field_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_field_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherFieldModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_identity_model.rs b/crates/bitwarden-api-api/src/models/cipher_identity_model.rs index 54463ad3a..e2e629398 100644 --- a/crates/bitwarden-api-api/src/models/cipher_identity_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_identity_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherIdentityModel { #[serde(rename = "title", skip_serializing_if = "Option::is_none")] pub title: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_login_model.rs b/crates/bitwarden-api-api/src/models/cipher_login_model.rs index d9f531154..159bee7cd 100644 --- a/crates/bitwarden-api-api/src/models/cipher_login_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_login_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherLoginModel { #[serde(rename = "uri", skip_serializing_if = "Option::is_none")] pub uri: Option, @@ -27,6 +27,8 @@ pub struct CipherLoginModel { pub totp: Option, #[serde(rename = "autofillOnPageLoad", skip_serializing_if = "Option::is_none")] pub autofill_on_page_load: Option, + #[serde(rename = "fido2Credentials", skip_serializing_if = "Option::is_none")] + pub fido2_credentials: Option>, } impl CipherLoginModel { @@ -39,6 +41,7 @@ impl CipherLoginModel { password_revision_date: None, totp: None, autofill_on_page_load: None, + fido2_credentials: None, } } } diff --git a/crates/bitwarden-api-api/src/models/cipher_login_uri_model.rs b/crates/bitwarden-api-api/src/models/cipher_login_uri_model.rs index 07358be79..39b6139c7 100644 --- a/crates/bitwarden-api-api/src/models/cipher_login_uri_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_login_uri_model.rs @@ -8,10 +8,12 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherLoginUriModel { #[serde(rename = "uri", skip_serializing_if = "Option::is_none")] pub uri: Option, + #[serde(rename = "uriChecksum", skip_serializing_if = "Option::is_none")] + pub uri_checksum: Option, #[serde(rename = "match", skip_serializing_if = "Option::is_none")] pub r#match: Option, } @@ -20,6 +22,7 @@ impl CipherLoginUriModel { pub fn new() -> CipherLoginUriModel { CipherLoginUriModel { uri: None, + uri_checksum: None, r#match: None, } } diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs index 1aa5b8e3b..bf8e29707 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherMiniDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model_list_response_model.rs index f0c30765f..8fbdaa67c 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherMiniDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs index c96ddfd18..b6e77e2a2 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherMiniResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_mini_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_mini_response_model_list_response_model.rs index 10dbe91ec..ccae92e9e 100644 --- a/crates/bitwarden-api-api/src/models/cipher_mini_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_mini_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherMiniResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_partial_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_partial_request_model.rs index 791dc52d1..f911ef5cb 100644 --- a/crates/bitwarden-api-api/src/models/cipher_partial_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_partial_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherPartialRequestModel { #[serde(rename = "folderId", skip_serializing_if = "Option::is_none")] pub folder_id: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_password_history_model.rs b/crates/bitwarden-api-api/src/models/cipher_password_history_model.rs index b7ea59de0..4ab05138a 100644 --- a/crates/bitwarden-api-api/src/models/cipher_password_history_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_password_history_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherPasswordHistoryModel { #[serde(rename = "password")] pub password: String, diff --git a/crates/bitwarden-api-api/src/models/cipher_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_request_model.rs index 2e445802b..8f8d17312 100644 --- a/crates/bitwarden-api-api/src/models/cipher_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherRequestModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_response_model.rs index 59831e6fb..bd9c360b3 100644 --- a/crates/bitwarden-api-api/src/models/cipher_response_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_secure_note_model.rs b/crates/bitwarden-api-api/src/models/cipher_secure_note_model.rs index 6cb7a0a2a..a1cb38421 100644 --- a/crates/bitwarden-api-api/src/models/cipher_secure_note_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_secure_note_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherSecureNoteModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/cipher_share_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_share_request_model.rs index ec5cdab25..86dcb3454 100644 --- a/crates/bitwarden-api-api/src/models/cipher_share_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_share_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherShareRequestModel { #[serde(rename = "collectionIds")] pub collection_ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs index 093d2e5d9..665bd4b4d 100644 --- a/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs +++ b/crates/bitwarden-api-api/src/models/cipher_with_id_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CipherWithIdRequestModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_access_details_response_model.rs b/crates/bitwarden-api-api/src/models/collection_access_details_response_model.rs index faaf5b47a..99ba1ed9b 100644 --- a/crates/bitwarden-api-api/src/models/collection_access_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_access_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionAccessDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_access_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/collection_access_details_response_model_list_response_model.rs index 21d388fdf..89b0cb89a 100644 --- a/crates/bitwarden-api-api/src/models/collection_access_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_access_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionAccessDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_bulk_delete_request_model.rs b/crates/bitwarden-api-api/src/models/collection_bulk_delete_request_model.rs index 7d2d5d8fe..d919294b9 100644 --- a/crates/bitwarden-api-api/src/models/collection_bulk_delete_request_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_bulk_delete_request_model.rs @@ -8,19 +8,14 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionBulkDeleteRequestModel { #[serde(rename = "ids")] - pub ids: Vec, - #[serde(rename = "organizationId", skip_serializing_if = "Option::is_none")] - pub organization_id: Option, + pub ids: Vec, } impl CollectionBulkDeleteRequestModel { - pub fn new(ids: Vec) -> CollectionBulkDeleteRequestModel { - CollectionBulkDeleteRequestModel { - ids, - organization_id: None, - } + pub fn new(ids: Vec) -> CollectionBulkDeleteRequestModel { + CollectionBulkDeleteRequestModel { ids } } } diff --git a/crates/bitwarden-api-api/src/models/collection_details_response_model.rs b/crates/bitwarden-api-api/src/models/collection_details_response_model.rs index f364a98e8..3275bb104 100644 --- a/crates/bitwarden-api-api/src/models/collection_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -24,6 +24,8 @@ pub struct CollectionDetailsResponseModel { pub read_only: Option, #[serde(rename = "hidePasswords", skip_serializing_if = "Option::is_none")] pub hide_passwords: Option, + #[serde(rename = "manage", skip_serializing_if = "Option::is_none")] + pub manage: Option, } impl CollectionDetailsResponseModel { @@ -36,6 +38,7 @@ impl CollectionDetailsResponseModel { external_id: None, read_only: None, hide_passwords: None, + manage: None, } } } diff --git a/crates/bitwarden-api-api/src/models/collection_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/collection_details_response_model_list_response_model.rs index 8e71cb637..e505be1dd 100644 --- a/crates/bitwarden-api-api/src/models/collection_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_request_model.rs b/crates/bitwarden-api-api/src/models/collection_request_model.rs index 3b3449d8f..6a67c959c 100644 --- a/crates/bitwarden-api-api/src/models/collection_request_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/collection_response_model.rs b/crates/bitwarden-api-api/src/models/collection_response_model.rs index 580adc1bb..091a88fea 100644 --- a/crates/bitwarden-api-api/src/models/collection_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/collection_response_model_list_response_model.rs index 6a5e3720d..943be4ca5 100644 --- a/crates/bitwarden-api-api/src/models/collection_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/collection_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/collection_with_id_request_model.rs index 659dbf617..ae621c621 100644 --- a/crates/bitwarden-api-api/src/models/collection_with_id_request_model.rs +++ b/crates/bitwarden-api-api/src/models/collection_with_id_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct CollectionWithIdRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/config_response_model.rs b/crates/bitwarden-api-api/src/models/config_response_model.rs index 6ac6d935c..3d087338f 100644 --- a/crates/bitwarden-api-api/src/models/config_response_model.rs +++ b/crates/bitwarden-api-api/src/models/config_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ConfigResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/credential_create_options.rs b/crates/bitwarden-api-api/src/models/credential_create_options.rs new file mode 100644 index 000000000..57d6799f9 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/credential_create_options.rs @@ -0,0 +1,56 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct CredentialCreateOptions { + #[serde(rename = "status", skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(rename = "errorMessage", skip_serializing_if = "Option::is_none")] + pub error_message: Option, + #[serde(rename = "rp", skip_serializing_if = "Option::is_none")] + pub rp: Option>, + #[serde(rename = "user", skip_serializing_if = "Option::is_none")] + pub user: Option>, + #[serde(rename = "challenge", skip_serializing_if = "Option::is_none")] + pub challenge: Option, + #[serde(rename = "pubKeyCredParams", skip_serializing_if = "Option::is_none")] + pub pub_key_cred_params: Option>, + #[serde(rename = "timeout", skip_serializing_if = "Option::is_none")] + pub timeout: Option, + #[serde(rename = "attestation", skip_serializing_if = "Option::is_none")] + pub attestation: Option, + #[serde( + rename = "authenticatorSelection", + skip_serializing_if = "Option::is_none" + )] + pub authenticator_selection: Option>, + #[serde(rename = "excludeCredentials", skip_serializing_if = "Option::is_none")] + pub exclude_credentials: Option>, + #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] + pub extensions: Option>, +} + +impl CredentialCreateOptions { + pub fn new() -> CredentialCreateOptions { + CredentialCreateOptions { + status: None, + error_message: None, + rp: None, + user: None, + challenge: None, + pub_key_cred_params: None, + timeout: None, + attestation: None, + authenticator_selection: None, + exclude_credentials: None, + extensions: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/delete_recover_request_model.rs b/crates/bitwarden-api-api/src/models/delete_recover_request_model.rs index 4a4026d98..a065a1724 100644 --- a/crates/bitwarden-api-api/src/models/delete_recover_request_model.rs +++ b/crates/bitwarden-api-api/src/models/delete_recover_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeleteRecoverRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/device_keys_request_model.rs b/crates/bitwarden-api-api/src/models/device_keys_request_model.rs index 4b6fdbb69..4864103b8 100644 --- a/crates/bitwarden-api-api/src/models/device_keys_request_model.rs +++ b/crates/bitwarden-api-api/src/models/device_keys_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceKeysRequestModel { #[serde(rename = "encryptedUserKey")] pub encrypted_user_key: String, diff --git a/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs b/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs index 65d82513c..8000d96fe 100644 --- a/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/device_keys_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceKeysUpdateRequestModel { #[serde(rename = "encryptedPublicKey")] pub encrypted_public_key: String, diff --git a/crates/bitwarden-api-api/src/models/device_request_model.rs b/crates/bitwarden-api-api/src/models/device_request_model.rs index 556350265..856801792 100644 --- a/crates/bitwarden-api-api/src/models/device_request_model.rs +++ b/crates/bitwarden-api-api/src/models/device_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceRequestModel { #[serde(rename = "type")] pub r#type: crate::models::DeviceType, diff --git a/crates/bitwarden-api-api/src/models/device_response_model.rs b/crates/bitwarden-api-api/src/models/device_response_model.rs index c6dc76d96..08a7bfe2f 100644 --- a/crates/bitwarden-api-api/src/models/device_response_model.rs +++ b/crates/bitwarden-api-api/src/models/device_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/device_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/device_response_model_list_response_model.rs index 47ab93fae..6db95f61f 100644 --- a/crates/bitwarden-api-api/src/models/device_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/device_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/device_token_request_model.rs b/crates/bitwarden-api-api/src/models/device_token_request_model.rs index 1e0b8b3b0..295d8545d 100644 --- a/crates/bitwarden-api-api/src/models/device_token_request_model.rs +++ b/crates/bitwarden-api-api/src/models/device_token_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceTokenRequestModel { #[serde(rename = "pushToken", skip_serializing_if = "Option::is_none")] pub push_token: Option, diff --git a/crates/bitwarden-api-api/src/models/device_type.rs b/crates/bitwarden-api-api/src/models/device_type.rs index b6785618a..26bbc7a52 100644 --- a/crates/bitwarden-api-api/src/models/device_type.rs +++ b/crates/bitwarden-api-api/src/models/device_type.rs @@ -37,6 +37,9 @@ pub enum DeviceType { Variant20 = 20, Variant21 = 21, Variant22 = 22, + Variant23 = 23, + Variant24 = 24, + Variant25 = 25, } impl ToString for DeviceType { @@ -65,6 +68,9 @@ impl ToString for DeviceType { Self::Variant20 => String::from("20"), Self::Variant21 => String::from("21"), Self::Variant22 => String::from("22"), + Self::Variant23 => String::from("23"), + Self::Variant24 => String::from("24"), + Self::Variant25 => String::from("25"), } } } diff --git a/crates/bitwarden-api-api/src/models/device_verification_request_model.rs b/crates/bitwarden-api-api/src/models/device_verification_request_model.rs index bba9b491a..e6a6907f5 100644 --- a/crates/bitwarden-api-api/src/models/device_verification_request_model.rs +++ b/crates/bitwarden-api-api/src/models/device_verification_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceVerificationRequestModel { #[serde(rename = "unknownDeviceVerificationEnabled")] pub unknown_device_verification_enabled: bool, diff --git a/crates/bitwarden-api-api/src/models/device_verification_response_model.rs b/crates/bitwarden-api-api/src/models/device_verification_response_model.rs index e969a8d5b..e9077828b 100644 --- a/crates/bitwarden-api-api/src/models/device_verification_response_model.rs +++ b/crates/bitwarden-api-api/src/models/device_verification_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DeviceVerificationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/domains_response_model.rs b/crates/bitwarden-api-api/src/models/domains_response_model.rs index 3e4cc73db..8ccab95c1 100644 --- a/crates/bitwarden-api-api/src/models/domains_response_model.rs +++ b/crates/bitwarden-api-api/src/models/domains_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct DomainsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/email_request_model.rs b/crates/bitwarden-api-api/src/models/email_request_model.rs index 24a205f63..e8db8de94 100644 --- a/crates/bitwarden-api-api/src/models/email_request_model.rs +++ b/crates/bitwarden-api-api/src/models/email_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmailRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/email_token_request_model.rs b/crates/bitwarden-api-api/src/models/email_token_request_model.rs index ed29f776c..09ea36974 100644 --- a/crates/bitwarden-api-api/src/models/email_token_request_model.rs +++ b/crates/bitwarden-api-api/src/models/email_token_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmailTokenRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model.rs index d6b7945e6..6869f6709 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessGranteeDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model_list_response_model.rs index 1fc800217..9d76aaea9 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_grantee_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessGranteeDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model.rs index ecf1eb186..902cd938c 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessGrantorDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model_list_response_model.rs index 51cbabb3e..414f5037f 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_grantor_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessGrantorDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_invite_request_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_invite_request_model.rs index 3ec945bc6..2d85903aa 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_invite_request_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_invite_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessInviteRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_password_request_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_password_request_model.rs index 6687a57fe..091a31495 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_password_request_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_password_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessPasswordRequestModel { #[serde(rename = "newMasterPasswordHash")] pub new_master_password_hash: String, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_takeover_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_takeover_response_model.rs index ce22542ea..c4bd0786a 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_takeover_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_takeover_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessTakeoverResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_update_request_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_update_request_model.rs index 184e4288b..433041c35 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessUpdateRequestModel { #[serde(rename = "type")] pub r#type: crate::models::EmergencyAccessType, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_view_response_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_view_response_model.rs index 066162dc1..4e58cda5e 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_view_response_model.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_view_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EmergencyAccessViewResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/emergency_access_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/emergency_access_with_id_request_model.rs new file mode 100644 index 000000000..45d16e39b --- /dev/null +++ b/crates/bitwarden-api-api/src/models/emergency_access_with_id_request_model.rs @@ -0,0 +1,36 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct EmergencyAccessWithIdRequestModel { + #[serde(rename = "type")] + pub r#type: crate::models::EmergencyAccessType, + #[serde(rename = "waitTimeDays")] + pub wait_time_days: i32, + #[serde(rename = "keyEncrypted", skip_serializing_if = "Option::is_none")] + pub key_encrypted: Option, + #[serde(rename = "id")] + pub id: uuid::Uuid, +} + +impl EmergencyAccessWithIdRequestModel { + pub fn new( + r#type: crate::models::EmergencyAccessType, + wait_time_days: i32, + id: uuid::Uuid, + ) -> EmergencyAccessWithIdRequestModel { + EmergencyAccessWithIdRequestModel { + r#type, + wait_time_days, + key_encrypted: None, + id, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/environment_config_response_model.rs b/crates/bitwarden-api-api/src/models/environment_config_response_model.rs index 1cceee850..9bb550571 100644 --- a/crates/bitwarden-api-api/src/models/environment_config_response_model.rs +++ b/crates/bitwarden-api-api/src/models/environment_config_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EnvironmentConfigResponseModel { #[serde(rename = "cloudRegion", skip_serializing_if = "Option::is_none")] pub cloud_region: Option, diff --git a/crates/bitwarden-api-api/src/models/event_response_model.rs b/crates/bitwarden-api-api/src/models/event_response_model.rs index 03ce76ed7..b634ef7dc 100644 --- a/crates/bitwarden-api-api/src/models/event_response_model.rs +++ b/crates/bitwarden-api-api/src/models/event_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EventResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/event_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/event_response_model_list_response_model.rs index e2042731c..40f1d9e8e 100644 --- a/crates/bitwarden-api-api/src/models/event_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/event_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct EventResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/event_type.rs b/crates/bitwarden-api-api/src/models/event_type.rs index f0cea8ebc..cc4e96c14 100644 --- a/crates/bitwarden-api-api/src/models/event_type.rs +++ b/crates/bitwarden-api-api/src/models/event_type.rs @@ -73,6 +73,7 @@ pub enum EventType { Variant1606 = 1606, Variant1607 = 1607, Variant1608 = 1608, + Variant1609 = 1609, Variant1700 = 1700, Variant1800 = 1800, Variant1801 = 1801, @@ -151,6 +152,7 @@ impl ToString for EventType { Self::Variant1606 => String::from("1606"), Self::Variant1607 => String::from("1607"), Self::Variant1608 => String::from("1608"), + Self::Variant1609 => String::from("1609"), Self::Variant1700 => String::from("1700"), Self::Variant1800 => String::from("1800"), Self::Variant1801 => String::from("1801"), diff --git a/crates/bitwarden-api-api/src/models/fido2_user.rs b/crates/bitwarden-api-api/src/models/fido2_user.rs new file mode 100644 index 000000000..542019d39 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/fido2_user.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Fido2User { + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "displayName", skip_serializing_if = "Option::is_none")] + pub display_name: Option, +} + +impl Fido2User { + pub fn new() -> Fido2User { + Fido2User { + name: None, + id: None, + display_name: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/folder_request_model.rs b/crates/bitwarden-api-api/src/models/folder_request_model.rs index d226d2e04..cb73d7693 100644 --- a/crates/bitwarden-api-api/src/models/folder_request_model.rs +++ b/crates/bitwarden-api-api/src/models/folder_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct FolderRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/folder_response_model.rs b/crates/bitwarden-api-api/src/models/folder_response_model.rs index 976340c98..705c45f04 100644 --- a/crates/bitwarden-api-api/src/models/folder_response_model.rs +++ b/crates/bitwarden-api-api/src/models/folder_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct FolderResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/folder_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/folder_response_model_list_response_model.rs index d0209006d..3a12dfd31 100644 --- a/crates/bitwarden-api-api/src/models/folder_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/folder_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct FolderResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/folder_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/folder_with_id_request_model.rs index 599126620..a69b5ef8c 100644 --- a/crates/bitwarden-api-api/src/models/folder_with_id_request_model.rs +++ b/crates/bitwarden-api-api/src/models/folder_with_id_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct FolderWithIdRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/get_secrets_request_model.rs b/crates/bitwarden-api-api/src/models/get_secrets_request_model.rs index 2786d8c9d..93ca67bde 100644 --- a/crates/bitwarden-api-api/src/models/get_secrets_request_model.rs +++ b/crates/bitwarden-api-api/src/models/get_secrets_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GetSecretsRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/global_domains.rs b/crates/bitwarden-api-api/src/models/global_domains.rs index 10a943482..b86399762 100644 --- a/crates/bitwarden-api-api/src/models/global_domains.rs +++ b/crates/bitwarden-api-api/src/models/global_domains.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GlobalDomains { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/granted_access_policy_request.rs b/crates/bitwarden-api-api/src/models/granted_access_policy_request.rs index 4d4f1291d..3d35274a0 100644 --- a/crates/bitwarden-api-api/src/models/granted_access_policy_request.rs +++ b/crates/bitwarden-api-api/src/models/granted_access_policy_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GrantedAccessPolicyRequest { #[serde(rename = "grantedId")] pub granted_id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/group.rs b/crates/bitwarden-api-api/src/models/group.rs index c7acafc56..7133029b5 100644 --- a/crates/bitwarden-api-api/src/models/group.rs +++ b/crates/bitwarden-api-api/src/models/group.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Group { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/group_bulk_request_model.rs b/crates/bitwarden-api-api/src/models/group_bulk_request_model.rs index 1f56fe0fb..432f9f6d8 100644 --- a/crates/bitwarden-api-api/src/models/group_bulk_request_model.rs +++ b/crates/bitwarden-api-api/src/models/group_bulk_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupBulkRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/group_details_response_model.rs b/crates/bitwarden-api-api/src/models/group_details_response_model.rs index 91e20d584..d6ee7239a 100644 --- a/crates/bitwarden-api-api/src/models/group_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/group_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/group_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/group_details_response_model_list_response_model.rs index 5aa54b57c..c1c19d332 100644 --- a/crates/bitwarden-api-api/src/models/group_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/group_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/group_project_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/group_project_access_policy_response_model.rs index d43b70e95..2b6f5c9c0 100644 --- a/crates/bitwarden-api-api/src/models/group_project_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/group_project_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupProjectAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/group_request_model.rs b/crates/bitwarden-api-api/src/models/group_request_model.rs index 27d24defc..0284a04d9 100644 --- a/crates/bitwarden-api-api/src/models/group_request_model.rs +++ b/crates/bitwarden-api-api/src/models/group_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/group_response_model.rs b/crates/bitwarden-api-api/src/models/group_response_model.rs index 32d43b51f..388fe68f5 100644 --- a/crates/bitwarden-api-api/src/models/group_response_model.rs +++ b/crates/bitwarden-api-api/src/models/group_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/group_service_account_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/group_service_account_access_policy_response_model.rs index 0f7eb9b3e..af04b2cfe 100644 --- a/crates/bitwarden-api-api/src/models/group_service_account_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/group_service_account_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct GroupServiceAccountAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/import_ciphers_request_model.rs b/crates/bitwarden-api-api/src/models/import_ciphers_request_model.rs index 9cc2a7d75..371f2fa5c 100644 --- a/crates/bitwarden-api-api/src/models/import_ciphers_request_model.rs +++ b/crates/bitwarden-api-api/src/models/import_ciphers_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ImportCiphersRequestModel { #[serde(rename = "folders", skip_serializing_if = "Option::is_none")] pub folders: Option>, diff --git a/crates/bitwarden-api-api/src/models/import_organization_ciphers_request_model.rs b/crates/bitwarden-api-api/src/models/import_organization_ciphers_request_model.rs index 625f733a3..894fb7131 100644 --- a/crates/bitwarden-api-api/src/models/import_organization_ciphers_request_model.rs +++ b/crates/bitwarden-api-api/src/models/import_organization_ciphers_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ImportOrganizationCiphersRequestModel { #[serde(rename = "collections", skip_serializing_if = "Option::is_none")] pub collections: Option>, diff --git a/crates/bitwarden-api-api/src/models/import_organization_users_request_model.rs b/crates/bitwarden-api-api/src/models/import_organization_users_request_model.rs index 72f276d05..ff5be1b6f 100644 --- a/crates/bitwarden-api-api/src/models/import_organization_users_request_model.rs +++ b/crates/bitwarden-api-api/src/models/import_organization_users_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ImportOrganizationUsersRequestModel { #[serde(rename = "groups", skip_serializing_if = "Option::is_none")] pub groups: Option>, diff --git a/crates/bitwarden-api-api/src/models/inner_project_export_response_model.rs b/crates/bitwarden-api-api/src/models/inner_project_export_response_model.rs index 2c14b4d3c..a34dab3a6 100644 --- a/crates/bitwarden-api-api/src/models/inner_project_export_response_model.rs +++ b/crates/bitwarden-api-api/src/models/inner_project_export_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InnerProjectExportResponseModel { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/inner_project_import_request_model.rs b/crates/bitwarden-api-api/src/models/inner_project_import_request_model.rs index 1f3b7614d..808504d83 100644 --- a/crates/bitwarden-api-api/src/models/inner_project_import_request_model.rs +++ b/crates/bitwarden-api-api/src/models/inner_project_import_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InnerProjectImportRequestModel { #[serde(rename = "id")] pub id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/inner_secret_export_response_model.rs b/crates/bitwarden-api-api/src/models/inner_secret_export_response_model.rs index d735029b9..7a55ad679 100644 --- a/crates/bitwarden-api-api/src/models/inner_secret_export_response_model.rs +++ b/crates/bitwarden-api-api/src/models/inner_secret_export_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InnerSecretExportResponseModel { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/inner_secret_import_request_model.rs b/crates/bitwarden-api-api/src/models/inner_secret_import_request_model.rs index 594f14cce..bfe164eff 100644 --- a/crates/bitwarden-api-api/src/models/inner_secret_import_request_model.rs +++ b/crates/bitwarden-api-api/src/models/inner_secret_import_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InnerSecretImportRequestModel { #[serde(rename = "id")] pub id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/installation_request_model.rs b/crates/bitwarden-api-api/src/models/installation_request_model.rs index a8abba2d6..58b8924ef 100644 --- a/crates/bitwarden-api-api/src/models/installation_request_model.rs +++ b/crates/bitwarden-api-api/src/models/installation_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InstallationRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/installation_response_model.rs b/crates/bitwarden-api-api/src/models/installation_response_model.rs index 4fd14dce8..0d7009ff1 100644 --- a/crates/bitwarden-api-api/src/models/installation_response_model.rs +++ b/crates/bitwarden-api-api/src/models/installation_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct InstallationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/int32_int32_key_value_pair.rs b/crates/bitwarden-api-api/src/models/int32_int32_key_value_pair.rs index 3ca10d2b3..831f0e03a 100644 --- a/crates/bitwarden-api-api/src/models/int32_int32_key_value_pair.rs +++ b/crates/bitwarden-api-api/src/models/int32_int32_key_value_pair.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Int32Int32KeyValuePair { #[serde(rename = "key", skip_serializing_if = "Option::is_none")] pub key: Option, diff --git a/crates/bitwarden-api-api/src/models/kdf_request_model.rs b/crates/bitwarden-api-api/src/models/kdf_request_model.rs index bb903a84f..2f43e2f45 100644 --- a/crates/bitwarden-api-api/src/models/kdf_request_model.rs +++ b/crates/bitwarden-api-api/src/models/kdf_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct KdfRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/key_model.rs b/crates/bitwarden-api-api/src/models/key_model.rs index 20aa497de..78231697b 100644 --- a/crates/bitwarden-api-api/src/models/key_model.rs +++ b/crates/bitwarden-api-api/src/models/key_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct KeyModel { #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, diff --git a/crates/bitwarden-api-api/src/models/keys_request_model.rs b/crates/bitwarden-api-api/src/models/keys_request_model.rs index f1db24fc9..d87329136 100644 --- a/crates/bitwarden-api-api/src/models/keys_request_model.rs +++ b/crates/bitwarden-api-api/src/models/keys_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct KeysRequestModel { #[serde(rename = "publicKey", skip_serializing_if = "Option::is_none")] pub public_key: Option, diff --git a/crates/bitwarden-api-api/src/models/keys_response_model.rs b/crates/bitwarden-api-api/src/models/keys_response_model.rs index 82f3e8804..21b998384 100644 --- a/crates/bitwarden-api-api/src/models/keys_response_model.rs +++ b/crates/bitwarden-api-api/src/models/keys_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct KeysResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/master_password_policy_response_model.rs b/crates/bitwarden-api-api/src/models/master_password_policy_response_model.rs index 356a61f34..b1a53bdea 100644 --- a/crates/bitwarden-api-api/src/models/master_password_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/master_password_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MasterPasswordPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/mod.rs b/crates/bitwarden-api-api/src/models/mod.rs index db4702827..8bed9f858 100644 --- a/crates/bitwarden-api-api/src/models/mod.rs +++ b/crates/bitwarden-api-api/src/models/mod.rs @@ -14,14 +14,22 @@ pub mod access_token_response_model_list_response_model; pub use self::access_token_response_model_list_response_model::AccessTokenResponseModelListResponseModel; pub mod admin_auth_request_update_request_model; pub use self::admin_auth_request_update_request_model::AdminAuthRequestUpdateRequestModel; +pub mod algorithm; +pub use self::algorithm::Algorithm; pub mod api_key_response_model; pub use self::api_key_response_model::ApiKeyResponseModel; +pub mod assertion_options; +pub use self::assertion_options::AssertionOptions; +pub mod assertion_response; +pub use self::assertion_response::AssertionResponse; pub mod attachment_request_model; pub use self::attachment_request_model::AttachmentRequestModel; pub mod attachment_response_model; pub use self::attachment_response_model::AttachmentResponseModel; pub mod attachment_upload_data_response_model; pub use self::attachment_upload_data_response_model::AttachmentUploadDataResponseModel; +pub mod attestation_conveyance_preference; +pub use self::attestation_conveyance_preference::AttestationConveyancePreference; pub mod auth_request_create_request_model; pub use self::auth_request_create_request_model::AuthRequestCreateRequestModel; pub mod auth_request_response_model; @@ -32,10 +40,20 @@ pub mod auth_request_type; pub use self::auth_request_type::AuthRequestType; pub mod auth_request_update_request_model; pub use self::auth_request_update_request_model::AuthRequestUpdateRequestModel; +pub mod authentication_extensions_client_inputs; +pub use self::authentication_extensions_client_inputs::AuthenticationExtensionsClientInputs; pub mod authentication_extensions_client_outputs; pub use self::authentication_extensions_client_outputs::AuthenticationExtensionsClientOutputs; +pub mod authenticator_assertion_raw_response; +pub use self::authenticator_assertion_raw_response::AuthenticatorAssertionRawResponse; +pub mod authenticator_attachment; +pub use self::authenticator_attachment::AuthenticatorAttachment; pub mod authenticator_attestation_raw_response; pub use self::authenticator_attestation_raw_response::AuthenticatorAttestationRawResponse; +pub mod authenticator_selection; +pub use self::authenticator_selection::AuthenticatorSelection; +pub mod authenticator_transport; +pub use self::authenticator_transport::AuthenticatorTransport; pub mod base_access_policy_response_model; pub use self::base_access_policy_response_model::BaseAccessPolicyResponseModel; pub mod base_secret_response_model; @@ -64,8 +82,8 @@ pub mod billing_transaction; pub use self::billing_transaction::BillingTransaction; pub mod bit_pay_invoice_request_model; pub use self::bit_pay_invoice_request_model::BitPayInvoiceRequestModel; -pub mod bitwarden_product_type; -pub use self::bitwarden_product_type::BitwardenProductType; +pub mod bulk_collection_access_request_model; +pub use self::bulk_collection_access_request_model::BulkCollectionAccessRequestModel; pub mod bulk_delete_response_model; pub use self::bulk_delete_response_model::BulkDeleteResponseModel; pub mod bulk_delete_response_model_list_response_model; @@ -92,6 +110,8 @@ pub mod cipher_details_response_model; pub use self::cipher_details_response_model::CipherDetailsResponseModel; pub mod cipher_details_response_model_list_response_model; pub use self::cipher_details_response_model_list_response_model::CipherDetailsResponseModelListResponseModel; +pub mod cipher_fido2_credential_model; +pub use self::cipher_fido2_credential_model::CipherFido2CredentialModel; pub mod cipher_field_model; pub use self::cipher_field_model::CipherFieldModel; pub mod cipher_identity_model; @@ -146,6 +166,8 @@ pub mod collection_with_id_request_model; pub use self::collection_with_id_request_model::CollectionWithIdRequestModel; pub mod config_response_model; pub use self::config_response_model::ConfigResponseModel; +pub mod credential_create_options; +pub use self::credential_create_options::CredentialCreateOptions; pub mod delete_recover_request_model; pub use self::delete_recover_request_model::DeleteRecoverRequestModel; pub mod device_keys_request_model; @@ -194,6 +216,8 @@ pub mod emergency_access_update_request_model; pub use self::emergency_access_update_request_model::EmergencyAccessUpdateRequestModel; pub mod emergency_access_view_response_model; pub use self::emergency_access_view_response_model::EmergencyAccessViewResponseModel; +pub mod emergency_access_with_id_request_model; +pub use self::emergency_access_with_id_request_model::EmergencyAccessWithIdRequestModel; pub mod environment_config_response_model; pub use self::environment_config_response_model::EnvironmentConfigResponseModel; pub mod event_response_model; @@ -204,6 +228,8 @@ pub mod event_system_user; pub use self::event_system_user::EventSystemUser; pub mod event_type; pub use self::event_type::EventType; +pub mod fido2_user; +pub use self::fido2_user::Fido2User; pub mod field_type; pub use self::field_type::FieldType; pub mod file_upload_type; @@ -240,8 +266,6 @@ pub mod group_response_model; pub use self::group_response_model::GroupResponseModel; pub mod group_service_account_access_policy_response_model; pub use self::group_service_account_access_policy_response_model::GroupServiceAccountAccessPolicyResponseModel; -pub mod iap_check_request_model; -pub use self::iap_check_request_model::IapCheckRequestModel; pub mod import_ciphers_request_model; pub use self::import_ciphers_request_model::ImportCiphersRequestModel; pub mod import_organization_ciphers_request_model; @@ -290,6 +314,8 @@ pub mod organization_api_key_type; pub use self::organization_api_key_type::OrganizationApiKeyType; pub mod organization_auto_enroll_status_response_model; pub use self::organization_auto_enroll_status_response_model::OrganizationAutoEnrollStatusResponseModel; +pub mod organization_collection_management_update_request_model; +pub use self::organization_collection_management_update_request_model::OrganizationCollectionManagementUpdateRequestModel; pub mod organization_connection_request_model; pub use self::organization_connection_request_model::OrganizationConnectionRequestModel; pub mod organization_connection_response_model; @@ -318,6 +344,8 @@ pub mod organization_public_key_response_model; pub use self::organization_public_key_response_model::OrganizationPublicKeyResponseModel; pub mod organization_response_model; pub use self::organization_response_model::OrganizationResponseModel; +pub mod organization_risks_subscription_failure_response_model; +pub use self::organization_risks_subscription_failure_response_model::OrganizationRisksSubscriptionFailureResponseModel; pub mod organization_seat_request_model; pub use self::organization_seat_request_model::OrganizationSeatRequestModel; pub mod organization_sponsorship_create_request_model; @@ -394,6 +422,8 @@ pub mod other_device_keys_update_request_model; pub use self::other_device_keys_update_request_model::OtherDeviceKeysUpdateRequestModel; pub mod password_hint_request_model; pub use self::password_hint_request_model::PasswordHintRequestModel; +pub mod password_manager_plan_features_response_model; +pub use self::password_manager_plan_features_response_model::PasswordManagerPlanFeaturesResponseModel; pub mod password_request_model; pub use self::password_request_model::PasswordRequestModel; pub mod payment_method_type; @@ -406,6 +436,8 @@ pub mod pending_organization_auth_request_response_model; pub use self::pending_organization_auth_request_response_model::PendingOrganizationAuthRequestResponseModel; pub mod pending_organization_auth_request_response_model_list_response_model; pub use self::pending_organization_auth_request_response_model_list_response_model::PendingOrganizationAuthRequestResponseModelListResponseModel; +pub mod people_access_policies_request_model; +pub use self::people_access_policies_request_model::PeopleAccessPoliciesRequestModel; pub mod permissions; pub use self::permissions::Permissions; pub mod plan_response_model; @@ -448,6 +480,8 @@ pub mod project_access_policies_response_model; pub use self::project_access_policies_response_model::ProjectAccessPoliciesResponseModel; pub mod project_create_request_model; pub use self::project_create_request_model::ProjectCreateRequestModel; +pub mod project_people_access_policies_response_model; +pub use self::project_people_access_policies_response_model::ProjectPeopleAccessPoliciesResponseModel; pub mod project_response_model; pub use self::project_response_model::ProjectResponseModel; pub mod project_response_model_list_response_model; @@ -506,6 +540,12 @@ pub mod provider_user_user_details_response_model; pub use self::provider_user_user_details_response_model::ProviderUserUserDetailsResponseModel; pub mod provider_user_user_details_response_model_list_response_model; pub use self::provider_user_user_details_response_model_list_response_model::ProviderUserUserDetailsResponseModelListResponseModel; +pub mod pub_key_cred_param; +pub use self::pub_key_cred_param::PubKeyCredParam; +pub mod public_key_credential_descriptor; +pub use self::public_key_credential_descriptor::PublicKeyCredentialDescriptor; +pub mod public_key_credential_rp_entity; +pub use self::public_key_credential_rp_entity::PublicKeyCredentialRpEntity; pub mod public_key_credential_type; pub use self::public_key_credential_type::PublicKeyCredentialType; pub mod push_registration_request_model; @@ -520,6 +560,8 @@ pub mod register_request_model; pub use self::register_request_model::RegisterRequestModel; pub mod register_response_model; pub use self::register_response_model::RegisterResponseModel; +pub mod reset_password_with_org_id_request_model; +pub use self::reset_password_with_org_id_request_model::ResetPasswordWithOrgIdRequestModel; pub mod response_data; pub use self::response_data::ResponseData; pub mod revoke_access_tokens_request; @@ -544,6 +586,8 @@ pub mod secret_with_projects_inner_project; pub use self::secret_with_projects_inner_project::SecretWithProjectsInnerProject; pub mod secret_with_projects_list_response_model; pub use self::secret_with_projects_list_response_model::SecretWithProjectsListResponseModel; +pub mod secrets_manager_plan_features_response_model; +pub use self::secrets_manager_plan_features_response_model::SecretsManagerPlanFeaturesResponseModel; pub mod secrets_manager_subscribe_request_model; pub use self::secrets_manager_subscribe_request_model::SecretsManagerSubscribeRequestModel; pub mod secrets_manager_subscription_update_request_model; @@ -578,10 +622,10 @@ pub mod send_with_id_request_model; pub use self::send_with_id_request_model::SendWithIdRequestModel; pub mod server_config_response_model; pub use self::server_config_response_model::ServerConfigResponseModel; -pub mod service_account_access_policies_response_model; -pub use self::service_account_access_policies_response_model::ServiceAccountAccessPoliciesResponseModel; pub mod service_account_create_request_model; pub use self::service_account_create_request_model::ServiceAccountCreateRequestModel; +pub mod service_account_people_access_policies_response_model; +pub use self::service_account_people_access_policies_response_model::ServiceAccountPeopleAccessPoliciesResponseModel; pub mod service_account_project_access_policy_response_model; pub use self::service_account_project_access_policy_response_model::ServiceAccountProjectAccessPolicyResponseModel; pub mod service_account_project_access_policy_response_model_list_response_model; @@ -686,9 +730,25 @@ pub mod user_project_access_policy_response_model; pub use self::user_project_access_policy_response_model::UserProjectAccessPolicyResponseModel; pub mod user_service_account_access_policy_response_model; pub use self::user_service_account_access_policy_response_model::UserServiceAccountAccessPolicyResponseModel; +pub mod user_verification_requirement; +pub use self::user_verification_requirement::UserVerificationRequirement; pub mod verify_delete_recover_request_model; pub use self::verify_delete_recover_request_model::VerifyDeleteRecoverRequestModel; pub mod verify_email_request_model; pub use self::verify_email_request_model::VerifyEmailRequestModel; pub mod verify_otp_request_model; pub use self::verify_otp_request_model::VerifyOtpRequestModel; +pub mod web_authn_credential_create_options_response_model; +pub use self::web_authn_credential_create_options_response_model::WebAuthnCredentialCreateOptionsResponseModel; +pub mod web_authn_credential_response_model; +pub use self::web_authn_credential_response_model::WebAuthnCredentialResponseModel; +pub mod web_authn_credential_response_model_list_response_model; +pub use self::web_authn_credential_response_model_list_response_model::WebAuthnCredentialResponseModelListResponseModel; +pub mod web_authn_login_assertion_options_response_model; +pub use self::web_authn_login_assertion_options_response_model::WebAuthnLoginAssertionOptionsResponseModel; +pub mod web_authn_login_credential_create_request_model; +pub use self::web_authn_login_credential_create_request_model::WebAuthnLoginCredentialCreateRequestModel; +pub mod web_authn_login_credential_update_request_model; +pub use self::web_authn_login_credential_update_request_model::WebAuthnLoginCredentialUpdateRequestModel; +pub mod web_authn_prf_status; +pub use self::web_authn_prf_status::WebAuthnPrfStatus; diff --git a/crates/bitwarden-api-api/src/models/organization_api_key_information.rs b/crates/bitwarden-api-api/src/models/organization_api_key_information.rs index fceb50762..94c56de5f 100644 --- a/crates/bitwarden-api-api/src/models/organization_api_key_information.rs +++ b/crates/bitwarden-api-api/src/models/organization_api_key_information.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationApiKeyInformation { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_api_key_information_list_response_model.rs b/crates/bitwarden-api-api/src/models/organization_api_key_information_list_response_model.rs index 129ebf4b9..63b65454c 100644 --- a/crates/bitwarden-api-api/src/models/organization_api_key_information_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_api_key_information_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationApiKeyInformationListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_api_key_request_model.rs b/crates/bitwarden-api-api/src/models/organization_api_key_request_model.rs index 5466d6cb1..3af42cef6 100644 --- a/crates/bitwarden-api-api/src/models/organization_api_key_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_api_key_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationApiKeyRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_auto_enroll_status_response_model.rs b/crates/bitwarden-api-api/src/models/organization_auto_enroll_status_response_model.rs index c652f55fc..e068219ee 100644 --- a/crates/bitwarden-api-api/src/models/organization_auto_enroll_status_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_auto_enroll_status_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationAutoEnrollStatusResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_collection_management_update_request_model.rs b/crates/bitwarden-api-api/src/models/organization_collection_management_update_request_model.rs new file mode 100644 index 000000000..ce5d52f6d --- /dev/null +++ b/crates/bitwarden-api-api/src/models/organization_collection_management_update_request_model.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct OrganizationCollectionManagementUpdateRequestModel { + #[serde( + rename = "limitCreateDeleteOwnerAdmin", + skip_serializing_if = "Option::is_none" + )] + pub limit_create_delete_owner_admin: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, +} + +impl OrganizationCollectionManagementUpdateRequestModel { + pub fn new() -> OrganizationCollectionManagementUpdateRequestModel { + OrganizationCollectionManagementUpdateRequestModel { + limit_create_delete_owner_admin: None, + allow_admin_access_to_all_collection_items: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/organization_connection_request_model.rs b/crates/bitwarden-api-api/src/models/organization_connection_request_model.rs index 3105b2b3e..d201c54b2 100644 --- a/crates/bitwarden-api-api/src/models/organization_connection_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_connection_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationConnectionRequestModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_connection_response_model.rs b/crates/bitwarden-api-api/src/models/organization_connection_response_model.rs index beb31068f..88ccf278c 100644 --- a/crates/bitwarden-api-api/src/models/organization_connection_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_connection_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationConnectionResponseModel { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_create_request_model.rs b/crates/bitwarden-api-api/src/models/organization_create_request_model.rs index 493737ccf..8c00b6888 100644 --- a/crates/bitwarden-api-api/src/models/organization_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationCreateRequestModel { #[serde(rename = "name")] pub name: String, @@ -77,6 +77,11 @@ pub struct OrganizationCreateRequestModel { pub additional_service_accounts: Option, #[serde(rename = "useSecretsManager")] pub use_secrets_manager: bool, + #[serde( + rename = "isFromSecretsManagerTrial", + skip_serializing_if = "Option::is_none" + )] + pub is_from_secrets_manager_trial: Option, } impl OrganizationCreateRequestModel { @@ -110,6 +115,7 @@ impl OrganizationCreateRequestModel { additional_sm_seats: None, additional_service_accounts: None, use_secrets_manager, + is_from_secrets_manager_trial: None, } } } diff --git a/crates/bitwarden-api-api/src/models/organization_domain_request_model.rs b/crates/bitwarden-api-api/src/models/organization_domain_request_model.rs index e17cfd936..b1dbe8395 100644 --- a/crates/bitwarden-api-api/src/models/organization_domain_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_domain_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationDomainRequestModel { #[serde(rename = "txt")] pub txt: String, diff --git a/crates/bitwarden-api-api/src/models/organization_domain_response_model.rs b/crates/bitwarden-api-api/src/models/organization_domain_response_model.rs index 919a18ffa..524a00f93 100644 --- a/crates/bitwarden-api-api/src/models/organization_domain_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_domain_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationDomainResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_domain_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/organization_domain_response_model_list_response_model.rs index 46db2791b..49224feb3 100644 --- a/crates/bitwarden-api-api/src/models/organization_domain_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_domain_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationDomainResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_domain_sso_details_request_model.rs b/crates/bitwarden-api-api/src/models/organization_domain_sso_details_request_model.rs index abef29d1e..a731af833 100644 --- a/crates/bitwarden-api-api/src/models/organization_domain_sso_details_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_domain_sso_details_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationDomainSsoDetailsRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/organization_domain_sso_details_response_model.rs b/crates/bitwarden-api-api/src/models/organization_domain_sso_details_response_model.rs index f9ce9db71..c409df706 100644 --- a/crates/bitwarden-api-api/src/models/organization_domain_sso_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_domain_sso_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationDomainSsoDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_keys_request_model.rs b/crates/bitwarden-api-api/src/models/organization_keys_request_model.rs index 3750a4e05..eccd5f5b3 100644 --- a/crates/bitwarden-api-api/src/models/organization_keys_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_keys_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationKeysRequestModel { #[serde(rename = "publicKey")] pub public_key: String, diff --git a/crates/bitwarden-api-api/src/models/organization_keys_response_model.rs b/crates/bitwarden-api-api/src/models/organization_keys_response_model.rs index b8bb486fb..6992abccb 100644 --- a/crates/bitwarden-api-api/src/models/organization_keys_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_keys_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationKeysResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_license.rs b/crates/bitwarden-api-api/src/models/organization_license.rs index b440b8e00..2497f073e 100644 --- a/crates/bitwarden-api-api/src/models/organization_license.rs +++ b/crates/bitwarden-api-api/src/models/organization_license.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationLicense { #[serde(rename = "licenseKey", skip_serializing_if = "Option::is_none")] pub license_key: Option, @@ -78,6 +78,24 @@ pub struct OrganizationLicense { skip_serializing_if = "Option::is_none" )] pub expiration_without_grace_period: Option, + #[serde(rename = "usePasswordManager", skip_serializing_if = "Option::is_none")] + pub use_password_manager: Option, + #[serde(rename = "useSecretsManager", skip_serializing_if = "Option::is_none")] + pub use_secrets_manager: Option, + #[serde(rename = "smSeats", skip_serializing_if = "Option::is_none")] + pub sm_seats: Option, + #[serde(rename = "smServiceAccounts", skip_serializing_if = "Option::is_none")] + pub sm_service_accounts: Option, + #[serde( + rename = "limitCollectionCreationDeletion", + skip_serializing_if = "Option::is_none" + )] + pub limit_collection_creation_deletion: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, #[serde(rename = "trial", skip_serializing_if = "Option::is_none")] pub trial: Option, #[serde(rename = "licenseType", skip_serializing_if = "Option::is_none")] @@ -122,6 +140,12 @@ impl OrganizationLicense { refresh: None, expires: None, expiration_without_grace_period: None, + use_password_manager: None, + use_secrets_manager: None, + sm_seats: None, + sm_service_accounts: None, + limit_collection_creation_deletion: None, + allow_admin_access_to_all_collection_items: None, trial: None, license_type: None, hash: None, diff --git a/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs b/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs index c5849d3e6..aca53523a 100644 --- a/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_public_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationPublicKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_response_model.rs b/crates/bitwarden-api-api/src/models/organization_response_model.rs index 6618b1f79..e5c877fb0 100644 --- a/crates/bitwarden-api-api/src/models/organization_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -98,6 +98,21 @@ pub struct OrganizationResponseModel { skip_serializing_if = "Option::is_none" )] pub max_autoscale_sm_service_accounts: Option, + #[serde( + rename = "limitCollectionCreationDeletion", + skip_serializing_if = "Option::is_none" + )] + pub limit_collection_creation_deletion: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, + #[serde( + rename = "flexibleCollections", + skip_serializing_if = "Option::is_none" + )] + pub flexible_collections: Option, } impl OrganizationResponseModel { @@ -141,6 +156,9 @@ impl OrganizationResponseModel { sm_service_accounts: None, max_autoscale_sm_seats: None, max_autoscale_sm_service_accounts: None, + limit_collection_creation_deletion: None, + allow_admin_access_to_all_collection_items: None, + flexible_collections: None, } } } diff --git a/crates/bitwarden-api-api/src/models/organization_risks_subscription_failure_response_model.rs b/crates/bitwarden-api-api/src/models/organization_risks_subscription_failure_response_model.rs new file mode 100644 index 000000000..4e138cd85 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/organization_risks_subscription_failure_response_model.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct OrganizationRisksSubscriptionFailureResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "organizationId", skip_serializing_if = "Option::is_none")] + pub organization_id: Option, + #[serde( + rename = "risksSubscriptionFailure", + skip_serializing_if = "Option::is_none" + )] + pub risks_subscription_failure: Option, +} + +impl OrganizationRisksSubscriptionFailureResponseModel { + pub fn new() -> OrganizationRisksSubscriptionFailureResponseModel { + OrganizationRisksSubscriptionFailureResponseModel { + object: None, + organization_id: None, + risks_subscription_failure: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/organization_seat_request_model.rs b/crates/bitwarden-api-api/src/models/organization_seat_request_model.rs index e822b9f82..58f815f4b 100644 --- a/crates/bitwarden-api-api/src/models/organization_seat_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_seat_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSeatRequestModel { #[serde(rename = "seatAdjustment")] pub seat_adjustment: i32, diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_create_request_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_create_request_model.rs index f823b56fe..dbd33d616 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipCreateRequestModel { #[serde(rename = "planSponsorshipType")] pub plan_sponsorship_type: crate::models::PlanSponsorshipType, diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_redeem_request_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_redeem_request_model.rs index b978ff27c..08a3f3741 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_redeem_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_redeem_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipRedeemRequestModel { #[serde(rename = "planSponsorshipType")] pub plan_sponsorship_type: crate::models::PlanSponsorshipType, diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_request_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_request_model.rs index 94cd9a088..247e8f3ea 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipRequestModel { #[serde( rename = "sponsoringOrganizationUserId", diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_response_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_response_model.rs index 5798d3500..21f90016a 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipResponseModel { #[serde( rename = "sponsoringOrganizationUserId", diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_request_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_request_model.rs index cfffe3ec3..3aca9f7fc 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipSyncRequestModel { #[serde(rename = "billingSyncKey", skip_serializing_if = "Option::is_none")] pub billing_sync_key: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_response_model.rs b/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_response_model.rs index 0d2b71f74..e3630d1ee 100644 --- a/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sponsorship_sync_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSponsorshipSyncResponseModel { #[serde(rename = "sponsorshipsBatch", skip_serializing_if = "Option::is_none")] pub sponsorships_batch: Option>, diff --git a/crates/bitwarden-api-api/src/models/organization_sso_request_model.rs b/crates/bitwarden-api-api/src/models/organization_sso_request_model.rs index 1accd7a2e..4818e8e5d 100644 --- a/crates/bitwarden-api-api/src/models/organization_sso_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sso_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSsoRequestModel { #[serde(rename = "enabled")] pub enabled: bool, diff --git a/crates/bitwarden-api-api/src/models/organization_sso_response_model.rs b/crates/bitwarden-api-api/src/models/organization_sso_response_model.rs index 9a1676049..d0d73e4b0 100644 --- a/crates/bitwarden-api-api/src/models/organization_sso_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_sso_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSsoResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs b/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs index b08184d43..1bbfc630f 100644 --- a/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_subscription_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSubscriptionResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -98,12 +98,27 @@ pub struct OrganizationSubscriptionResponseModel { skip_serializing_if = "Option::is_none" )] pub max_autoscale_sm_service_accounts: Option, + #[serde( + rename = "limitCollectionCreationDeletion", + skip_serializing_if = "Option::is_none" + )] + pub limit_collection_creation_deletion: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, + #[serde( + rename = "flexibleCollections", + skip_serializing_if = "Option::is_none" + )] + pub flexible_collections: Option, #[serde(rename = "storageName", skip_serializing_if = "Option::is_none")] pub storage_name: Option, #[serde(rename = "storageGb", skip_serializing_if = "Option::is_none")] pub storage_gb: Option, - #[serde(rename = "discount", skip_serializing_if = "Option::is_none")] - pub discount: Option>, + #[serde(rename = "customerDiscount", skip_serializing_if = "Option::is_none")] + pub customer_discount: Option>, #[serde(rename = "subscription", skip_serializing_if = "Option::is_none")] pub subscription: Option>, #[serde(rename = "upcomingInvoice", skip_serializing_if = "Option::is_none")] @@ -117,8 +132,6 @@ pub struct OrganizationSubscriptionResponseModel { /// Date when a self-hosted organization expires (includes grace period). #[serde(rename = "expiration", skip_serializing_if = "Option::is_none")] pub expiration: Option, - #[serde(rename = "secretsManagerBeta", skip_serializing_if = "Option::is_none")] - pub secrets_manager_beta: Option, } impl OrganizationSubscriptionResponseModel { @@ -162,14 +175,16 @@ impl OrganizationSubscriptionResponseModel { sm_service_accounts: None, max_autoscale_sm_seats: None, max_autoscale_sm_service_accounts: None, + limit_collection_creation_deletion: None, + allow_admin_access_to_all_collection_items: None, + flexible_collections: None, storage_name: None, storage_gb: None, - discount: None, + customer_discount: None, subscription: None, upcoming_invoice: None, expiration_without_grace_period: None, expiration: None, - secrets_manager_beta: None, } } } diff --git a/crates/bitwarden-api-api/src/models/organization_subscription_update_request_model.rs b/crates/bitwarden-api-api/src/models/organization_subscription_update_request_model.rs index 9c919c759..d85f8d56a 100644 --- a/crates/bitwarden-api-api/src/models/organization_subscription_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_subscription_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationSubscriptionUpdateRequestModel { #[serde(rename = "seatAdjustment")] pub seat_adjustment: i32, diff --git a/crates/bitwarden-api-api/src/models/organization_tax_info_update_request_model.rs b/crates/bitwarden-api-api/src/models/organization_tax_info_update_request_model.rs index c6356037c..76a106b16 100644 --- a/crates/bitwarden-api-api/src/models/organization_tax_info_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_tax_info_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationTaxInfoUpdateRequestModel { #[serde(rename = "country")] pub country: String, diff --git a/crates/bitwarden-api-api/src/models/organization_update_request_model.rs b/crates/bitwarden-api-api/src/models/organization_update_request_model.rs index f4603d6a0..ede9d668a 100644 --- a/crates/bitwarden-api-api/src/models/organization_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUpdateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/organization_upgrade_request_model.rs b/crates/bitwarden-api-api/src/models/organization_upgrade_request_model.rs index 23f605dab..45bc99dd7 100644 --- a/crates/bitwarden-api-api/src/models/organization_upgrade_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_upgrade_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUpgradeRequestModel { #[serde(rename = "businessName", skip_serializing_if = "Option::is_none")] pub business_name: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_accept_init_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_accept_init_request_model.rs index 3ef9d7ced..ab4f7f0ff 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_accept_init_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_accept_init_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserAcceptInitRequestModel { #[serde(rename = "token")] pub token: String, diff --git a/crates/bitwarden-api-api/src/models/organization_user_accept_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_accept_request_model.rs index b46fc5851..62732f1d3 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_accept_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_accept_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserAcceptRequestModel { #[serde(rename = "token")] pub token: String, diff --git a/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model.rs index 7530bb3a7..468d654a3 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserBulkConfirmRequestModel { #[serde(rename = "keys")] pub keys: Vec, diff --git a/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model_entry.rs b/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model_entry.rs index a349578fa..f3ccb5e08 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model_entry.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_bulk_confirm_request_model_entry.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserBulkConfirmRequestModelEntry { #[serde(rename = "id")] pub id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/organization_user_bulk_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_bulk_request_model.rs index 14fdaa561..6f973f960 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_bulk_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_bulk_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserBulkRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model.rs index ba66e6f1f..f84f1509d 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserBulkResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model_list_response_model.rs index 5adc0087e..0be2de9a1 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_bulk_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserBulkResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_confirm_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_confirm_request_model.rs index f5abe9011..e6a00ae6b 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_confirm_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_confirm_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserConfirmRequestModel { #[serde(rename = "key")] pub key: String, diff --git a/crates/bitwarden-api-api/src/models/organization_user_details_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_details_response_model.rs index 179bb4a54..5fe8caf42 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_invite_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_invite_request_model.rs index 68de06fe1..0cf5c3429 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_invite_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_invite_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserInviteRequestModel { #[serde(rename = "emails")] pub emails: Vec, diff --git a/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model.rs index b3dbf5991..5bb053f81 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserPublicKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model_list_response_model.rs index d6de32d79..ae59cc365 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_public_key_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserPublicKeyResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_reset_password_details_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_reset_password_details_response_model.rs index 0dbd87182..07343bf5b 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_reset_password_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_reset_password_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserResetPasswordDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs index 7287c58a3..c11fcda48 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_reset_password_enrollment_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserResetPasswordEnrollmentRequestModel { #[serde(rename = "resetPasswordKey", skip_serializing_if = "Option::is_none")] pub reset_password_key: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_reset_password_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_reset_password_request_model.rs index 210aa2ec9..001086531 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_reset_password_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_reset_password_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserResetPasswordRequestModel { #[serde(rename = "newMasterPasswordHash")] pub new_master_password_hash: String, diff --git a/crates/bitwarden-api-api/src/models/organization_user_update_groups_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_update_groups_request_model.rs index 38c9dafe7..c9b636fc9 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_update_groups_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_update_groups_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserUpdateGroupsRequestModel { #[serde(rename = "groupIds")] pub group_ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/organization_user_update_request_model.rs b/crates/bitwarden-api-api/src/models/organization_user_update_request_model.rs index 1d83589ee..54b479dd6 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserUpdateRequestModel { #[serde(rename = "type")] pub r#type: crate::models::OrganizationUserType, diff --git a/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model.rs index 96d06ff30..add9e86e4 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserUserDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model_list_response_model.rs index f0975fc2d..e3feac1db 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_user_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationUserUserDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/organization_verify_bank_request_model.rs b/crates/bitwarden-api-api/src/models/organization_verify_bank_request_model.rs index f46a657a0..e19bdb89d 100644 --- a/crates/bitwarden-api-api/src/models/organization_verify_bank_request_model.rs +++ b/crates/bitwarden-api-api/src/models/organization_verify_bank_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OrganizationVerifyBankRequestModel { #[serde(rename = "amount1")] pub amount1: i32, diff --git a/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs b/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs index c163a4343..d7454c7cf 100644 --- a/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/other_device_keys_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct OtherDeviceKeysUpdateRequestModel { #[serde(rename = "encryptedPublicKey")] pub encrypted_public_key: String, diff --git a/crates/bitwarden-api-api/src/models/password_hint_request_model.rs b/crates/bitwarden-api-api/src/models/password_hint_request_model.rs index 6e4692bf2..8704c6fe1 100644 --- a/crates/bitwarden-api-api/src/models/password_hint_request_model.rs +++ b/crates/bitwarden-api-api/src/models/password_hint_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PasswordHintRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/password_manager_plan_features_response_model.rs b/crates/bitwarden-api-api/src/models/password_manager_plan_features_response_model.rs new file mode 100644 index 000000000..91fa49b6a --- /dev/null +++ b/crates/bitwarden-api-api/src/models/password_manager_plan_features_response_model.rs @@ -0,0 +1,98 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PasswordManagerPlanFeaturesResponseModel { + #[serde(rename = "stripePlanId", skip_serializing_if = "Option::is_none")] + pub stripe_plan_id: Option, + #[serde(rename = "stripeSeatPlanId", skip_serializing_if = "Option::is_none")] + pub stripe_seat_plan_id: Option, + #[serde(rename = "basePrice", skip_serializing_if = "Option::is_none")] + pub base_price: Option, + #[serde(rename = "seatPrice", skip_serializing_if = "Option::is_none")] + pub seat_price: Option, + #[serde(rename = "allowSeatAutoscale", skip_serializing_if = "Option::is_none")] + pub allow_seat_autoscale: Option, + #[serde( + rename = "hasAdditionalSeatsOption", + skip_serializing_if = "Option::is_none" + )] + pub has_additional_seats_option: Option, + #[serde(rename = "maxAdditionalSeats", skip_serializing_if = "Option::is_none")] + pub max_additional_seats: Option, + #[serde(rename = "baseSeats", skip_serializing_if = "Option::is_none")] + pub base_seats: Option, + #[serde( + rename = "hasPremiumAccessOption", + skip_serializing_if = "Option::is_none" + )] + pub has_premium_access_option: Option, + #[serde( + rename = "stripePremiumAccessPlanId", + skip_serializing_if = "Option::is_none" + )] + pub stripe_premium_access_plan_id: Option, + #[serde( + rename = "premiumAccessOptionPrice", + skip_serializing_if = "Option::is_none" + )] + pub premium_access_option_price: Option, + #[serde(rename = "maxSeats", skip_serializing_if = "Option::is_none")] + pub max_seats: Option, + #[serde(rename = "baseStorageGb", skip_serializing_if = "Option::is_none")] + pub base_storage_gb: Option, + #[serde( + rename = "hasAdditionalStorageOption", + skip_serializing_if = "Option::is_none" + )] + pub has_additional_storage_option: Option, + #[serde( + rename = "additionalStoragePricePerGb", + skip_serializing_if = "Option::is_none" + )] + pub additional_storage_price_per_gb: Option, + #[serde( + rename = "stripeStoragePlanId", + skip_serializing_if = "Option::is_none" + )] + pub stripe_storage_plan_id: Option, + #[serde( + rename = "maxAdditionalStorage", + skip_serializing_if = "Option::is_none" + )] + pub max_additional_storage: Option, + #[serde(rename = "maxCollections", skip_serializing_if = "Option::is_none")] + pub max_collections: Option, +} + +impl PasswordManagerPlanFeaturesResponseModel { + pub fn new() -> PasswordManagerPlanFeaturesResponseModel { + PasswordManagerPlanFeaturesResponseModel { + stripe_plan_id: None, + stripe_seat_plan_id: None, + base_price: None, + seat_price: None, + allow_seat_autoscale: None, + has_additional_seats_option: None, + max_additional_seats: None, + base_seats: None, + has_premium_access_option: None, + stripe_premium_access_plan_id: None, + premium_access_option_price: None, + max_seats: None, + base_storage_gb: None, + has_additional_storage_option: None, + additional_storage_price_per_gb: None, + stripe_storage_plan_id: None, + max_additional_storage: None, + max_collections: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/password_request_model.rs b/crates/bitwarden-api-api/src/models/password_request_model.rs index a1cac4dd2..c7fcb6e8b 100644 --- a/crates/bitwarden-api-api/src/models/password_request_model.rs +++ b/crates/bitwarden-api-api/src/models/password_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PasswordRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/payment_method_type.rs b/crates/bitwarden-api-api/src/models/payment_method_type.rs index 2b3cbd1f0..8df2830a4 100644 --- a/crates/bitwarden-api-api/src/models/payment_method_type.rs +++ b/crates/bitwarden-api-api/src/models/payment_method_type.rs @@ -20,8 +20,6 @@ pub enum PaymentMethodType { Variant3 = 3, Variant4 = 4, Variant5 = 5, - Variant6 = 6, - Variant7 = 7, Variant8 = 8, Variant255 = 255, } @@ -35,8 +33,6 @@ impl ToString for PaymentMethodType { Self::Variant3 => String::from("3"), Self::Variant4 => String::from("4"), Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), Self::Variant8 => String::from("8"), Self::Variant255 => String::from("255"), } diff --git a/crates/bitwarden-api-api/src/models/payment_request_model.rs b/crates/bitwarden-api-api/src/models/payment_request_model.rs index 08cb166cf..00e07ff11 100644 --- a/crates/bitwarden-api-api/src/models/payment_request_model.rs +++ b/crates/bitwarden-api-api/src/models/payment_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PaymentRequestModel { #[serde(rename = "country")] pub country: String, diff --git a/crates/bitwarden-api-api/src/models/payment_response_model.rs b/crates/bitwarden-api-api/src/models/payment_response_model.rs index 696b5ad10..2eddb498f 100644 --- a/crates/bitwarden-api-api/src/models/payment_response_model.rs +++ b/crates/bitwarden-api-api/src/models/payment_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PaymentResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model.rs b/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model.rs index fafb94836..5a0bc7bcb 100644 --- a/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model.rs +++ b/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PendingOrganizationAuthRequestResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model_list_response_model.rs index 43b6a9d31..d97c8c4ba 100644 --- a/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/pending_organization_auth_request_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PendingOrganizationAuthRequestResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/people_access_policies_request_model.rs b/crates/bitwarden-api-api/src/models/people_access_policies_request_model.rs new file mode 100644 index 000000000..909ce9c30 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/people_access_policies_request_model.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PeopleAccessPoliciesRequestModel { + #[serde( + rename = "userAccessPolicyRequests", + skip_serializing_if = "Option::is_none" + )] + pub user_access_policy_requests: Option>, + #[serde( + rename = "groupAccessPolicyRequests", + skip_serializing_if = "Option::is_none" + )] + pub group_access_policy_requests: Option>, +} + +impl PeopleAccessPoliciesRequestModel { + pub fn new() -> PeopleAccessPoliciesRequestModel { + PeopleAccessPoliciesRequestModel { + user_access_policy_requests: None, + group_access_policy_requests: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/permissions.rs b/crates/bitwarden-api-api/src/models/permissions.rs index d879faddc..3d3a6b7b7 100644 --- a/crates/bitwarden-api-api/src/models/permissions.rs +++ b/crates/bitwarden-api-api/src/models/permissions.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct Permissions { #[serde(rename = "accessEventLogs", skip_serializing_if = "Option::is_none")] pub access_event_logs: Option, diff --git a/crates/bitwarden-api-api/src/models/plan_response_model.rs b/crates/bitwarden-api-api/src/models/plan_response_model.rs index 17dcb777b..e1e264e9a 100644 --- a/crates/bitwarden-api-api/src/models/plan_response_model.rs +++ b/crates/bitwarden-api-api/src/models/plan_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PlanResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -35,36 +35,6 @@ pub struct PlanResponseModel { skip_serializing_if = "Option::is_none" )] pub can_be_used_by_business: Option, - #[serde(rename = "baseSeats", skip_serializing_if = "Option::is_none")] - pub base_seats: Option, - #[serde(rename = "baseStorageGb", skip_serializing_if = "Option::is_none")] - pub base_storage_gb: Option, - #[serde(rename = "maxCollections", skip_serializing_if = "Option::is_none")] - pub max_collections: Option, - #[serde(rename = "maxUsers", skip_serializing_if = "Option::is_none")] - pub max_users: Option, - #[serde( - rename = "hasAdditionalSeatsOption", - skip_serializing_if = "Option::is_none" - )] - pub has_additional_seats_option: Option, - #[serde(rename = "maxAdditionalSeats", skip_serializing_if = "Option::is_none")] - pub max_additional_seats: Option, - #[serde( - rename = "hasAdditionalStorageOption", - skip_serializing_if = "Option::is_none" - )] - pub has_additional_storage_option: Option, - #[serde( - rename = "maxAdditionalStorage", - skip_serializing_if = "Option::is_none" - )] - pub max_additional_storage: Option, - #[serde( - rename = "hasPremiumAccessOption", - skip_serializing_if = "Option::is_none" - )] - pub has_premium_access_option: Option, #[serde(rename = "trialPeriodDays", skip_serializing_if = "Option::is_none")] pub trial_period_days: Option, #[serde(rename = "hasSelfHost", skip_serializing_if = "Option::is_none")] @@ -97,62 +67,10 @@ pub struct PlanResponseModel { pub legacy_year: Option, #[serde(rename = "disabled", skip_serializing_if = "Option::is_none")] pub disabled: Option, - #[serde(rename = "stripePlanId", skip_serializing_if = "Option::is_none")] - pub stripe_plan_id: Option, - #[serde(rename = "stripeSeatPlanId", skip_serializing_if = "Option::is_none")] - pub stripe_seat_plan_id: Option, - #[serde( - rename = "stripeStoragePlanId", - skip_serializing_if = "Option::is_none" - )] - pub stripe_storage_plan_id: Option, - #[serde( - rename = "stripePremiumAccessPlanId", - skip_serializing_if = "Option::is_none" - )] - pub stripe_premium_access_plan_id: Option, - #[serde(rename = "basePrice", skip_serializing_if = "Option::is_none")] - pub base_price: Option, - #[serde(rename = "seatPrice", skip_serializing_if = "Option::is_none")] - pub seat_price: Option, - #[serde( - rename = "additionalStoragePricePerGb", - skip_serializing_if = "Option::is_none" - )] - pub additional_storage_price_per_gb: Option, - #[serde( - rename = "premiumAccessOptionPrice", - skip_serializing_if = "Option::is_none" - )] - pub premium_access_option_price: Option, - #[serde( - rename = "stripeServiceAccountPlanId", - skip_serializing_if = "Option::is_none" - )] - pub stripe_service_account_plan_id: Option, - #[serde( - rename = "additionalPricePerServiceAccount", - skip_serializing_if = "Option::is_none" - )] - pub additional_price_per_service_account: Option, - #[serde(rename = "baseServiceAccount", skip_serializing_if = "Option::is_none")] - pub base_service_account: Option, - #[serde(rename = "maxServiceAccounts", skip_serializing_if = "Option::is_none")] - pub max_service_accounts: Option, - #[serde( - rename = "maxAdditionalServiceAccounts", - skip_serializing_if = "Option::is_none" - )] - pub max_additional_service_accounts: Option, - #[serde( - rename = "hasAdditionalServiceAccountOption", - skip_serializing_if = "Option::is_none" - )] - pub has_additional_service_account_option: Option, - #[serde(rename = "maxProjects", skip_serializing_if = "Option::is_none")] - pub max_projects: Option, - #[serde(rename = "bitwardenProduct", skip_serializing_if = "Option::is_none")] - pub bitwarden_product: Option, + #[serde(rename = "secretsManager", skip_serializing_if = "Option::is_none")] + pub secrets_manager: Option>, + #[serde(rename = "passwordManager", skip_serializing_if = "Option::is_none")] + pub password_manager: Option>, } impl PlanResponseModel { @@ -166,15 +84,6 @@ impl PlanResponseModel { name_localization_key: None, description_localization_key: None, can_be_used_by_business: None, - base_seats: None, - base_storage_gb: None, - max_collections: None, - max_users: None, - has_additional_seats_option: None, - max_additional_seats: None, - has_additional_storage_option: None, - max_additional_storage: None, - has_premium_access_option: None, trial_period_days: None, has_self_host: None, has_policies: None, @@ -191,22 +100,8 @@ impl PlanResponseModel { display_sort_order: None, legacy_year: None, disabled: None, - stripe_plan_id: None, - stripe_seat_plan_id: None, - stripe_storage_plan_id: None, - stripe_premium_access_plan_id: None, - base_price: None, - seat_price: None, - additional_storage_price_per_gb: None, - premium_access_option_price: None, - stripe_service_account_plan_id: None, - additional_price_per_service_account: None, - base_service_account: None, - max_service_accounts: None, - max_additional_service_accounts: None, - has_additional_service_account_option: None, - max_projects: None, - bitwarden_product: None, + secrets_manager: None, + password_manager: None, } } } diff --git a/crates/bitwarden-api-api/src/models/plan_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/plan_response_model_list_response_model.rs index afbb0b849..15ce8c37a 100644 --- a/crates/bitwarden-api-api/src/models/plan_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/plan_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PlanResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/plan_type.rs b/crates/bitwarden-api-api/src/models/plan_type.rs index 62d713894..a43634b19 100644 --- a/crates/bitwarden-api-api/src/models/plan_type.rs +++ b/crates/bitwarden-api-api/src/models/plan_type.rs @@ -26,6 +26,11 @@ pub enum PlanType { Variant9 = 9, Variant10 = 10, Variant11 = 11, + Variant12 = 12, + Variant13 = 13, + Variant14 = 14, + Variant15 = 15, + Variant16 = 16, } impl ToString for PlanType { @@ -43,6 +48,11 @@ impl ToString for PlanType { Self::Variant9 => String::from("9"), Self::Variant10 => String::from("10"), Self::Variant11 => String::from("11"), + Self::Variant12 => String::from("12"), + Self::Variant13 => String::from("13"), + Self::Variant14 => String::from("14"), + Self::Variant15 => String::from("15"), + Self::Variant16 => String::from("16"), } } } diff --git a/crates/bitwarden-api-api/src/models/policy_request_model.rs b/crates/bitwarden-api-api/src/models/policy_request_model.rs index 509b98c83..31b3880ea 100644 --- a/crates/bitwarden-api-api/src/models/policy_request_model.rs +++ b/crates/bitwarden-api-api/src/models/policy_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PolicyRequestModel { #[serde(rename = "type")] pub r#type: crate::models::PolicyType, diff --git a/crates/bitwarden-api-api/src/models/policy_response_model.rs b/crates/bitwarden-api-api/src/models/policy_response_model.rs index 4c5d4a633..bda9e87a5 100644 --- a/crates/bitwarden-api-api/src/models/policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/policy_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/policy_response_model_list_response_model.rs index 82ee4f996..bc96d434a 100644 --- a/crates/bitwarden-api-api/src/models/policy_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/policy_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PolicyResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/potential_grantee_response_model.rs b/crates/bitwarden-api-api/src/models/potential_grantee_response_model.rs index 895a48705..52adb76f6 100644 --- a/crates/bitwarden-api-api/src/models/potential_grantee_response_model.rs +++ b/crates/bitwarden-api-api/src/models/potential_grantee_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PotentialGranteeResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -20,6 +20,10 @@ pub struct PotentialGranteeResponseModel { pub r#type: Option, #[serde(rename = "email", skip_serializing_if = "Option::is_none")] pub email: Option, + #[serde(rename = "currentUserInGroup", skip_serializing_if = "Option::is_none")] + pub current_user_in_group: Option, + #[serde(rename = "currentUser", skip_serializing_if = "Option::is_none")] + pub current_user: Option, } impl PotentialGranteeResponseModel { @@ -30,6 +34,8 @@ impl PotentialGranteeResponseModel { name: None, r#type: None, email: None, + current_user_in_group: None, + current_user: None, } } } diff --git a/crates/bitwarden-api-api/src/models/potential_grantee_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/potential_grantee_response_model_list_response_model.rs index acbe8f4bb..65da6ae07 100644 --- a/crates/bitwarden-api-api/src/models/potential_grantee_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/potential_grantee_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PotentialGranteeResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/prelogin_request_model.rs b/crates/bitwarden-api-api/src/models/prelogin_request_model.rs index 4749b2abd..855c9fb09 100644 --- a/crates/bitwarden-api-api/src/models/prelogin_request_model.rs +++ b/crates/bitwarden-api-api/src/models/prelogin_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PreloginRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-api/src/models/prelogin_response_model.rs b/crates/bitwarden-api-api/src/models/prelogin_response_model.rs index 2b4589486..bf5d536d2 100644 --- a/crates/bitwarden-api-api/src/models/prelogin_response_model.rs +++ b/crates/bitwarden-api-api/src/models/prelogin_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PreloginResponseModel { #[serde(rename = "kdf", skip_serializing_if = "Option::is_none")] pub kdf: Option, diff --git a/crates/bitwarden-api-api/src/models/product_type.rs b/crates/bitwarden-api-api/src/models/product_type.rs index dd4882690..aa4ebedc5 100644 --- a/crates/bitwarden-api-api/src/models/product_type.rs +++ b/crates/bitwarden-api-api/src/models/product_type.rs @@ -18,6 +18,7 @@ pub enum ProductType { Variant1 = 1, Variant2 = 2, Variant3 = 3, + Variant4 = 4, } impl ToString for ProductType { @@ -27,6 +28,7 @@ impl ToString for ProductType { Self::Variant1 => String::from("1"), Self::Variant2 => String::from("2"), Self::Variant3 => String::from("3"), + Self::Variant4 => String::from("4"), } } } diff --git a/crates/bitwarden-api-api/src/models/profile_organization_response_model.rs b/crates/bitwarden-api-api/src/models/profile_organization_response_model.rs index ec818fb7d..5984d13ae 100644 --- a/crates/bitwarden-api-api/src/models/profile_organization_response_model.rs +++ b/crates/bitwarden-api-api/src/models/profile_organization_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProfileOrganizationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -133,6 +133,21 @@ pub struct ProfileOrganizationResponseModel { skip_serializing_if = "Option::is_none" )] pub access_secrets_manager: Option, + #[serde( + rename = "limitCollectionCreationDeletion", + skip_serializing_if = "Option::is_none" + )] + pub limit_collection_creation_deletion: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, + #[serde( + rename = "flexibleCollections", + skip_serializing_if = "Option::is_none" + )] + pub flexible_collections: Option, } impl ProfileOrganizationResponseModel { @@ -183,6 +198,9 @@ impl ProfileOrganizationResponseModel { family_sponsorship_valid_until: None, family_sponsorship_to_delete: None, access_secrets_manager: None, + limit_collection_creation_deletion: None, + allow_admin_access_to_all_collection_items: None, + flexible_collections: None, } } } diff --git a/crates/bitwarden-api-api/src/models/profile_organization_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/profile_organization_response_model_list_response_model.rs index e794446dd..c1fb06209 100644 --- a/crates/bitwarden-api-api/src/models/profile_organization_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/profile_organization_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProfileOrganizationResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/profile_provider_organization_response_model.rs b/crates/bitwarden-api-api/src/models/profile_provider_organization_response_model.rs index 9f8a03ba9..af8b13fb6 100644 --- a/crates/bitwarden-api-api/src/models/profile_provider_organization_response_model.rs +++ b/crates/bitwarden-api-api/src/models/profile_provider_organization_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProfileProviderOrganizationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -133,6 +133,21 @@ pub struct ProfileProviderOrganizationResponseModel { skip_serializing_if = "Option::is_none" )] pub access_secrets_manager: Option, + #[serde( + rename = "limitCollectionCreationDeletion", + skip_serializing_if = "Option::is_none" + )] + pub limit_collection_creation_deletion: Option, + #[serde( + rename = "allowAdminAccessToAllCollectionItems", + skip_serializing_if = "Option::is_none" + )] + pub allow_admin_access_to_all_collection_items: Option, + #[serde( + rename = "flexibleCollections", + skip_serializing_if = "Option::is_none" + )] + pub flexible_collections: Option, } impl ProfileProviderOrganizationResponseModel { @@ -183,6 +198,9 @@ impl ProfileProviderOrganizationResponseModel { family_sponsorship_valid_until: None, family_sponsorship_to_delete: None, access_secrets_manager: None, + limit_collection_creation_deletion: None, + allow_admin_access_to_all_collection_items: None, + flexible_collections: None, } } } diff --git a/crates/bitwarden-api-api/src/models/profile_provider_response_model.rs b/crates/bitwarden-api-api/src/models/profile_provider_response_model.rs index 06426a78b..f9a5cd392 100644 --- a/crates/bitwarden-api-api/src/models/profile_provider_response_model.rs +++ b/crates/bitwarden-api-api/src/models/profile_provider_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProfileProviderResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/profile_response_model.rs b/crates/bitwarden-api-api/src/models/profile_response_model.rs index 7ccf71a1f..a151875b1 100644 --- a/crates/bitwarden-api-api/src/models/profile_response_model.rs +++ b/crates/bitwarden-api-api/src/models/profile_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProfileResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -45,6 +45,8 @@ pub struct ProfileResponseModel { pub uses_key_connector: Option, #[serde(rename = "avatarColor", skip_serializing_if = "Option::is_none")] pub avatar_color: Option, + #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] + pub creation_date: Option, #[serde(rename = "organizations", skip_serializing_if = "Option::is_none")] pub organizations: Option>, #[serde(rename = "providers", skip_serializing_if = "Option::is_none")] @@ -76,6 +78,7 @@ impl ProfileResponseModel { force_password_reset: None, uses_key_connector: None, avatar_color: None, + creation_date: None, organizations: None, providers: None, provider_organizations: None, diff --git a/crates/bitwarden-api-api/src/models/project_access_policies_response_model.rs b/crates/bitwarden-api-api/src/models/project_access_policies_response_model.rs index 9bb4bc4d8..17daba3d9 100644 --- a/crates/bitwarden-api-api/src/models/project_access_policies_response_model.rs +++ b/crates/bitwarden-api-api/src/models/project_access_policies_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProjectAccessPoliciesResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/project_create_request_model.rs b/crates/bitwarden-api-api/src/models/project_create_request_model.rs index a74931e1f..dcec98f62 100644 --- a/crates/bitwarden-api-api/src/models/project_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/project_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProjectCreateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/project_people_access_policies_response_model.rs b/crates/bitwarden-api-api/src/models/project_people_access_policies_response_model.rs new file mode 100644 index 000000000..27655433f --- /dev/null +++ b/crates/bitwarden-api-api/src/models/project_people_access_policies_response_model.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct ProjectPeopleAccessPoliciesResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "userAccessPolicies", skip_serializing_if = "Option::is_none")] + pub user_access_policies: Option>, + #[serde( + rename = "groupAccessPolicies", + skip_serializing_if = "Option::is_none" + )] + pub group_access_policies: Option>, +} + +impl ProjectPeopleAccessPoliciesResponseModel { + pub fn new() -> ProjectPeopleAccessPoliciesResponseModel { + ProjectPeopleAccessPoliciesResponseModel { + object: None, + user_access_policies: None, + group_access_policies: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/project_response_model.rs b/crates/bitwarden-api-api/src/models/project_response_model.rs index a6045885d..93bc6f14e 100644 --- a/crates/bitwarden-api-api/src/models/project_response_model.rs +++ b/crates/bitwarden-api-api/src/models/project_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProjectResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/project_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/project_response_model_list_response_model.rs index 4978edbe6..b6143ddf5 100644 --- a/crates/bitwarden-api-api/src/models/project_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/project_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProjectResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/project_update_request_model.rs b/crates/bitwarden-api-api/src/models/project_update_request_model.rs index a0c85cdf8..913168899 100644 --- a/crates/bitwarden-api-api/src/models/project_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/project_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProjectUpdateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/protected_device_response_model.rs b/crates/bitwarden-api-api/src/models/protected_device_response_model.rs index f34e1128d..055d34c20 100644 --- a/crates/bitwarden-api-api/src/models/protected_device_response_model.rs +++ b/crates/bitwarden-api-api/src/models/protected_device_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProtectedDeviceResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_organization_add_request_model.rs b/crates/bitwarden-api-api/src/models/provider_organization_add_request_model.rs index 2c8c66697..c25569d90 100644 --- a/crates/bitwarden-api-api/src/models/provider_organization_add_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_organization_add_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderOrganizationAddRequestModel { #[serde(rename = "organizationId")] pub organization_id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/provider_organization_create_request_model.rs b/crates/bitwarden-api-api/src/models/provider_organization_create_request_model.rs index 69e5c63d6..4cfb59343 100644 --- a/crates/bitwarden-api-api/src/models/provider_organization_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_organization_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderOrganizationCreateRequestModel { #[serde(rename = "clientOwnerEmail")] pub client_owner_email: String, diff --git a/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model.rs b/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model.rs index bb4e3a029..2c8e99a99 100644 --- a/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderOrganizationOrganizationDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model_list_response_model.rs index 6e4671153..114240fc1 100644 --- a/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_organization_organization_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderOrganizationOrganizationDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_organization_response_model.rs b/crates/bitwarden-api-api/src/models/provider_organization_response_model.rs index c72f7a9bf..a1d339190 100644 --- a/crates/bitwarden-api-api/src/models/provider_organization_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_organization_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderOrganizationResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_response_model.rs b/crates/bitwarden-api-api/src/models/provider_response_model.rs index 2ca58e08c..83cfe0b69 100644 --- a/crates/bitwarden-api-api/src/models/provider_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -30,6 +30,8 @@ pub struct ProviderResponseModel { pub business_tax_number: Option, #[serde(rename = "billingEmail", skip_serializing_if = "Option::is_none")] pub billing_email: Option, + #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] + pub creation_date: Option, } impl ProviderResponseModel { @@ -45,6 +47,7 @@ impl ProviderResponseModel { business_country: None, business_tax_number: None, billing_email: None, + creation_date: None, } } } diff --git a/crates/bitwarden-api-api/src/models/provider_setup_request_model.rs b/crates/bitwarden-api-api/src/models/provider_setup_request_model.rs index 5ffdc9a6e..dacc39a8d 100644 --- a/crates/bitwarden-api-api/src/models/provider_setup_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_setup_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderSetupRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/provider_update_request_model.rs b/crates/bitwarden-api-api/src/models/provider_update_request_model.rs index bf03dfc66..39d892904 100644 --- a/crates/bitwarden-api-api/src/models/provider_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUpdateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/provider_user_accept_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_accept_request_model.rs index 3f037c22b..cf526fa7c 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_accept_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_accept_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserAcceptRequestModel { #[serde(rename = "token")] pub token: String, diff --git a/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model.rs index 0b80432ec..78bc34e17 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserBulkConfirmRequestModel { #[serde(rename = "keys")] pub keys: Vec, diff --git a/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model_entry.rs b/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model_entry.rs index eac03ea15..cc5c82d82 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model_entry.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_bulk_confirm_request_model_entry.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserBulkConfirmRequestModelEntry { #[serde(rename = "id")] pub id: uuid::Uuid, diff --git a/crates/bitwarden-api-api/src/models/provider_user_bulk_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_bulk_request_model.rs index 697206108..5e4cdca5a 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_bulk_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_bulk_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserBulkRequestModel { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model.rs index de52b31f7..00da85ac4 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserBulkResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model_list_response_model.rs index 3954b0948..9f76667b9 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_bulk_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserBulkResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_confirm_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_confirm_request_model.rs index 333809dfd..917b858cf 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_confirm_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_confirm_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserConfirmRequestModel { #[serde(rename = "key")] pub key: String, diff --git a/crates/bitwarden-api-api/src/models/provider_user_invite_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_invite_request_model.rs index c547d5cb5..6113957bb 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_invite_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_invite_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserInviteRequestModel { #[serde(rename = "emails")] pub emails: Vec, diff --git a/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model.rs index 9743af7b1..8dbd5f0a7 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserPublicKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model_list_response_model.rs index 04a8e5584..154070458 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_public_key_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserPublicKeyResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_response_model.rs index db7fac194..3ffeaa926 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_update_request_model.rs b/crates/bitwarden-api-api/src/models/provider_user_update_request_model.rs index 8707fdb24..eeb36bff7 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserUpdateRequestModel { #[serde(rename = "type")] pub r#type: crate::models::ProviderUserType, diff --git a/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model.rs index 774865640..74f6169cb 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserUserDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model_list_response_model.rs index 963b28c90..7e9a171fe 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_user_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ProviderUserUserDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/pub_key_cred_param.rs b/crates/bitwarden-api-api/src/models/pub_key_cred_param.rs new file mode 100644 index 000000000..670062fa1 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/pub_key_cred_param.rs @@ -0,0 +1,26 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PubKeyCredParam { + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, + #[serde(rename = "alg", skip_serializing_if = "Option::is_none")] + pub alg: Option, +} + +impl PubKeyCredParam { + pub fn new() -> PubKeyCredParam { + PubKeyCredParam { + r#type: None, + alg: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/public_key_credential_descriptor.rs b/crates/bitwarden-api-api/src/models/public_key_credential_descriptor.rs new file mode 100644 index 000000000..e266e1105 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/public_key_credential_descriptor.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PublicKeyCredentialDescriptor { + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "transports", skip_serializing_if = "Option::is_none")] + pub transports: Option>, +} + +impl PublicKeyCredentialDescriptor { + pub fn new() -> PublicKeyCredentialDescriptor { + PublicKeyCredentialDescriptor { + r#type: None, + id: None, + transports: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/public_key_credential_rp_entity.rs b/crates/bitwarden-api-api/src/models/public_key_credential_rp_entity.rs new file mode 100644 index 000000000..318405f71 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/public_key_credential_rp_entity.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PublicKeyCredentialRpEntity { + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "icon", skip_serializing_if = "Option::is_none")] + pub icon: Option, +} + +impl PublicKeyCredentialRpEntity { + pub fn new() -> PublicKeyCredentialRpEntity { + PublicKeyCredentialRpEntity { + id: None, + name: None, + icon: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/push_registration_request_model.rs b/crates/bitwarden-api-api/src/models/push_registration_request_model.rs index 190ce4555..aca447e3f 100644 --- a/crates/bitwarden-api-api/src/models/push_registration_request_model.rs +++ b/crates/bitwarden-api-api/src/models/push_registration_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PushRegistrationRequestModel { #[serde(rename = "deviceId")] pub device_id: String, diff --git a/crates/bitwarden-api-api/src/models/push_send_request_model.rs b/crates/bitwarden-api-api/src/models/push_send_request_model.rs index 2ef909c16..d064b78e2 100644 --- a/crates/bitwarden-api-api/src/models/push_send_request_model.rs +++ b/crates/bitwarden-api-api/src/models/push_send_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PushSendRequestModel { #[serde(rename = "userId", skip_serializing_if = "Option::is_none")] pub user_id: Option, diff --git a/crates/bitwarden-api-api/src/models/push_update_request_model.rs b/crates/bitwarden-api-api/src/models/push_update_request_model.rs index a6030831a..2fda855bb 100644 --- a/crates/bitwarden-api-api/src/models/push_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/push_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PushUpdateRequestModel { #[serde(rename = "deviceIds")] pub device_ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/register_request_model.rs b/crates/bitwarden-api-api/src/models/register_request_model.rs index dbdd37ad6..b4a0d4b8d 100644 --- a/crates/bitwarden-api-api/src/models/register_request_model.rs +++ b/crates/bitwarden-api-api/src/models/register_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RegisterRequestModel { #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, diff --git a/crates/bitwarden-api-api/src/models/register_response_model.rs b/crates/bitwarden-api-api/src/models/register_response_model.rs index 55710d5b5..629d2af4f 100644 --- a/crates/bitwarden-api-api/src/models/register_response_model.rs +++ b/crates/bitwarden-api-api/src/models/register_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RegisterResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/reset_password_with_org_id_request_model.rs b/crates/bitwarden-api-api/src/models/reset_password_with_org_id_request_model.rs new file mode 100644 index 000000000..c74c02592 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/reset_password_with_org_id_request_model.rs @@ -0,0 +1,26 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct ResetPasswordWithOrgIdRequestModel { + #[serde(rename = "resetPasswordKey", skip_serializing_if = "Option::is_none")] + pub reset_password_key: Option, + #[serde(rename = "organizationId")] + pub organization_id: uuid::Uuid, +} + +impl ResetPasswordWithOrgIdRequestModel { + pub fn new(organization_id: uuid::Uuid) -> ResetPasswordWithOrgIdRequestModel { + ResetPasswordWithOrgIdRequestModel { + reset_password_key: None, + organization_id, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/response_data.rs b/crates/bitwarden-api-api/src/models/response_data.rs index 33f138cd6..9ff2a66e0 100644 --- a/crates/bitwarden-api-api/src/models/response_data.rs +++ b/crates/bitwarden-api-api/src/models/response_data.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ResponseData { #[serde(rename = "attestationObject", skip_serializing_if = "Option::is_none")] pub attestation_object: Option, diff --git a/crates/bitwarden-api-api/src/models/revoke_access_tokens_request.rs b/crates/bitwarden-api-api/src/models/revoke_access_tokens_request.rs index 53fcece6d..20d18ab59 100644 --- a/crates/bitwarden-api-api/src/models/revoke_access_tokens_request.rs +++ b/crates/bitwarden-api-api/src/models/revoke_access_tokens_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RevokeAccessTokensRequest { #[serde(rename = "ids")] pub ids: Vec, diff --git a/crates/bitwarden-api-api/src/models/secret_create_request_model.rs b/crates/bitwarden-api-api/src/models/secret_create_request_model.rs index a99bc551e..7bc23b871 100644 --- a/crates/bitwarden-api-api/src/models/secret_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/secret_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretCreateRequestModel { #[serde(rename = "key")] pub key: String, diff --git a/crates/bitwarden-api-api/src/models/secret_response_inner_project.rs b/crates/bitwarden-api-api/src/models/secret_response_inner_project.rs index bdd2c4fe0..25be360ad 100644 --- a/crates/bitwarden-api-api/src/models/secret_response_inner_project.rs +++ b/crates/bitwarden-api-api/src/models/secret_response_inner_project.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretResponseInnerProject { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/secret_response_model.rs b/crates/bitwarden-api-api/src/models/secret_response_model.rs index 2dcf8b192..dffea3122 100644 --- a/crates/bitwarden-api-api/src/models/secret_response_model.rs +++ b/crates/bitwarden-api-api/src/models/secret_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/secret_update_request_model.rs b/crates/bitwarden-api-api/src/models/secret_update_request_model.rs index a4675c6ba..67ae4ade2 100644 --- a/crates/bitwarden-api-api/src/models/secret_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/secret_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretUpdateRequestModel { #[serde(rename = "key")] pub key: String, diff --git a/crates/bitwarden-api-api/src/models/secret_verification_request_model.rs b/crates/bitwarden-api-api/src/models/secret_verification_request_model.rs index f4774d5b6..85ceee419 100644 --- a/crates/bitwarden-api-api/src/models/secret_verification_request_model.rs +++ b/crates/bitwarden-api-api/src/models/secret_verification_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretVerificationRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/secret_with_projects_inner_project.rs b/crates/bitwarden-api-api/src/models/secret_with_projects_inner_project.rs index 3b68f65d5..cce3b239c 100644 --- a/crates/bitwarden-api-api/src/models/secret_with_projects_inner_project.rs +++ b/crates/bitwarden-api-api/src/models/secret_with_projects_inner_project.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretWithProjectsInnerProject { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/secret_with_projects_list_response_model.rs b/crates/bitwarden-api-api/src/models/secret_with_projects_list_response_model.rs index 1a832ab48..046e698f4 100644 --- a/crates/bitwarden-api-api/src/models/secret_with_projects_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/secret_with_projects_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretWithProjectsListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/secrets_manager_plan_features_response_model.rs b/crates/bitwarden-api-api/src/models/secrets_manager_plan_features_response_model.rs new file mode 100644 index 000000000..ef8d32f04 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/secrets_manager_plan_features_response_model.rs @@ -0,0 +1,86 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct SecretsManagerPlanFeaturesResponseModel { + #[serde(rename = "maxServiceAccounts", skip_serializing_if = "Option::is_none")] + pub max_service_accounts: Option, + #[serde( + rename = "allowServiceAccountsAutoscale", + skip_serializing_if = "Option::is_none" + )] + pub allow_service_accounts_autoscale: Option, + #[serde( + rename = "stripeServiceAccountPlanId", + skip_serializing_if = "Option::is_none" + )] + pub stripe_service_account_plan_id: Option, + #[serde( + rename = "additionalPricePerServiceAccount", + skip_serializing_if = "Option::is_none" + )] + pub additional_price_per_service_account: Option, + #[serde(rename = "baseServiceAccount", skip_serializing_if = "Option::is_none")] + pub base_service_account: Option, + #[serde( + rename = "maxAdditionalServiceAccount", + skip_serializing_if = "Option::is_none" + )] + pub max_additional_service_account: Option, + #[serde( + rename = "hasAdditionalServiceAccountOption", + skip_serializing_if = "Option::is_none" + )] + pub has_additional_service_account_option: Option, + #[serde(rename = "stripeSeatPlanId", skip_serializing_if = "Option::is_none")] + pub stripe_seat_plan_id: Option, + #[serde( + rename = "hasAdditionalSeatsOption", + skip_serializing_if = "Option::is_none" + )] + pub has_additional_seats_option: Option, + #[serde(rename = "basePrice", skip_serializing_if = "Option::is_none")] + pub base_price: Option, + #[serde(rename = "seatPrice", skip_serializing_if = "Option::is_none")] + pub seat_price: Option, + #[serde(rename = "baseSeats", skip_serializing_if = "Option::is_none")] + pub base_seats: Option, + #[serde(rename = "maxSeats", skip_serializing_if = "Option::is_none")] + pub max_seats: Option, + #[serde(rename = "maxAdditionalSeats", skip_serializing_if = "Option::is_none")] + pub max_additional_seats: Option, + #[serde(rename = "allowSeatAutoscale", skip_serializing_if = "Option::is_none")] + pub allow_seat_autoscale: Option, + #[serde(rename = "maxProjects", skip_serializing_if = "Option::is_none")] + pub max_projects: Option, +} + +impl SecretsManagerPlanFeaturesResponseModel { + pub fn new() -> SecretsManagerPlanFeaturesResponseModel { + SecretsManagerPlanFeaturesResponseModel { + max_service_accounts: None, + allow_service_accounts_autoscale: None, + stripe_service_account_plan_id: None, + additional_price_per_service_account: None, + base_service_account: None, + max_additional_service_account: None, + has_additional_service_account_option: None, + stripe_seat_plan_id: None, + has_additional_seats_option: None, + base_price: None, + seat_price: None, + base_seats: None, + max_seats: None, + max_additional_seats: None, + allow_seat_autoscale: None, + max_projects: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs b/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs index 2510d8f2c..cf27fa764 100644 --- a/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs +++ b/crates/bitwarden-api-api/src/models/secrets_manager_subscribe_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretsManagerSubscribeRequestModel { #[serde(rename = "additionalSmSeats")] pub additional_sm_seats: i32, diff --git a/crates/bitwarden-api-api/src/models/secrets_manager_subscription_update_request_model.rs b/crates/bitwarden-api-api/src/models/secrets_manager_subscription_update_request_model.rs index 406769bce..b61e9c2fe 100644 --- a/crates/bitwarden-api-api/src/models/secrets_manager_subscription_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/secrets_manager_subscription_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretsManagerSubscriptionUpdateRequestModel { #[serde(rename = "seatAdjustment")] pub seat_adjustment: i32, diff --git a/crates/bitwarden-api-api/src/models/secrets_with_projects_inner_secret.rs b/crates/bitwarden-api-api/src/models/secrets_with_projects_inner_secret.rs index 45dcbd9c1..2b6673ef1 100644 --- a/crates/bitwarden-api-api/src/models/secrets_with_projects_inner_secret.rs +++ b/crates/bitwarden-api-api/src/models/secrets_with_projects_inner_secret.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SecretsWithProjectsInnerSecret { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/selection_read_only_request_model.rs b/crates/bitwarden-api-api/src/models/selection_read_only_request_model.rs index 2d7d0c4da..81695f1d7 100644 --- a/crates/bitwarden-api-api/src/models/selection_read_only_request_model.rs +++ b/crates/bitwarden-api-api/src/models/selection_read_only_request_model.rs @@ -8,22 +8,25 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SelectionReadOnlyRequestModel { #[serde(rename = "id")] - pub id: String, + pub id: uuid::Uuid, #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")] pub read_only: Option, #[serde(rename = "hidePasswords", skip_serializing_if = "Option::is_none")] pub hide_passwords: Option, + #[serde(rename = "manage", skip_serializing_if = "Option::is_none")] + pub manage: Option, } impl SelectionReadOnlyRequestModel { - pub fn new(id: String) -> SelectionReadOnlyRequestModel { + pub fn new(id: uuid::Uuid) -> SelectionReadOnlyRequestModel { SelectionReadOnlyRequestModel { id, read_only: None, hide_passwords: None, + manage: None, } } } diff --git a/crates/bitwarden-api-api/src/models/selection_read_only_response_model.rs b/crates/bitwarden-api-api/src/models/selection_read_only_response_model.rs index c989fccf0..b24fd8368 100644 --- a/crates/bitwarden-api-api/src/models/selection_read_only_response_model.rs +++ b/crates/bitwarden-api-api/src/models/selection_read_only_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SelectionReadOnlyResponseModel { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, @@ -16,6 +16,8 @@ pub struct SelectionReadOnlyResponseModel { pub read_only: Option, #[serde(rename = "hidePasswords", skip_serializing_if = "Option::is_none")] pub hide_passwords: Option, + #[serde(rename = "manage", skip_serializing_if = "Option::is_none")] + pub manage: Option, } impl SelectionReadOnlyResponseModel { @@ -24,6 +26,7 @@ impl SelectionReadOnlyResponseModel { id: None, read_only: None, hide_passwords: None, + manage: None, } } } diff --git a/crates/bitwarden-api-api/src/models/self_hosted_organization_license_request_model.rs b/crates/bitwarden-api-api/src/models/self_hosted_organization_license_request_model.rs index 935589714..3e5038e38 100644 --- a/crates/bitwarden-api-api/src/models/self_hosted_organization_license_request_model.rs +++ b/crates/bitwarden-api-api/src/models/self_hosted_organization_license_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SelfHostedOrganizationLicenseRequestModel { #[serde(rename = "licenseKey", skip_serializing_if = "Option::is_none")] pub license_key: Option, diff --git a/crates/bitwarden-api-api/src/models/send_access_request_model.rs b/crates/bitwarden-api-api/src/models/send_access_request_model.rs index 2cdff93c3..51192dc02 100644 --- a/crates/bitwarden-api-api/src/models/send_access_request_model.rs +++ b/crates/bitwarden-api-api/src/models/send_access_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendAccessRequestModel { #[serde(rename = "password", skip_serializing_if = "Option::is_none")] pub password: Option, diff --git a/crates/bitwarden-api-api/src/models/send_file_model.rs b/crates/bitwarden-api-api/src/models/send_file_model.rs index 88d15c50e..e94c99ea2 100644 --- a/crates/bitwarden-api-api/src/models/send_file_model.rs +++ b/crates/bitwarden-api-api/src/models/send_file_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendFileModel { #[serde(rename = "id", skip_serializing_if = "Option::is_none")] pub id: Option, diff --git a/crates/bitwarden-api-api/src/models/send_file_upload_data_response_model.rs b/crates/bitwarden-api-api/src/models/send_file_upload_data_response_model.rs index 0c22f4126..0f1329824 100644 --- a/crates/bitwarden-api-api/src/models/send_file_upload_data_response_model.rs +++ b/crates/bitwarden-api-api/src/models/send_file_upload_data_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendFileUploadDataResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/send_request_model.rs b/crates/bitwarden-api-api/src/models/send_request_model.rs index 2d528623c..e117b82fb 100644 --- a/crates/bitwarden-api-api/src/models/send_request_model.rs +++ b/crates/bitwarden-api-api/src/models/send_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendRequestModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/send_response_model.rs b/crates/bitwarden-api-api/src/models/send_response_model.rs index 76af62ed4..c74ddd7c4 100644 --- a/crates/bitwarden-api-api/src/models/send_response_model.rs +++ b/crates/bitwarden-api-api/src/models/send_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/send_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/send_response_model_list_response_model.rs index 608927413..c0870e19c 100644 --- a/crates/bitwarden-api-api/src/models/send_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/send_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/send_text_model.rs b/crates/bitwarden-api-api/src/models/send_text_model.rs index 3c37ba152..58f2effd0 100644 --- a/crates/bitwarden-api-api/src/models/send_text_model.rs +++ b/crates/bitwarden-api-api/src/models/send_text_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendTextModel { #[serde(rename = "text", skip_serializing_if = "Option::is_none")] pub text: Option, diff --git a/crates/bitwarden-api-api/src/models/send_with_id_request_model.rs b/crates/bitwarden-api-api/src/models/send_with_id_request_model.rs index 8c31ae2ff..06dc03a95 100644 --- a/crates/bitwarden-api-api/src/models/send_with_id_request_model.rs +++ b/crates/bitwarden-api-api/src/models/send_with_id_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SendWithIdRequestModel { #[serde(rename = "type", skip_serializing_if = "Option::is_none")] pub r#type: Option, diff --git a/crates/bitwarden-api-api/src/models/server_config_response_model.rs b/crates/bitwarden-api-api/src/models/server_config_response_model.rs index 46d417394..a5603808f 100644 --- a/crates/bitwarden-api-api/src/models/server_config_response_model.rs +++ b/crates/bitwarden-api-api/src/models/server_config_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServerConfigResponseModel { #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_create_request_model.rs b/crates/bitwarden-api-api/src/models/service_account_create_request_model.rs index f34686774..ebebc8f96 100644 --- a/crates/bitwarden-api-api/src/models/service_account_create_request_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_create_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountCreateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/service_account_people_access_policies_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_people_access_policies_response_model.rs new file mode 100644 index 000000000..3b38851f4 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/service_account_people_access_policies_response_model.rs @@ -0,0 +1,34 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct ServiceAccountPeopleAccessPoliciesResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "userAccessPolicies", skip_serializing_if = "Option::is_none")] + pub user_access_policies: + Option>, + #[serde( + rename = "groupAccessPolicies", + skip_serializing_if = "Option::is_none" + )] + pub group_access_policies: + Option>, +} + +impl ServiceAccountPeopleAccessPoliciesResponseModel { + pub fn new() -> ServiceAccountPeopleAccessPoliciesResponseModel { + ServiceAccountPeopleAccessPoliciesResponseModel { + object: None, + user_access_policies: None, + group_access_policies: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model.rs index f734f6538..8eb850e01 100644 --- a/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountProjectAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model_list_response_model.rs index 307f2b333..531970536 100644 --- a/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_project_access_policy_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountProjectAccessPolicyResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_response_model.rs index ec43e6014..0cba8669a 100644 --- a/crates/bitwarden-api-api/src/models/service_account_response_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs index 5be4d8bb1..f8b8ce339 100644 --- a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountSecretsDetailsResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs index 5edfbefba..81ac10efa 100644 --- a/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_secrets_details_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountSecretsDetailsResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/service_account_update_request_model.rs b/crates/bitwarden-api-api/src/models/service_account_update_request_model.rs index 842760819..400617ed8 100644 --- a/crates/bitwarden-api-api/src/models/service_account_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/service_account_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ServiceAccountUpdateRequestModel { #[serde(rename = "name")] pub name: String, diff --git a/crates/bitwarden-api-api/src/models/set_key_connector_key_request_model.rs b/crates/bitwarden-api-api/src/models/set_key_connector_key_request_model.rs index a39326e05..8da90aa4e 100644 --- a/crates/bitwarden-api-api/src/models/set_key_connector_key_request_model.rs +++ b/crates/bitwarden-api-api/src/models/set_key_connector_key_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SetKeyConnectorKeyRequestModel { #[serde(rename = "key")] pub key: String, diff --git a/crates/bitwarden-api-api/src/models/set_password_request_model.rs b/crates/bitwarden-api-api/src/models/set_password_request_model.rs index f7b3e3e61..30b04c9fc 100644 --- a/crates/bitwarden-api-api/src/models/set_password_request_model.rs +++ b/crates/bitwarden-api-api/src/models/set_password_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SetPasswordRequestModel { #[serde(rename = "masterPasswordHash")] pub master_password_hash: String, @@ -16,8 +16,8 @@ pub struct SetPasswordRequestModel { pub key: String, #[serde(rename = "masterPasswordHint", skip_serializing_if = "Option::is_none")] pub master_password_hint: Option, - #[serde(rename = "keys")] - pub keys: Box, + #[serde(rename = "keys", skip_serializing_if = "Option::is_none")] + pub keys: Option>, #[serde(rename = "kdf")] pub kdf: crate::models::KdfType, #[serde(rename = "kdfIterations")] @@ -34,7 +34,6 @@ impl SetPasswordRequestModel { pub fn new( master_password_hash: String, key: String, - keys: crate::models::KeysRequestModel, kdf: crate::models::KdfType, kdf_iterations: i32, ) -> SetPasswordRequestModel { @@ -42,7 +41,7 @@ impl SetPasswordRequestModel { master_password_hash, key, master_password_hint: None, - keys: Box::new(keys), + keys: None, kdf, kdf_iterations, kdf_memory: None, diff --git a/crates/bitwarden-api-api/src/models/sm_export_response_model.rs b/crates/bitwarden-api-api/src/models/sm_export_response_model.rs index 60ab8697c..71f821254 100644 --- a/crates/bitwarden-api-api/src/models/sm_export_response_model.rs +++ b/crates/bitwarden-api-api/src/models/sm_export_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SmExportResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/sm_import_request_model.rs b/crates/bitwarden-api-api/src/models/sm_import_request_model.rs index 431a87fe4..68e53efbb 100644 --- a/crates/bitwarden-api-api/src/models/sm_import_request_model.rs +++ b/crates/bitwarden-api-api/src/models/sm_import_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SmImportRequestModel { #[serde(rename = "projects", skip_serializing_if = "Option::is_none")] pub projects: Option>, diff --git a/crates/bitwarden-api-api/src/models/sso_configuration_data.rs b/crates/bitwarden-api-api/src/models/sso_configuration_data.rs index 2d898488e..1cf5ea714 100644 --- a/crates/bitwarden-api-api/src/models/sso_configuration_data.rs +++ b/crates/bitwarden-api-api/src/models/sso_configuration_data.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SsoConfigurationData { #[serde(rename = "configType", skip_serializing_if = "Option::is_none")] pub config_type: Option, @@ -108,6 +108,8 @@ pub struct SsoConfigurationData { skip_serializing_if = "Option::is_none" )] pub idp_want_authn_requests_signed: Option, + #[serde(rename = "spUniqueEntityId", skip_serializing_if = "Option::is_none")] + pub sp_unique_entity_id: Option, #[serde(rename = "spNameIdFormat", skip_serializing_if = "Option::is_none")] pub sp_name_id_format: Option, #[serde( @@ -163,6 +165,7 @@ impl SsoConfigurationData { idp_disable_outbound_logout_requests: None, idp_outbound_signing_algorithm: None, idp_want_authn_requests_signed: None, + sp_unique_entity_id: None, sp_name_id_format: None, sp_outbound_signing_algorithm: None, sp_signing_behavior: None, diff --git a/crates/bitwarden-api-api/src/models/sso_configuration_data_request.rs b/crates/bitwarden-api-api/src/models/sso_configuration_data_request.rs index 8e6f18ced..7b26413c8 100644 --- a/crates/bitwarden-api-api/src/models/sso_configuration_data_request.rs +++ b/crates/bitwarden-api-api/src/models/sso_configuration_data_request.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SsoConfigurationDataRequest { #[serde(rename = "configType")] pub config_type: crate::models::SsoType, @@ -63,6 +63,8 @@ pub struct SsoConfigurationDataRequest { skip_serializing_if = "Option::is_none" )] pub expected_return_acr_value: Option, + #[serde(rename = "spUniqueEntityId", skip_serializing_if = "Option::is_none")] + pub sp_unique_entity_id: Option, #[serde(rename = "spNameIdFormat", skip_serializing_if = "Option::is_none")] pub sp_name_id_format: Option, #[serde( @@ -149,6 +151,7 @@ impl SsoConfigurationDataRequest { additional_name_claim_types: None, acr_values: None, expected_return_acr_value: None, + sp_unique_entity_id: None, sp_name_id_format: None, sp_outbound_signing_algorithm: None, sp_signing_behavior: None, diff --git a/crates/bitwarden-api-api/src/models/sso_urls.rs b/crates/bitwarden-api-api/src/models/sso_urls.rs index 45bb286f0..fa0b03cfb 100644 --- a/crates/bitwarden-api-api/src/models/sso_urls.rs +++ b/crates/bitwarden-api-api/src/models/sso_urls.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SsoUrls { #[serde(rename = "callbackPath", skip_serializing_if = "Option::is_none")] pub callback_path: Option, @@ -19,6 +19,8 @@ pub struct SsoUrls { pub signed_out_callback_path: Option, #[serde(rename = "spEntityId", skip_serializing_if = "Option::is_none")] pub sp_entity_id: Option, + #[serde(rename = "spEntityIdStatic", skip_serializing_if = "Option::is_none")] + pub sp_entity_id_static: Option, #[serde(rename = "spMetadataUrl", skip_serializing_if = "Option::is_none")] pub sp_metadata_url: Option, #[serde(rename = "spAcsUrl", skip_serializing_if = "Option::is_none")] @@ -31,6 +33,7 @@ impl SsoUrls { callback_path: None, signed_out_callback_path: None, sp_entity_id: None, + sp_entity_id_static: None, sp_metadata_url: None, sp_acs_url: None, } diff --git a/crates/bitwarden-api-api/src/models/storage_request_model.rs b/crates/bitwarden-api-api/src/models/storage_request_model.rs index 5625f8874..8d7778a73 100644 --- a/crates/bitwarden-api-api/src/models/storage_request_model.rs +++ b/crates/bitwarden-api-api/src/models/storage_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct StorageRequestModel { #[serde(rename = "storageGbAdjustment")] pub storage_gb_adjustment: i32, diff --git a/crates/bitwarden-api-api/src/models/subscription_response_model.rs b/crates/bitwarden-api-api/src/models/subscription_response_model.rs index c21cbdbea..a3d80dba3 100644 --- a/crates/bitwarden-api-api/src/models/subscription_response_model.rs +++ b/crates/bitwarden-api-api/src/models/subscription_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SubscriptionResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -22,14 +22,10 @@ pub struct SubscriptionResponseModel { pub upcoming_invoice: Option>, #[serde(rename = "subscription", skip_serializing_if = "Option::is_none")] pub subscription: Option>, - #[serde(rename = "discount", skip_serializing_if = "Option::is_none")] - pub discount: Option>, #[serde(rename = "license", skip_serializing_if = "Option::is_none")] pub license: Option>, #[serde(rename = "expiration", skip_serializing_if = "Option::is_none")] pub expiration: Option, - #[serde(rename = "usingInAppPurchase", skip_serializing_if = "Option::is_none")] - pub using_in_app_purchase: Option, } impl SubscriptionResponseModel { @@ -41,10 +37,8 @@ impl SubscriptionResponseModel { max_storage_gb: None, upcoming_invoice: None, subscription: None, - discount: None, license: None, expiration: None, - using_in_app_purchase: None, } } } diff --git a/crates/bitwarden-api-api/src/models/sync_response_model.rs b/crates/bitwarden-api-api/src/models/sync_response_model.rs index 60b1d5f7b..757cecc14 100644 --- a/crates/bitwarden-api-api/src/models/sync_response_model.rs +++ b/crates/bitwarden-api-api/src/models/sync_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct SyncResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/tax_info_response_model.rs b/crates/bitwarden-api-api/src/models/tax_info_response_model.rs index 344e80f45..e7825b67c 100644 --- a/crates/bitwarden-api-api/src/models/tax_info_response_model.rs +++ b/crates/bitwarden-api-api/src/models/tax_info_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TaxInfoResponseModel { #[serde(rename = "taxIdNumber", skip_serializing_if = "Option::is_none")] pub tax_id_number: Option, diff --git a/crates/bitwarden-api-api/src/models/tax_info_update_request_model.rs b/crates/bitwarden-api-api/src/models/tax_info_update_request_model.rs index 969528e53..153fb27b0 100644 --- a/crates/bitwarden-api-api/src/models/tax_info_update_request_model.rs +++ b/crates/bitwarden-api-api/src/models/tax_info_update_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TaxInfoUpdateRequestModel { #[serde(rename = "country")] pub country: String, diff --git a/crates/bitwarden-api-api/src/models/tax_rate_response_model.rs b/crates/bitwarden-api-api/src/models/tax_rate_response_model.rs index 3ae819bf6..3980008c3 100644 --- a/crates/bitwarden-api-api/src/models/tax_rate_response_model.rs +++ b/crates/bitwarden-api-api/src/models/tax_rate_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TaxRateResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/tax_rate_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/tax_rate_response_model_list_response_model.rs index 5c23891b1..496b713ff 100644 --- a/crates/bitwarden-api-api/src/models/tax_rate_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/tax_rate_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TaxRateResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_authenticator_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_authenticator_response_model.rs index dde60927c..cf2707e15 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_authenticator_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_authenticator_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorAuthenticatorResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_duo_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_duo_response_model.rs index 833a98a3d..e0afc8212 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_duo_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_duo_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorDuoResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_email_request_model.rs b/crates/bitwarden-api-api/src/models/two_factor_email_request_model.rs index 614ad8f80..7d121412a 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_email_request_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_email_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorEmailRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_email_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_email_response_model.rs index afbbafd8d..a976dba0f 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_email_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_email_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorEmailResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_provider_request_model.rs b/crates/bitwarden-api-api/src/models/two_factor_provider_request_model.rs index 7c9b231b0..7b22d2a6b 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_provider_request_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_provider_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorProviderRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_provider_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_provider_response_model.rs index dbca32167..0c97a3088 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_provider_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_provider_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorProviderResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_provider_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_provider_response_model_list_response_model.rs index 7b71fee31..73a7b4d57 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_provider_response_model_list_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_provider_response_model_list_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorProviderResponseModelListResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_recover_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_recover_response_model.rs index 2267c134a..c35ce8a17 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_recover_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_recover_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorRecoverResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_recovery_request_model.rs b/crates/bitwarden-api-api/src/models/two_factor_recovery_request_model.rs index 2ceb17a83..425d528b3 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_recovery_request_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_recovery_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorRecoveryRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_web_authn_delete_request_model.rs b/crates/bitwarden-api-api/src/models/two_factor_web_authn_delete_request_model.rs index f104792fd..e981d0e5d 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_web_authn_delete_request_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_web_authn_delete_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorWebAuthnDeleteRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_web_authn_request_model.rs b/crates/bitwarden-api-api/src/models/two_factor_web_authn_request_model.rs index 34c7e1a9b..2139ad022 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_web_authn_request_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_web_authn_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorWebAuthnRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_web_authn_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_web_authn_response_model.rs index 96cb72e96..c372f2f45 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_web_authn_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_web_authn_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorWebAuthnResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/two_factor_yubi_key_response_model.rs b/crates/bitwarden-api-api/src/models/two_factor_yubi_key_response_model.rs index 1fecc82f3..f2122d29a 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_yubi_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_yubi_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct TwoFactorYubiKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/update_avatar_request_model.rs b/crates/bitwarden-api-api/src/models/update_avatar_request_model.rs index ea00c08c5..ea648983e 100644 --- a/crates/bitwarden-api-api/src/models/update_avatar_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_avatar_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateAvatarRequestModel { #[serde(rename = "avatarColor", skip_serializing_if = "Option::is_none")] pub avatar_color: Option, diff --git a/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs b/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs index e4d381d51..ab69cf249 100644 --- a/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_devices_trust_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateDevicesTrustRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/update_domains_request_model.rs b/crates/bitwarden-api-api/src/models/update_domains_request_model.rs index 9c651953d..7bf75cb8a 100644 --- a/crates/bitwarden-api-api/src/models/update_domains_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_domains_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateDomainsRequestModel { #[serde(rename = "equivalentDomains", skip_serializing_if = "Option::is_none")] pub equivalent_domains: Option>>, diff --git a/crates/bitwarden-api-api/src/models/update_key_request_model.rs b/crates/bitwarden-api-api/src/models/update_key_request_model.rs index 155679c8b..c6b298251 100644 --- a/crates/bitwarden-api-api/src/models/update_key_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_key_request_model.rs @@ -8,37 +8,44 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateKeyRequestModel { #[serde(rename = "masterPasswordHash")] pub master_password_hash: String, - #[serde(rename = "ciphers")] - pub ciphers: Vec, - #[serde(rename = "folders")] - pub folders: Vec, - #[serde(rename = "sends", skip_serializing_if = "Option::is_none")] - pub sends: Option>, - #[serde(rename = "privateKey")] - pub private_key: String, #[serde(rename = "key")] pub key: String, + #[serde(rename = "privateKey")] + pub private_key: String, + #[serde(rename = "ciphers", skip_serializing_if = "Option::is_none")] + pub ciphers: Option>, + #[serde(rename = "folders", skip_serializing_if = "Option::is_none")] + pub folders: Option>, + #[serde(rename = "sends", skip_serializing_if = "Option::is_none")] + pub sends: Option>, + #[serde( + rename = "emergencyAccessKeys", + skip_serializing_if = "Option::is_none" + )] + pub emergency_access_keys: Option>, + #[serde(rename = "resetPasswordKeys", skip_serializing_if = "Option::is_none")] + pub reset_password_keys: Option>, } impl UpdateKeyRequestModel { pub fn new( master_password_hash: String, - ciphers: Vec, - folders: Vec, - private_key: String, key: String, + private_key: String, ) -> UpdateKeyRequestModel { UpdateKeyRequestModel { master_password_hash, - ciphers, - folders, - sends: None, - private_key, key, + private_key, + ciphers: None, + folders: None, + sends: None, + emergency_access_keys: None, + reset_password_keys: None, } } } diff --git a/crates/bitwarden-api-api/src/models/update_profile_request_model.rs b/crates/bitwarden-api-api/src/models/update_profile_request_model.rs index 06677e170..deb6a9d9e 100644 --- a/crates/bitwarden-api-api/src/models/update_profile_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_profile_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateProfileRequestModel { #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, diff --git a/crates/bitwarden-api-api/src/models/update_temp_password_request_model.rs b/crates/bitwarden-api-api/src/models/update_temp_password_request_model.rs index abc8b00ca..40eebaab9 100644 --- a/crates/bitwarden-api-api/src/models/update_temp_password_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_temp_password_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateTempPasswordRequestModel { #[serde(rename = "newMasterPasswordHash")] pub new_master_password_hash: String, diff --git a/crates/bitwarden-api-api/src/models/update_two_factor_authenticator_request_model.rs b/crates/bitwarden-api-api/src/models/update_two_factor_authenticator_request_model.rs index c4e267218..245993415 100644 --- a/crates/bitwarden-api-api/src/models/update_two_factor_authenticator_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_two_factor_authenticator_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateTwoFactorAuthenticatorRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/update_two_factor_duo_request_model.rs b/crates/bitwarden-api-api/src/models/update_two_factor_duo_request_model.rs index 4bab5acb9..55a168af3 100644 --- a/crates/bitwarden-api-api/src/models/update_two_factor_duo_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_two_factor_duo_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateTwoFactorDuoRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/update_two_factor_email_request_model.rs b/crates/bitwarden-api-api/src/models/update_two_factor_email_request_model.rs index 93328b7c8..1dc4f190c 100644 --- a/crates/bitwarden-api-api/src/models/update_two_factor_email_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_two_factor_email_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateTwoFactorEmailRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/update_two_factor_yubico_otp_request_model.rs b/crates/bitwarden-api-api/src/models/update_two_factor_yubico_otp_request_model.rs index eddf00bfc..19c5e37ba 100644 --- a/crates/bitwarden-api-api/src/models/update_two_factor_yubico_otp_request_model.rs +++ b/crates/bitwarden-api-api/src/models/update_two_factor_yubico_otp_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UpdateTwoFactorYubicoOtpRequestModel { #[serde(rename = "masterPasswordHash", skip_serializing_if = "Option::is_none")] pub master_password_hash: Option, diff --git a/crates/bitwarden-api-api/src/models/user.rs b/crates/bitwarden-api-api/src/models/user.rs index e0ac14ed7..470a2837f 100644 --- a/crates/bitwarden-api-api/src/models/user.rs +++ b/crates/bitwarden-api-api/src/models/user.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct User { #[serde(rename = "email", skip_serializing_if = "Option::is_none")] pub email: Option, diff --git a/crates/bitwarden-api-api/src/models/user_key_response_model.rs b/crates/bitwarden-api-api/src/models/user_key_response_model.rs index 66bba4d5c..bb70b620d 100644 --- a/crates/bitwarden-api-api/src/models/user_key_response_model.rs +++ b/crates/bitwarden-api-api/src/models/user_key_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UserKeyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-api/src/models/user_license.rs b/crates/bitwarden-api-api/src/models/user_license.rs index 3ec9ef334..508222fb7 100644 --- a/crates/bitwarden-api-api/src/models/user_license.rs +++ b/crates/bitwarden-api-api/src/models/user_license.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UserLicense { #[serde(rename = "licenseKey", skip_serializing_if = "Option::is_none")] pub license_key: Option, diff --git a/crates/bitwarden-api-api/src/models/user_project_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/user_project_access_policy_response_model.rs index f4a6d96ca..280657ec1 100644 --- a/crates/bitwarden-api-api/src/models/user_project_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/user_project_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UserProjectAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -33,6 +33,8 @@ pub struct UserProjectAccessPolicyResponseModel { pub user_id: Option, #[serde(rename = "grantedProjectId", skip_serializing_if = "Option::is_none")] pub granted_project_id: Option, + #[serde(rename = "currentUser", skip_serializing_if = "Option::is_none")] + pub current_user: Option, } impl UserProjectAccessPolicyResponseModel { @@ -48,6 +50,7 @@ impl UserProjectAccessPolicyResponseModel { organization_user_name: None, user_id: None, granted_project_id: None, + current_user: None, } } } diff --git a/crates/bitwarden-api-api/src/models/user_service_account_access_policy_response_model.rs b/crates/bitwarden-api-api/src/models/user_service_account_access_policy_response_model.rs index dada10c97..a69bb2a7c 100644 --- a/crates/bitwarden-api-api/src/models/user_service_account_access_policy_response_model.rs +++ b/crates/bitwarden-api-api/src/models/user_service_account_access_policy_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct UserServiceAccountAccessPolicyResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, @@ -36,6 +36,8 @@ pub struct UserServiceAccountAccessPolicyResponseModel { skip_serializing_if = "Option::is_none" )] pub granted_service_account_id: Option, + #[serde(rename = "currentUser", skip_serializing_if = "Option::is_none")] + pub current_user: Option, } impl UserServiceAccountAccessPolicyResponseModel { @@ -51,6 +53,7 @@ impl UserServiceAccountAccessPolicyResponseModel { organization_user_name: None, user_id: None, granted_service_account_id: None, + current_user: None, } } } diff --git a/crates/bitwarden-api-api/src/models/user_verification_requirement.rs b/crates/bitwarden-api-api/src/models/user_verification_requirement.rs new file mode 100644 index 000000000..647b1f9b9 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/user_verification_requirement.rs @@ -0,0 +1,36 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum UserVerificationRequirement { + #[serde(rename = "required")] + Required, + #[serde(rename = "preferred")] + Preferred, + #[serde(rename = "discouraged")] + Discouraged, +} + +impl ToString for UserVerificationRequirement { + fn to_string(&self) -> String { + match self { + Self::Required => String::from("required"), + Self::Preferred => String::from("preferred"), + Self::Discouraged => String::from("discouraged"), + } + } +} + +impl Default for UserVerificationRequirement { + fn default() -> UserVerificationRequirement { + Self::Required + } +} diff --git a/crates/bitwarden-api-api/src/models/verify_delete_recover_request_model.rs b/crates/bitwarden-api-api/src/models/verify_delete_recover_request_model.rs index ac4ec4902..0ad0e127c 100644 --- a/crates/bitwarden-api-api/src/models/verify_delete_recover_request_model.rs +++ b/crates/bitwarden-api-api/src/models/verify_delete_recover_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct VerifyDeleteRecoverRequestModel { #[serde(rename = "userId")] pub user_id: String, diff --git a/crates/bitwarden-api-api/src/models/verify_email_request_model.rs b/crates/bitwarden-api-api/src/models/verify_email_request_model.rs index ce66c6f2c..74304bcca 100644 --- a/crates/bitwarden-api-api/src/models/verify_email_request_model.rs +++ b/crates/bitwarden-api-api/src/models/verify_email_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct VerifyEmailRequestModel { #[serde(rename = "userId")] pub user_id: String, diff --git a/crates/bitwarden-api-api/src/models/verify_otp_request_model.rs b/crates/bitwarden-api-api/src/models/verify_otp_request_model.rs index db57d5f60..6c9be6992 100644 --- a/crates/bitwarden-api-api/src/models/verify_otp_request_model.rs +++ b/crates/bitwarden-api-api/src/models/verify_otp_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct VerifyOtpRequestModel { #[serde(rename = "otp")] pub otp: String, diff --git a/crates/bitwarden-api-api/src/models/web_authn_credential_create_options_response_model.rs b/crates/bitwarden-api-api/src/models/web_authn_credential_create_options_response_model.rs new file mode 100644 index 000000000..f13024a6f --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_credential_create_options_response_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnCredentialCreateOptionsResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "options", skip_serializing_if = "Option::is_none")] + pub options: Option>, + #[serde(rename = "token", skip_serializing_if = "Option::is_none")] + pub token: Option, +} + +impl WebAuthnCredentialCreateOptionsResponseModel { + pub fn new() -> WebAuthnCredentialCreateOptionsResponseModel { + WebAuthnCredentialCreateOptionsResponseModel { + object: None, + options: None, + token: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_credential_response_model.rs b/crates/bitwarden-api-api/src/models/web_authn_credential_response_model.rs new file mode 100644 index 000000000..852b3a527 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_credential_response_model.rs @@ -0,0 +1,32 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnCredentialResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "name", skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(rename = "prfStatus", skip_serializing_if = "Option::is_none")] + pub prf_status: Option, +} + +impl WebAuthnCredentialResponseModel { + pub fn new() -> WebAuthnCredentialResponseModel { + WebAuthnCredentialResponseModel { + object: None, + id: None, + name: None, + prf_status: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_credential_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/web_authn_credential_response_model_list_response_model.rs new file mode 100644 index 000000000..b0072c62f --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_credential_response_model_list_response_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnCredentialResponseModelListResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "data", skip_serializing_if = "Option::is_none")] + pub data: Option>, + #[serde(rename = "continuationToken", skip_serializing_if = "Option::is_none")] + pub continuation_token: Option, +} + +impl WebAuthnCredentialResponseModelListResponseModel { + pub fn new() -> WebAuthnCredentialResponseModelListResponseModel { + WebAuthnCredentialResponseModelListResponseModel { + object: None, + data: None, + continuation_token: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_login_assertion_options_response_model.rs b/crates/bitwarden-api-api/src/models/web_authn_login_assertion_options_response_model.rs new file mode 100644 index 000000000..27ed6afc4 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_login_assertion_options_response_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnLoginAssertionOptionsResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "options", skip_serializing_if = "Option::is_none")] + pub options: Option>, + #[serde(rename = "token", skip_serializing_if = "Option::is_none")] + pub token: Option, +} + +impl WebAuthnLoginAssertionOptionsResponseModel { + pub fn new() -> WebAuthnLoginAssertionOptionsResponseModel { + WebAuthnLoginAssertionOptionsResponseModel { + object: None, + options: None, + token: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_login_credential_create_request_model.rs b/crates/bitwarden-api-api/src/models/web_authn_login_credential_create_request_model.rs new file mode 100644 index 000000000..f5565655a --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_login_credential_create_request_model.rs @@ -0,0 +1,49 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnLoginCredentialCreateRequestModel { + #[serde(rename = "deviceResponse")] + pub device_response: Box, + #[serde(rename = "name")] + pub name: String, + #[serde(rename = "token")] + pub token: String, + #[serde(rename = "supportsPrf")] + pub supports_prf: bool, + #[serde(rename = "encryptedUserKey", skip_serializing_if = "Option::is_none")] + pub encrypted_user_key: Option, + #[serde(rename = "encryptedPublicKey", skip_serializing_if = "Option::is_none")] + pub encrypted_public_key: Option, + #[serde( + rename = "encryptedPrivateKey", + skip_serializing_if = "Option::is_none" + )] + pub encrypted_private_key: Option, +} + +impl WebAuthnLoginCredentialCreateRequestModel { + pub fn new( + device_response: crate::models::AuthenticatorAttestationRawResponse, + name: String, + token: String, + supports_prf: bool, + ) -> WebAuthnLoginCredentialCreateRequestModel { + WebAuthnLoginCredentialCreateRequestModel { + device_response: Box::new(device_response), + name, + token, + supports_prf, + encrypted_user_key: None, + encrypted_public_key: None, + encrypted_private_key: None, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_login_credential_update_request_model.rs b/crates/bitwarden-api-api/src/models/web_authn_login_credential_update_request_model.rs new file mode 100644 index 000000000..ce12d0c43 --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_login_credential_update_request_model.rs @@ -0,0 +1,41 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnLoginCredentialUpdateRequestModel { + #[serde(rename = "deviceResponse")] + pub device_response: Box, + #[serde(rename = "token")] + pub token: String, + #[serde(rename = "encryptedUserKey")] + pub encrypted_user_key: String, + #[serde(rename = "encryptedPublicKey")] + pub encrypted_public_key: String, + #[serde(rename = "encryptedPrivateKey")] + pub encrypted_private_key: String, +} + +impl WebAuthnLoginCredentialUpdateRequestModel { + pub fn new( + device_response: crate::models::AuthenticatorAssertionRawResponse, + token: String, + encrypted_user_key: String, + encrypted_public_key: String, + encrypted_private_key: String, + ) -> WebAuthnLoginCredentialUpdateRequestModel { + WebAuthnLoginCredentialUpdateRequestModel { + device_response: Box::new(device_response), + token, + encrypted_user_key, + encrypted_public_key, + encrypted_private_key, + } + } +} diff --git a/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs b/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs new file mode 100644 index 000000000..eb58bfdcc --- /dev/null +++ b/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs @@ -0,0 +1,36 @@ +/* + * Bitwarden Internal API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: latest + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[repr(i64)] +#[derive( + Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, +)] +pub enum WebAuthnPrfStatus { + Variant0 = 0, + Variant1 = 1, + Variant2 = 2, +} + +impl ToString for WebAuthnPrfStatus { + fn to_string(&self) -> String { + match self { + Self::Variant0 => String::from("0"), + Self::Variant1 => String::from("1"), + Self::Variant2 => String::from("2"), + } + } +} + +impl Default for WebAuthnPrfStatus { + fn default() -> WebAuthnPrfStatus { + Self::Variant0 + } +} diff --git a/crates/bitwarden-api-identity/.openapi-generator/FILES b/crates/bitwarden-api-identity/.openapi-generator/FILES index af978071e..968fd8fe4 100644 --- a/crates/bitwarden-api-identity/.openapi-generator/FILES +++ b/crates/bitwarden-api-identity/.openapi-generator/FILES @@ -7,10 +7,17 @@ src/apis/info_api.rs src/apis/mod.rs src/apis/sso_api.rs src/lib.rs +src/models/assertion_options.rs +src/models/authentication_extensions_client_inputs.rs +src/models/authenticator_transport.rs src/models/kdf_type.rs src/models/keys_request_model.rs src/models/mod.rs src/models/prelogin_request_model.rs src/models/prelogin_response_model.rs +src/models/public_key_credential_descriptor.rs +src/models/public_key_credential_type.rs src/models/register_request_model.rs src/models/register_response_model.rs +src/models/user_verification_requirement.rs +src/models/web_authn_login_assertion_options_response_model.rs diff --git a/crates/bitwarden-api-identity/.openapi-generator/VERSION b/crates/bitwarden-api-identity/.openapi-generator/VERSION index 4be2c727a..4b49d9bb6 100644 --- a/crates/bitwarden-api-identity/.openapi-generator/VERSION +++ b/crates/bitwarden-api-identity/.openapi-generator/VERSION @@ -1 +1 @@ -6.5.0 \ No newline at end of file +7.2.0 \ No newline at end of file diff --git a/crates/bitwarden-api-identity/README.md b/crates/bitwarden-api-identity/README.md index 8288a18e5..bb190aaad 100644 --- a/crates/bitwarden-api-identity/README.md +++ b/crates/bitwarden-api-identity/README.md @@ -26,30 +26,38 @@ bitwarden-api-identity = { path = "./bitwarden-api-identity" } All URIs are relative to _http://localhost_ -| Class | Method | HTTP request | Description | -| ------------- | ----------------------------------------------------------------------------------- | ---------------------------------- | ----------- | -| _AccountsApi_ | [**accounts_prelogin_post**](docs/AccountsApi.md#accounts_prelogin_post) | **POST** /accounts/prelogin | -| _AccountsApi_ | [**accounts_register_post**](docs/AccountsApi.md#accounts_register_post) | **POST** /accounts/register | -| _InfoApi_ | [**alive_get**](docs/InfoApi.md#alive_get) | **GET** /alive | -| _InfoApi_ | [**now_get**](docs/InfoApi.md#now_get) | **GET** /now | -| _InfoApi_ | [**version_get**](docs/InfoApi.md#version_get) | **GET** /version | -| _SsoApi_ | [**account_external_callback_get**](docs/SsoApi.md#account_external_callback_get) | **GET** /account/ExternalCallback | -| _SsoApi_ | [**account_external_challenge_get**](docs/SsoApi.md#account_external_challenge_get) | **GET** /account/ExternalChallenge | -| _SsoApi_ | [**account_login_get**](docs/SsoApi.md#account_login_get) | **GET** /account/Login | -| _SsoApi_ | [**account_pre_validate_get**](docs/SsoApi.md#account_pre_validate_get) | **GET** /account/PreValidate | -| _SsoApi_ | [**sso_external_callback_get**](docs/SsoApi.md#sso_external_callback_get) | **GET** /sso/ExternalCallback | -| _SsoApi_ | [**sso_external_challenge_get**](docs/SsoApi.md#sso_external_challenge_get) | **GET** /sso/ExternalChallenge | -| _SsoApi_ | [**sso_login_get**](docs/SsoApi.md#sso_login_get) | **GET** /sso/Login | -| _SsoApi_ | [**sso_pre_validate_get**](docs/SsoApi.md#sso_pre_validate_get) | **GET** /sso/PreValidate | +| Class | Method | HTTP request | Description | +| ------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------- | +| _AccountsApi_ | [**accounts_prelogin_post**](docs/AccountsApi.md#accounts_prelogin_post) | **POST** /accounts/prelogin | +| _AccountsApi_ | [**accounts_register_post**](docs/AccountsApi.md#accounts_register_post) | **POST** /accounts/register | +| _AccountsApi_ | [**accounts_webauthn_assertion_options_get**](docs/AccountsApi.md#accounts_webauthn_assertion_options_get) | **GET** /accounts/webauthn/assertion-options | +| _InfoApi_ | [**alive_get**](docs/InfoApi.md#alive_get) | **GET** /alive | +| _InfoApi_ | [**now_get**](docs/InfoApi.md#now_get) | **GET** /now | +| _InfoApi_ | [**version_get**](docs/InfoApi.md#version_get) | **GET** /version | +| _SsoApi_ | [**account_external_callback_get**](docs/SsoApi.md#account_external_callback_get) | **GET** /account/ExternalCallback | +| _SsoApi_ | [**account_external_challenge_get**](docs/SsoApi.md#account_external_challenge_get) | **GET** /account/ExternalChallenge | +| _SsoApi_ | [**account_login_get**](docs/SsoApi.md#account_login_get) | **GET** /account/Login | +| _SsoApi_ | [**account_pre_validate_get**](docs/SsoApi.md#account_pre_validate_get) | **GET** /account/PreValidate | +| _SsoApi_ | [**sso_external_callback_get**](docs/SsoApi.md#sso_external_callback_get) | **GET** /sso/ExternalCallback | +| _SsoApi_ | [**sso_external_challenge_get**](docs/SsoApi.md#sso_external_challenge_get) | **GET** /sso/ExternalChallenge | +| _SsoApi_ | [**sso_login_get**](docs/SsoApi.md#sso_login_get) | **GET** /sso/Login | +| _SsoApi_ | [**sso_pre_validate_get**](docs/SsoApi.md#sso_pre_validate_get) | **GET** /sso/PreValidate | ## Documentation For Models +- [AssertionOptions](docs/AssertionOptions.md) +- [AuthenticationExtensionsClientInputs](docs/AuthenticationExtensionsClientInputs.md) +- [AuthenticatorTransport](docs/AuthenticatorTransport.md) - [KdfType](docs/KdfType.md) - [KeysRequestModel](docs/KeysRequestModel.md) - [PreloginRequestModel](docs/PreloginRequestModel.md) - [PreloginResponseModel](docs/PreloginResponseModel.md) +- [PublicKeyCredentialDescriptor](docs/PublicKeyCredentialDescriptor.md) +- [PublicKeyCredentialType](docs/PublicKeyCredentialType.md) - [RegisterRequestModel](docs/RegisterRequestModel.md) - [RegisterResponseModel](docs/RegisterResponseModel.md) +- [UserVerificationRequirement](docs/UserVerificationRequirement.md) +- [WebAuthnLoginAssertionOptionsResponseModel](docs/WebAuthnLoginAssertionOptionsResponseModel.md) To get access to the crate's generated documentation, use: diff --git a/crates/bitwarden-api-identity/src/apis/accounts_api.rs b/crates/bitwarden-api-identity/src/apis/accounts_api.rs index efffdae3d..c7b0bd1fd 100644 --- a/crates/bitwarden-api-identity/src/apis/accounts_api.rs +++ b/crates/bitwarden-api-identity/src/apis/accounts_api.rs @@ -27,6 +27,13 @@ pub enum AccountsRegisterPostError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`accounts_webauthn_assertion_options_get`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum AccountsWebauthnAssertionOptionsGetError { + UnknownValue(serde_json::Value), +} + pub async fn accounts_prelogin_post( configuration: &configuration::Configuration, prelogin_request_model: Option, @@ -102,3 +109,45 @@ pub async fn accounts_register_post( Err(Error::ResponseError(local_var_error)) } } + +pub async fn accounts_webauthn_assertion_options_get( + configuration: &configuration::Configuration, +) -> Result< + crate::models::WebAuthnLoginAssertionOptionsResponseModel, + Error, +> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/accounts/webauthn/assertion-options", + local_var_configuration.base_path + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} diff --git a/crates/bitwarden-api-identity/src/apis/configuration.rs b/crates/bitwarden-api-identity/src/apis/configuration.rs index 46cf9212e..6ed785dc7 100644 --- a/crates/bitwarden-api-identity/src/apis/configuration.rs +++ b/crates/bitwarden-api-identity/src/apis/configuration.rs @@ -8,8 +8,6 @@ * Generated by: https://openapi-generator.tech */ -use reqwest; - #[derive(Debug, Clone)] pub struct Configuration { pub base_path: String, diff --git a/crates/bitwarden-api-identity/src/apis/mod.rs b/crates/bitwarden-api-identity/src/apis/mod.rs index f50e7d44a..907fffa89 100644 --- a/crates/bitwarden-api-identity/src/apis/mod.rs +++ b/crates/bitwarden-api-identity/src/apis/mod.rs @@ -60,6 +60,37 @@ pub fn urlencode>(s: T) -> String { ::url::form_urlencoded::byte_serialize(s.as_ref().as_bytes()).collect() } +pub fn parse_deep_object(prefix: &str, value: &serde_json::Value) -> Vec<(String, String)> { + if let serde_json::Value::Object(object) = value { + let mut params = vec![]; + + for (key, value) in object { + match value { + serde_json::Value::Object(_) => params.append(&mut parse_deep_object( + &format!("{}[{}]", prefix, key), + value, + )), + serde_json::Value::Array(array) => { + for (i, value) in array.iter().enumerate() { + params.append(&mut parse_deep_object( + &format!("{}[{}][{}]", prefix, key, i), + value, + )); + } + } + serde_json::Value::String(s) => { + params.push((format!("{}[{}]", prefix, key), s.clone())) + } + _ => params.push((format!("{}[{}]", prefix, key), value.to_string())), + } + } + + return params; + } + + unimplemented!("Only objects are supported with style=deepObject") +} + pub mod accounts_api; pub mod info_api; pub mod sso_api; diff --git a/crates/bitwarden-api-identity/src/models/assertion_options.rs b/crates/bitwarden-api-identity/src/models/assertion_options.rs new file mode 100644 index 000000000..f69580f77 --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/assertion_options.rs @@ -0,0 +1,44 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AssertionOptions { + #[serde(rename = "status", skip_serializing_if = "Option::is_none")] + pub status: Option, + #[serde(rename = "errorMessage", skip_serializing_if = "Option::is_none")] + pub error_message: Option, + #[serde(rename = "challenge", skip_serializing_if = "Option::is_none")] + pub challenge: Option, + #[serde(rename = "timeout", skip_serializing_if = "Option::is_none")] + pub timeout: Option, + #[serde(rename = "rpId", skip_serializing_if = "Option::is_none")] + pub rp_id: Option, + #[serde(rename = "allowCredentials", skip_serializing_if = "Option::is_none")] + pub allow_credentials: Option>, + #[serde(rename = "userVerification", skip_serializing_if = "Option::is_none")] + pub user_verification: Option, + #[serde(rename = "extensions", skip_serializing_if = "Option::is_none")] + pub extensions: Option>, +} + +impl AssertionOptions { + pub fn new() -> AssertionOptions { + AssertionOptions { + status: None, + error_message: None, + challenge: None, + timeout: None, + rp_id: None, + allow_credentials: None, + user_verification: None, + extensions: None, + } + } +} diff --git a/crates/bitwarden-api-identity/src/models/authentication_extensions_client_inputs.rs b/crates/bitwarden-api-identity/src/models/authentication_extensions_client_inputs.rs new file mode 100644 index 000000000..2677278cc --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/authentication_extensions_client_inputs.rs @@ -0,0 +1,35 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct AuthenticationExtensionsClientInputs { + #[serde(rename = "example.extension", skip_serializing_if = "Option::is_none")] + pub example_period_extension: Option, + #[serde(rename = "appid", skip_serializing_if = "Option::is_none")] + pub appid: Option, + #[serde(rename = "authnSel", skip_serializing_if = "Option::is_none")] + pub authn_sel: Option>, + #[serde(rename = "exts", skip_serializing_if = "Option::is_none")] + pub exts: Option, + #[serde(rename = "uvm", skip_serializing_if = "Option::is_none")] + pub uvm: Option, +} + +impl AuthenticationExtensionsClientInputs { + pub fn new() -> AuthenticationExtensionsClientInputs { + AuthenticationExtensionsClientInputs { + example_period_extension: None, + appid: None, + authn_sel: None, + exts: None, + uvm: None, + } + } +} diff --git a/crates/bitwarden-api-identity/src/models/authenticator_transport.rs b/crates/bitwarden-api-identity/src/models/authenticator_transport.rs new file mode 100644 index 000000000..bd3881305 --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/authenticator_transport.rs @@ -0,0 +1,39 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum AuthenticatorTransport { + #[serde(rename = "usb")] + Usb, + #[serde(rename = "nfc")] + Nfc, + #[serde(rename = "ble")] + Ble, + #[serde(rename = "internal")] + Internal, +} + +impl ToString for AuthenticatorTransport { + fn to_string(&self) -> String { + match self { + Self::Usb => String::from("usb"), + Self::Nfc => String::from("nfc"), + Self::Ble => String::from("ble"), + Self::Internal => String::from("internal"), + } + } +} + +impl Default for AuthenticatorTransport { + fn default() -> AuthenticatorTransport { + Self::Usb + } +} diff --git a/crates/bitwarden-api-identity/src/models/keys_request_model.rs b/crates/bitwarden-api-identity/src/models/keys_request_model.rs index ebbb28145..579c08aed 100644 --- a/crates/bitwarden-api-identity/src/models/keys_request_model.rs +++ b/crates/bitwarden-api-identity/src/models/keys_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct KeysRequestModel { #[serde(rename = "publicKey", skip_serializing_if = "Option::is_none")] pub public_key: Option, diff --git a/crates/bitwarden-api-identity/src/models/mod.rs b/crates/bitwarden-api-identity/src/models/mod.rs index 0464a3ea9..715e29686 100644 --- a/crates/bitwarden-api-identity/src/models/mod.rs +++ b/crates/bitwarden-api-identity/src/models/mod.rs @@ -1,3 +1,9 @@ +pub mod assertion_options; +pub use self::assertion_options::AssertionOptions; +pub mod authentication_extensions_client_inputs; +pub use self::authentication_extensions_client_inputs::AuthenticationExtensionsClientInputs; +pub mod authenticator_transport; +pub use self::authenticator_transport::AuthenticatorTransport; pub mod kdf_type; pub use self::kdf_type::KdfType; pub mod keys_request_model; @@ -6,7 +12,15 @@ pub mod prelogin_request_model; pub use self::prelogin_request_model::PreloginRequestModel; pub mod prelogin_response_model; pub use self::prelogin_response_model::PreloginResponseModel; +pub mod public_key_credential_descriptor; +pub use self::public_key_credential_descriptor::PublicKeyCredentialDescriptor; +pub mod public_key_credential_type; +pub use self::public_key_credential_type::PublicKeyCredentialType; pub mod register_request_model; pub use self::register_request_model::RegisterRequestModel; pub mod register_response_model; pub use self::register_response_model::RegisterResponseModel; +pub mod user_verification_requirement; +pub use self::user_verification_requirement::UserVerificationRequirement; +pub mod web_authn_login_assertion_options_response_model; +pub use self::web_authn_login_assertion_options_response_model::WebAuthnLoginAssertionOptionsResponseModel; diff --git a/crates/bitwarden-api-identity/src/models/prelogin_request_model.rs b/crates/bitwarden-api-identity/src/models/prelogin_request_model.rs index e56b1beb1..eb845142b 100644 --- a/crates/bitwarden-api-identity/src/models/prelogin_request_model.rs +++ b/crates/bitwarden-api-identity/src/models/prelogin_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PreloginRequestModel { #[serde(rename = "email")] pub email: String, diff --git a/crates/bitwarden-api-identity/src/models/prelogin_response_model.rs b/crates/bitwarden-api-identity/src/models/prelogin_response_model.rs index 583577ea6..a8935137d 100644 --- a/crates/bitwarden-api-identity/src/models/prelogin_response_model.rs +++ b/crates/bitwarden-api-identity/src/models/prelogin_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct PreloginResponseModel { #[serde(rename = "kdf", skip_serializing_if = "Option::is_none")] pub kdf: Option, diff --git a/crates/bitwarden-api-identity/src/models/public_key_credential_descriptor.rs b/crates/bitwarden-api-identity/src/models/public_key_credential_descriptor.rs new file mode 100644 index 000000000..67a4750ca --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/public_key_credential_descriptor.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct PublicKeyCredentialDescriptor { + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub r#type: Option, + #[serde(rename = "id", skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(rename = "transports", skip_serializing_if = "Option::is_none")] + pub transports: Option>, +} + +impl PublicKeyCredentialDescriptor { + pub fn new() -> PublicKeyCredentialDescriptor { + PublicKeyCredentialDescriptor { + r#type: None, + id: None, + transports: None, + } + } +} diff --git a/crates/bitwarden-api-identity/src/models/public_key_credential_type.rs b/crates/bitwarden-api-identity/src/models/public_key_credential_type.rs new file mode 100644 index 000000000..85027f09e --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/public_key_credential_type.rs @@ -0,0 +1,30 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum PublicKeyCredentialType { + #[serde(rename = "public-key")] + PublicKey, +} + +impl ToString for PublicKeyCredentialType { + fn to_string(&self) -> String { + match self { + Self::PublicKey => String::from("public-key"), + } + } +} + +impl Default for PublicKeyCredentialType { + fn default() -> PublicKeyCredentialType { + Self::PublicKey + } +} diff --git a/crates/bitwarden-api-identity/src/models/register_request_model.rs b/crates/bitwarden-api-identity/src/models/register_request_model.rs index 884702a6d..6034235a8 100644 --- a/crates/bitwarden-api-identity/src/models/register_request_model.rs +++ b/crates/bitwarden-api-identity/src/models/register_request_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RegisterRequestModel { #[serde(rename = "name", skip_serializing_if = "Option::is_none")] pub name: Option, diff --git a/crates/bitwarden-api-identity/src/models/register_response_model.rs b/crates/bitwarden-api-identity/src/models/register_response_model.rs index da2b4a79a..d2dbf37be 100644 --- a/crates/bitwarden-api-identity/src/models/register_response_model.rs +++ b/crates/bitwarden-api-identity/src/models/register_response_model.rs @@ -8,7 +8,7 @@ * Generated by: https://openapi-generator.tech */ -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RegisterResponseModel { #[serde(rename = "object", skip_serializing_if = "Option::is_none")] pub object: Option, diff --git a/crates/bitwarden-api-identity/src/models/user_verification_requirement.rs b/crates/bitwarden-api-identity/src/models/user_verification_requirement.rs new file mode 100644 index 000000000..ca0ddadb0 --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/user_verification_requirement.rs @@ -0,0 +1,36 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +/// +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)] +pub enum UserVerificationRequirement { + #[serde(rename = "required")] + Required, + #[serde(rename = "preferred")] + Preferred, + #[serde(rename = "discouraged")] + Discouraged, +} + +impl ToString for UserVerificationRequirement { + fn to_string(&self) -> String { + match self { + Self::Required => String::from("required"), + Self::Preferred => String::from("preferred"), + Self::Discouraged => String::from("discouraged"), + } + } +} + +impl Default for UserVerificationRequirement { + fn default() -> UserVerificationRequirement { + Self::Required + } +} diff --git a/crates/bitwarden-api-identity/src/models/web_authn_login_assertion_options_response_model.rs b/crates/bitwarden-api-identity/src/models/web_authn_login_assertion_options_response_model.rs new file mode 100644 index 000000000..199b12111 --- /dev/null +++ b/crates/bitwarden-api-identity/src/models/web_authn_login_assertion_options_response_model.rs @@ -0,0 +1,29 @@ +/* + * Bitwarden Identity + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: v1 + * + * Generated by: https://openapi-generator.tech + */ + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct WebAuthnLoginAssertionOptionsResponseModel { + #[serde(rename = "object", skip_serializing_if = "Option::is_none")] + pub object: Option, + #[serde(rename = "options", skip_serializing_if = "Option::is_none")] + pub options: Option>, + #[serde(rename = "token", skip_serializing_if = "Option::is_none")] + pub token: Option, +} + +impl WebAuthnLoginAssertionOptionsResponseModel { + pub fn new() -> WebAuthnLoginAssertionOptionsResponseModel { + WebAuthnLoginAssertionOptionsResponseModel { + object: None, + options: None, + token: None, + } + } +} From aa30b6593e01831bc7665878a50de2161d9c4efd Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 8 Feb 2024 13:18:06 +0100 Subject: [PATCH 270/378] [PM-3438] Encrypted export (#588) Implement encrypted export --- Cargo.lock | 3 + .../bitwarden-crypto/src/keys/master_key.rs | 92 +------ crates/bitwarden-crypto/src/keys/mod.rs | 4 +- crates/bitwarden-crypto/src/keys/pin_key.rs | 39 +++ crates/bitwarden-crypto/src/keys/utils.rs | 85 ++++++ crates/bitwarden-exporters/Cargo.toml | 4 +- .../bitwarden-exporters/src/encrypted_json.rs | 246 ++++++++++++++++++ crates/bitwarden-exporters/src/lib.rs | 11 +- crates/bitwarden/src/tool/exporters/mod.rs | 69 +++-- 9 files changed, 447 insertions(+), 106 deletions(-) create mode 100644 crates/bitwarden-crypto/src/keys/pin_key.rs create mode 100644 crates/bitwarden-crypto/src/keys/utils.rs create mode 100644 crates/bitwarden-exporters/src/encrypted_json.rs diff --git a/Cargo.lock b/Cargo.lock index c4b8d76d1..44aaee484 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -456,6 +456,8 @@ dependencies = [ name = "bitwarden-exporters" version = "0.1.0" dependencies = [ + "base64 0.21.7", + "bitwarden-crypto", "chrono", "csv", "serde", @@ -3813,6 +3815,7 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ + "getrandom 0.2.12", "serde", ] diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 0a435ed88..aff403c59 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -1,16 +1,11 @@ -use std::{num::NonZeroU32, pin::Pin}; +use std::num::NonZeroU32; -use aes::cipher::typenum::U32; use base64::{engine::general_purpose::STANDARD, Engine}; -use generic_array::GenericArray; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use sha2::Digest; -use crate::{ - util::{self, hkdf_expand}, - EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey, -}; +use super::utils::{derive_kdf_key, stretch_kdf_key}; +use crate::{util, EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey}; #[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -45,7 +40,7 @@ impl MasterKey { /// Derives a users master key from their password, email and KDF. pub fn derive(password: &[u8], email: &[u8], kdf: &Kdf) -> Result { - derive_key(password, email, kdf).map(Self) + derive_kdf_key(password, email, kdf).map(Self) } /// Derive the master key hash, used for local and remote password validation. @@ -62,14 +57,14 @@ impl MasterKey { /// Decrypt the users user key pub fn decrypt_user_key(&self, user_key: EncString) -> Result { - let stretched_key = stretch_master_key(self)?; + let stretched_key = stretch_kdf_key(&self.0)?; let mut dec: Vec = user_key.decrypt_with_key(&stretched_key)?; SymmetricCryptoKey::try_from(dec.as_mut_slice()) } pub fn encrypt_user_key(&self, user_key: &SymmetricCryptoKey) -> Result { - let stretched_key = stretch_master_key(self)?; + let stretched_key = stretch_kdf_key(&self.0)?; EncString::encrypt_aes256_hmac( user_key.to_vec().as_slice(), @@ -89,55 +84,13 @@ fn make_user_key( Ok((UserKey::new(user_key), protected)) } -/// Derive a generic key from a secret and salt using the provided KDF. -fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { - let mut hash = match kdf { - Kdf::PBKDF2 { iterations } => crate::util::pbkdf2(secret, salt, iterations.get()), - - Kdf::Argon2id { - iterations, - memory, - parallelism, - } => { - use argon2::*; - - let argon = Argon2::new( - Algorithm::Argon2id, - Version::V0x13, - Params::new( - memory.get() * 1024, // Convert MiB to KiB - iterations.get(), - parallelism.get(), - Some(32), - ) - .unwrap(), - ); - - let salt_sha = sha2::Sha256::new().chain_update(salt).finalize(); - - let mut hash = [0u8; 32]; - argon - .hash_password_into(secret, &salt_sha, &mut hash) - .unwrap(); - hash - } - }; - SymmetricCryptoKey::try_from(hash.as_mut_slice()) -} - -fn stretch_master_key(master_key: &MasterKey) -> Result { - let key: Pin>> = hkdf_expand(&master_key.0.key, Some("enc"))?; - let mac_key: Pin>> = hkdf_expand(&master_key.0.key, Some("mac"))?; - Ok(SymmetricCryptoKey::new(key, Some(mac_key))) -} - #[cfg(test)] mod tests { use std::num::NonZeroU32; use rand::SeedableRng; - use super::{make_user_key, stretch_master_key, HashPurpose, Kdf, MasterKey}; + use super::{make_user_key, HashPurpose, Kdf, MasterKey}; use crate::{keys::symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}; #[test] @@ -184,37 +137,6 @@ mod tests { assert_eq!(None, master_key.0.mac_key); } - #[test] - fn test_stretch_master_key() { - let master_key = MasterKey(SymmetricCryptoKey::new( - Box::pin( - [ - 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, - 167, 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, - ] - .into(), - ), - None, - )); - - let stretched = stretch_master_key(&master_key).unwrap(); - - assert_eq!( - [ - 111, 31, 178, 45, 238, 152, 37, 114, 143, 215, 124, 83, 135, 173, 195, 23, 142, - 134, 120, 249, 61, 132, 163, 182, 113, 197, 189, 204, 188, 21, 237, 96 - ], - stretched.key.as_slice() - ); - assert_eq!( - [ - 221, 127, 206, 234, 101, 27, 202, 38, 86, 52, 34, 28, 78, 28, 185, 16, 48, 61, 127, - 166, 209, 247, 194, 87, 232, 26, 48, 85, 193, 249, 179, 155 - ], - stretched.mac_key.as_ref().unwrap().as_slice() - ); - } - #[test] fn test_password_hash_pbkdf2() { let password = "asdfasdf".as_bytes(); diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 285e58b55..5bfd32b8b 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -12,8 +12,10 @@ mod asymmetric_crypto_key; pub use asymmetric_crypto_key::{ AsymmetricCryptoKey, AsymmetricEncryptable, AsymmetricPublicCryptoKey, }; - mod user_key; pub use user_key::UserKey; mod device_key; pub use device_key::{DeviceKey, TrustDeviceResponse}; +mod pin_key; +pub use pin_key::PinKey; +mod utils; diff --git a/crates/bitwarden-crypto/src/keys/pin_key.rs b/crates/bitwarden-crypto/src/keys/pin_key.rs new file mode 100644 index 000000000..475b7ffd9 --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/pin_key.rs @@ -0,0 +1,39 @@ +use crate::{ + keys::{ + key_encryptable::CryptoKey, + utils::{derive_kdf_key, stretch_kdf_key}, + }, + EncString, Kdf, KeyEncryptable, Result, SymmetricCryptoKey, +}; + +/// Pin Key. +/// +/// Derived from a specific password, used for pin encryption and exports. +pub struct PinKey(SymmetricCryptoKey); + +impl PinKey { + pub fn new(key: SymmetricCryptoKey) -> Self { + Self(key) + } + + /// Derives a users pin key from their password, email and KDF. + pub fn derive(password: &[u8], salt: &[u8], kdf: &Kdf) -> Result { + derive_kdf_key(password, salt, kdf).map(Self) + } +} + +impl CryptoKey for PinKey {} + +impl KeyEncryptable for &[u8] { + fn encrypt_with_key(self, key: &PinKey) -> Result { + let stretched_key = stretch_kdf_key(&key.0)?; + + self.encrypt_with_key(&stretched_key) + } +} + +impl KeyEncryptable for String { + fn encrypt_with_key(self, key: &PinKey) -> Result { + self.as_bytes().encrypt_with_key(key) + } +} diff --git a/crates/bitwarden-crypto/src/keys/utils.rs b/crates/bitwarden-crypto/src/keys/utils.rs new file mode 100644 index 000000000..d83e212d0 --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/utils.rs @@ -0,0 +1,85 @@ +use std::pin::Pin; + +use generic_array::{typenum::U32, GenericArray}; +use sha2::Digest; + +use crate::{util::hkdf_expand, Kdf, Result, SymmetricCryptoKey}; + +/// Derive a generic key from a secret and salt using the provided KDF. +pub(super) fn derive_kdf_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result { + let mut hash = match kdf { + Kdf::PBKDF2 { iterations } => crate::util::pbkdf2(secret, salt, iterations.get()), + + Kdf::Argon2id { + iterations, + memory, + parallelism, + } => { + use argon2::*; + + let argon = Argon2::new( + Algorithm::Argon2id, + Version::V0x13, + Params::new( + memory.get() * 1024, // Convert MiB to KiB + iterations.get(), + parallelism.get(), + Some(32), + ) + .unwrap(), + ); + + let salt_sha = sha2::Sha256::new().chain_update(salt).finalize(); + + let mut hash = [0u8; 32]; + argon + .hash_password_into(secret, &salt_sha, &mut hash) + .unwrap(); + hash + } + }; + SymmetricCryptoKey::try_from(hash.as_mut_slice()) +} + +pub(super) fn stretch_kdf_key(k: &SymmetricCryptoKey) -> Result { + let key: Pin>> = hkdf_expand(&k.key, Some("enc"))?; + let mac_key: Pin>> = hkdf_expand(&k.key, Some("mac"))?; + + Ok(SymmetricCryptoKey::new(key, Some(mac_key))) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_stretch_kdf_key() { + let key = SymmetricCryptoKey::new( + Box::pin( + [ + 31, 79, 104, 226, 150, 71, 177, 90, 194, 80, 172, 209, 17, 129, 132, 81, 138, + 167, 69, 167, 254, 149, 2, 27, 39, 197, 64, 42, 22, 195, 86, 75, + ] + .into(), + ), + None, + ); + + let stretched = stretch_kdf_key(&key).unwrap(); + + assert_eq!( + [ + 111, 31, 178, 45, 238, 152, 37, 114, 143, 215, 124, 83, 135, 173, 195, 23, 142, + 134, 120, 249, 61, 132, 163, 182, 113, 197, 189, 204, 188, 21, 237, 96 + ], + stretched.key.as_slice() + ); + assert_eq!( + [ + 221, 127, 206, 234, 101, 27, 202, 38, 86, 52, 34, 28, 78, 28, 185, 16, 48, 61, 127, + 166, 209, 247, 194, 87, 232, 26, 48, 85, 193, 249, 179, 155 + ], + stretched.mac_key.as_ref().unwrap().as_slice() + ); + } +} diff --git a/crates/bitwarden-exporters/Cargo.toml b/crates/bitwarden-exporters/Cargo.toml index 0008fbb49..40316437f 100644 --- a/crates/bitwarden-exporters/Cargo.toml +++ b/crates/bitwarden-exporters/Cargo.toml @@ -14,6 +14,8 @@ rust-version = "1.57" exclude = ["/resources"] [dependencies] +base64 = ">=0.21.2, <0.22" +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", @@ -23,4 +25,4 @@ csv = "1.3.0" serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" thiserror = ">=1.0.40, <2.0" -uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } +uuid = { version = ">=1.3.3, <2.0", features = ["serde", "v4"] } diff --git a/crates/bitwarden-exporters/src/encrypted_json.rs b/crates/bitwarden-exporters/src/encrypted_json.rs new file mode 100644 index 000000000..1bbfd2660 --- /dev/null +++ b/crates/bitwarden-exporters/src/encrypted_json.rs @@ -0,0 +1,246 @@ +use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::{generate_random_bytes, Kdf, KeyEncryptable, PinKey}; +use serde::Serialize; +use thiserror::Error; +use uuid::Uuid; + +use crate::{ + json::{self, export_json}, + Cipher, Folder, +}; + +#[derive(Error, Debug)] +pub enum EncryptedJsonError { + #[error(transparent)] + JsonExport(#[from] json::JsonError), + + #[error("JSON error: {0}")] + Serde(#[from] serde_json::Error), + + #[error("Cryptography error, {0}")] + Crypto(#[from] bitwarden_crypto::CryptoError), +} + +pub(crate) fn export_encrypted_json( + folders: Vec, + ciphers: Vec, + password: String, + kdf: Kdf, +) -> Result { + let decrypted_export = export_json(folders, ciphers)?; + + let (kdf_type, kdf_iterations, kdf_memory, kdf_parallelism) = match kdf { + Kdf::PBKDF2 { iterations } => (0, iterations.get(), None, None), + Kdf::Argon2id { + iterations, + memory, + parallelism, + } => ( + 1, + iterations.get(), + Some(memory.get()), + Some(parallelism.get()), + ), + }; + + let salt: [u8; 16] = generate_random_bytes(); + let salt = STANDARD.encode(salt); + let key = PinKey::derive(password.as_bytes(), salt.as_bytes(), &kdf)?; + + let enc_key_validation = Uuid::new_v4().to_string(); + + let encrypted_export = EncryptedJsonExport { + encrypted: true, + password_protected: true, + salt, + kdf_type, + kdf_iterations, + kdf_memory, + kdf_parallelism, + enc_key_validation: enc_key_validation.encrypt_with_key(&key)?.to_string(), + data: decrypted_export.encrypt_with_key(&key)?.to_string(), + }; + + Ok(serde_json::to_string_pretty(&encrypted_export)?) +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct EncryptedJsonExport { + encrypted: bool, + password_protected: bool, + salt: String, + kdf_type: u32, + kdf_iterations: u32, + kdf_memory: Option, + kdf_parallelism: Option, + #[serde(rename = "encKeyValidation_DO_NOT_EDIT")] + enc_key_validation: String, + data: String, +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroU32; + + use super::*; + use crate::{ + Card, Cipher, CipherType, Field, Identity, Login, LoginUri, SecureNote, SecureNoteType, + }; + + #[test] + pub fn test_export() { + let _export = export_encrypted_json( + vec![Folder { + id: "942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap(), + name: "Important".to_string(), + }], + vec![ + Cipher { + id: "25c8c414-b446-48e9-a1bd-b10700bbd740".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "Bitwarden".to_string(), + notes: Some("My note".to_string()), + + r#type: CipherType::Login(Box::new(Login { + username: Some("test@bitwarden.com".to_string()), + password: Some("asdfasdfasdf".to_string()), + login_uris: vec![LoginUri { + uri: Some("https://vault.bitwarden.com".to_string()), + r#match: None, + }], + totp: Some("ABC".to_string()), + })), + + favorite: true, + reprompt: 0, + + fields: vec![ + Field { + name: Some("Text".to_string()), + value: Some("A".to_string()), + r#type: 0, + linked_id: None, + }, + Field { + name: Some("Hidden".to_string()), + value: Some("B".to_string()), + r#type: 1, + linked_id: None, + }, + Field { + name: Some("Boolean (true)".to_string()), + value: Some("true".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Boolean (false)".to_string()), + value: Some("false".to_string()), + r#type: 2, + linked_id: None, + }, + Field { + name: Some("Linked".to_string()), + value: None, + r#type: 3, + linked_id: Some(101), + }, + ], + + revision_date: "2024-01-30T14:09:33.753Z".parse().unwrap(), + creation_date: "2024-01-30T11:23:54.416Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "23f0f877-42b1-4820-a850-b10700bc41eb".parse().unwrap(), + folder_id: None, + + name: "My secure note".to_string(), + notes: Some("Very secure!".to_string()), + + r#type: CipherType::SecureNote(Box::new(SecureNote { + r#type: SecureNoteType::Generic, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + creation_date: "2024-01-30T11:25:25.466Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "3ed8de45-48ee-4e26-a2dc-b10701276c53".parse().unwrap(), + folder_id: None, + + name: "My card".to_string(), + notes: None, + + r#type: CipherType::Card(Box::new(Card { + cardholder_name: Some("John Doe".to_string()), + exp_month: Some("1".to_string()), + exp_year: Some("2032".to_string()), + code: Some("123".to_string()), + brand: Some("Visa".to_string()), + number: Some("4111111111111111".to_string()), + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + }, + Cipher { + id: "41cc3bc1-c3d9-4637-876c-b10701273712".parse().unwrap(), + folder_id: Some("942e2984-1b9a-453b-b039-b107012713b9".parse().unwrap()), + + name: "My identity".to_string(), + notes: None, + + r#type: CipherType::Identity(Box::new(Identity { + title: Some("Mr".to_string()), + first_name: Some("John".to_string()), + middle_name: None, + last_name: Some("Doe".to_string()), + address1: None, + address2: None, + address3: None, + city: None, + state: None, + postal_code: None, + country: None, + company: Some("Bitwarden".to_string()), + email: None, + phone: None, + ssn: None, + username: Some("JDoe".to_string()), + passport_number: None, + license_number: None, + })), + + favorite: false, + reprompt: 0, + + fields: vec![], + + revision_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + creation_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), + deleted_date: None, + }, + ], + "password".to_string(), + Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + ) + .unwrap(); + } +} diff --git a/crates/bitwarden-exporters/src/lib.rs b/crates/bitwarden-exporters/src/lib.rs index bb690fbc1..814633489 100644 --- a/crates/bitwarden-exporters/src/lib.rs +++ b/crates/bitwarden-exporters/src/lib.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::Kdf; use chrono::{DateTime, Utc}; use thiserror::Error; use uuid::Uuid; @@ -6,11 +7,13 @@ mod csv; use csv::export_csv; mod json; use json::export_json; +mod encrypted_json; +use encrypted_json::export_encrypted_json; pub enum Format { Csv, Json, - EncryptedJson { password: String }, + EncryptedJson { password: String, kdf: Kdf }, } /// Export representation of a Bitwarden folder. @@ -127,6 +130,8 @@ pub enum ExportError { Csv(#[from] csv::CsvError), #[error("JSON error: {0}")] Json(#[from] json::JsonError), + #[error("Encrypted JSON error: {0}")] + EncryptedJsonError(#[from] encrypted_json::EncryptedJsonError), } pub fn export( @@ -137,6 +142,8 @@ pub fn export( match format { Format::Csv => Ok(export_csv(folders, ciphers)?), Format::Json => Ok(export_json(folders, ciphers)?), - Format::EncryptedJson { password: _ } => todo!(), + Format::EncryptedJson { password, kdf } => { + Ok(export_encrypted_json(folders, ciphers, password, kdf)?) + } } } diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index cbdb5bb86..9e9e99ed5 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -3,6 +3,7 @@ use bitwarden_exporters::export; use schemars::JsonSchema; use crate::{ + client::{LoginMethod, UserLoginMethod}, error::{Error, Result}, vault::{ login::LoginUriView, Cipher, CipherType, CipherView, Collection, FieldView, Folder, @@ -38,7 +39,35 @@ pub(super) fn export_vault( let ciphers: Vec = ciphers.into_iter().flat_map(|c| c.try_into()).collect(); - Ok(export(folders, ciphers, format.into())?) + let format = convert_format(client, format)?; + + Ok(export(folders, ciphers, format)?) +} + +fn convert_format( + client: &Client, + format: ExportFormat, +) -> Result { + let login_method = client + .login_method + .as_ref() + .ok_or(Error::NotAuthenticated)?; + + let kdf = match login_method { + LoginMethod::User( + UserLoginMethod::Username { kdf, .. } | UserLoginMethod::ApiKey { kdf, .. }, + ) => kdf, + _ => return Err(Error::NotAuthenticated), + }; + + Ok(match format { + ExportFormat::Csv => bitwarden_exporters::Format::Csv, + ExportFormat::Json => bitwarden_exporters::Format::Json, + ExportFormat::EncryptedJson { password } => bitwarden_exporters::Format::EncryptedJson { + password, + kdf: kdf.clone(), + }, + }) } pub(super) fn export_organization_vault( @@ -173,18 +202,11 @@ impl From for bitwarden_exporters::SecureNoteType { } } -impl From for bitwarden_exporters::Format { - fn from(value: ExportFormat) -> Self { - match value { - ExportFormat::Csv => Self::Csv, - ExportFormat::Json => Self::Json, - ExportFormat::EncryptedJson { password } => Self::EncryptedJson { password }, - } - } -} - #[cfg(test)] mod tests { + use std::num::NonZeroU32; + + use bitwarden_crypto::Kdf; use chrono::{DateTime, Utc}; use super::*; @@ -276,19 +298,32 @@ mod tests { } #[test] - fn test_from_export_format() { + fn test_convert_format() { + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "7b821276-e27c-400b-9853-606393c87f18".to_owned(), + email: "test@bitwarden.com".to_owned(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + })); + assert!(matches!( - bitwarden_exporters::Format::from(ExportFormat::Csv), + convert_format(&client, ExportFormat::Csv).unwrap(), bitwarden_exporters::Format::Csv )); assert!(matches!( - bitwarden_exporters::Format::from(ExportFormat::Json), + convert_format(&client, ExportFormat::Json).unwrap(), bitwarden_exporters::Format::Json )); assert!(matches!( - bitwarden_exporters::Format::from(ExportFormat::EncryptedJson { - password: "password".to_string() - }), + convert_format( + &client, + ExportFormat::EncryptedJson { + password: "password".to_string() + } + ) + .unwrap(), bitwarden_exporters::Format::EncryptedJson { .. } )); } From f57262c77a714e5ccbd2e1036364d4e48a04857f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 14:14:47 +0100 Subject: [PATCH 271/378] [PM-6108] Add support for missing AES decrypt types (#335) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add support for the missing AES decryption types: `AesCbc256_B64` and `AesCbc128_HmacSha256_B64`. Note that `SymmetricCryptoKey` at the moment expects 32 byte keys, and AES128 used 16 byte keys, so the 16byte key+mac get parsed as a single 32byte key. At the moment we just split it by hand, but ultimately we would need to handle this better in a future refactor. --- crates/bitwarden-crypto/src/aes.rs | 60 ++++++++++++++++++- .../src/enc_string/symmetric.rs | 51 ++++++++++++++-- 2 files changed, 104 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden-crypto/src/aes.rs b/crates/bitwarden-crypto/src/aes.rs index 195b818b7..ee76f9936 100644 --- a/crates/bitwarden-crypto/src/aes.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -6,7 +6,9 @@ //! [KeyEncryptable][crate::KeyEncryptable] & [KeyDecryptable][crate::KeyDecryptable] instead. use aes::cipher::{ - block_padding::Pkcs7, typenum::U32, BlockDecryptMut, BlockEncryptMut, KeyIvInit, + block_padding::Pkcs7, + typenum::{U16, U32}, + BlockDecryptMut, BlockEncryptMut, KeyIvInit, }; use generic_array::GenericArray; use hmac::Mac; @@ -109,6 +111,42 @@ fn encrypt_aes256_internal( (iv, data) } +/// Decrypt using AES-128 in CBC mode. +/// +/// Behaves similar to [decrypt_aes128_hmac], but does not validate the MAC. +fn decrypt_aes128(iv: &[u8; 16], data: Vec, key: &GenericArray) -> Result> { + // Decrypt data + let iv = GenericArray::from_slice(iv); + let mut data = data; + let decrypted_key_slice = cbc::Decryptor::::new(key, iv) + .decrypt_padded_mut::(&mut data) + .map_err(|_| CryptoError::KeyDecrypt)?; + + // Data is decrypted in place and returns a subslice of the original Vec, to avoid cloning it, + // we truncate to the subslice length + let decrypted_len = decrypted_key_slice.len(); + data.truncate(decrypted_len); + + Ok(data) +} + +/// Decrypt using AES-128 in CBC mode with MAC. +/// +/// Behaves similar to [decrypt_aes128], but also validates the MAC. +pub fn decrypt_aes128_hmac( + iv: &[u8; 16], + mac: &[u8; 32], + data: Vec, + mac_key: &GenericArray, + key: &GenericArray, +) -> Result> { + let res = generate_mac(mac_key, iv, &data)?; + if res.ct_ne(mac).into() { + return Err(CryptoError::InvalidMac); + } + decrypt_aes128(iv, data, key) +} + /// Generate a MAC using HMAC-SHA256. fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); @@ -124,14 +162,17 @@ fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { #[cfg(test)] mod tests { use base64::{engine::general_purpose::STANDARD, Engine}; - use generic_array::sequence::GenericSequence; + use generic_array::{sequence::GenericSequence, ArrayLength}; use rand::SeedableRng; use super::*; /// Helper function for generating a `GenericArray` of size 32 with each element being /// a multiple of a given increment, starting from a given offset. - fn generate_generic_array(offset: u8, increment: u8) -> GenericArray { + fn generate_generic_array>( + offset: u8, + increment: u8, + ) -> GenericArray { GenericArray::generate(|i| offset + i as u8 * increment) } @@ -170,6 +211,19 @@ mod tests { assert_eq!(mac.len(), 32); } + #[test] + fn test_decrypt_aes128() { + let iv = generate_vec(16, 0, 1); + let iv: &[u8; 16] = iv.as_slice().try_into().unwrap(); + let key = generate_generic_array(0, 1); + + let data = STANDARD.decode("dC0X+2IjFbeL4WLLg2jX7Q==").unwrap(); + + let decrypted = decrypt_aes128(iv, data, &key).unwrap(); + + assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!"); + } + #[test] fn test_decrypt_aes256() { let iv = generate_vec(16, 0, 1); diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index a7768de23..d5489fc96 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -236,13 +236,26 @@ impl KeyEncryptable for &[u8] { impl KeyDecryptable> for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result> { match self { + EncString::AesCbc256_B64 { iv, data } => { + let dec = crate::aes::decrypt_aes256(iv, data.clone(), &key.key)?; + Ok(dec) + } + EncString::AesCbc128_HmacSha256_B64 { iv, mac, data } => { + // TODO: SymmetricCryptoKey is designed to handle 32 byte keys only, but this + // variant uses a 16 byte key This means the key+mac are going to be + // parsed as a single 32 byte key, at the moment we split it manually + // When refactoring the key handling, this should be fixed. + let enc_key = key.key[0..16].into(); + let mac_key = key.key[16..32].into(); + let dec = crate::aes::decrypt_aes128_hmac(iv, mac, data.clone(), mac_key, enc_key)?; + Ok(dec) + } EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.as_ref().ok_or(CryptoError::InvalidMac)?; let dec = crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, &key.key)?; Ok(dec) } - _ => Err(CryptoError::InvalidKey), } } } @@ -277,7 +290,7 @@ mod tests { use schemars::schema_for; use super::EncString; - use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable}; + use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; #[test] fn test_enc_string_roundtrip() { @@ -343,7 +356,9 @@ mod tests { data, &[93, 118, 241, 43, 16, 211, 135, 233, 150, 136, 221, 71, 140, 125, 141, 215] ); - } + } else { + panic!("Invalid variant") + }; } #[test] @@ -368,7 +383,35 @@ mod tests { data, &[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69] ); - } + } else { + panic!("Invalid variant") + }; + } + + #[test] + fn test_decrypt_cbc256() { + let key = "hvBMMb1t79YssFZkpetYsM3deyVuQv4r88Uj9gvYe08="; + let key: SymmetricCryptoKey = key.parse().unwrap(); + + let enc_str = "0.NQfjHLr6za7VQVAbrpL81w==|wfrjmyJ0bfwkQlySrhw8dA=="; + let enc_string: EncString = enc_str.parse().unwrap(); + assert_eq!(enc_string.enc_type(), 0); + + let dec_str: String = enc_string.decrypt_with_key(&key).unwrap(); + assert_eq!(dec_str, "EncryptMe!"); + } + + #[test] + fn test_decrypt_cbc128_hmac() { + let key = "Gt1aZ8kTTgkF80bLtb7LiMZBcxEA2FA5mbvV4x7K208="; + let key: SymmetricCryptoKey = key.parse().unwrap(); + + let enc_str = "1.CU/oG4VZuxbHoZSDZjCLQw==|kb1HGwAk+fQ275ORfLf5Ew==|8UaEYHyqRZcG37JWhYBOBdEatEXd1u1/wN7OuImolcM="; + let enc_string: EncString = enc_str.parse().unwrap(); + assert_eq!(enc_string.enc_type(), 1); + + let dec_str: String = enc_string.decrypt_with_key(&key).unwrap(); + assert_eq!(dec_str, "EncryptMe!"); } #[test] From 939934665abbf2e9b36b20bb7b87530cc1f7618e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 8 Feb 2024 14:15:02 +0100 Subject: [PATCH 272/378] [PM-6107] Use rayon to multithread encryption/decryption (#215) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Use rayon to multithread the encryption and decryption of ciphers. Note that this will have no benefit for WASM, as in that case it falls back to a single thread model. In my Mac I get 8-9x speedups when decrypting a big number of EncStrings. --- Cargo.lock | 40 +++++++++++++++++ crates/bitwarden-crypto/Cargo.toml | 1 + crates/bitwarden-crypto/src/encryptable.rs | 34 +++++++++----- .../src/keys/key_encryptable.rs | 44 ++++++++++++++----- 4 files changed, 96 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44aaee484..9e7cc9414 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -439,6 +439,7 @@ dependencies = [ "pbkdf2", "rand 0.8.5", "rand_chacha 0.3.1", + "rayon", "rsa", "schemars", "serde", @@ -961,6 +962,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -2578,6 +2598,26 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 295cdd38e..f0eac0d0a 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -32,6 +32,7 @@ num-bigint = ">=0.4, <0.5" num-traits = ">=0.2.15, <0.3" pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } rand = ">=0.8.5, <0.9" +rayon = ">=1.8.1, <2.0" rsa = ">=0.9.2, <0.10" schemars = { version = ">=0.8, <0.9", features = ["uuid1"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } diff --git a/crates/bitwarden-crypto/src/encryptable.rs b/crates/bitwarden-crypto/src/encryptable.rs index 9f1256afa..a9882629f 100644 --- a/crates/bitwarden-crypto/src/encryptable.rs +++ b/crates/bitwarden-crypto/src/encryptable.rs @@ -1,10 +1,11 @@ use std::{collections::HashMap, hash::Hash}; +use rayon::prelude::*; use uuid::Uuid; use crate::{CryptoError, KeyDecryptable, KeyEncryptable, Result, SymmetricCryptoKey}; -pub trait KeyContainer { +pub trait KeyContainer: Send + Sync { fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey>; } @@ -46,37 +47,48 @@ impl + LocateKey, Output> Decrypta } } -impl, Output> Encryptable> for Vec { +impl + Send + Sync, Output: Send + Sync> Encryptable> + for Vec +{ fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { - self.into_iter().map(|e| e.encrypt(enc, org_id)).collect() + self.into_par_iter() + .map(|e| e.encrypt(enc, org_id)) + .collect() } } -impl, Output> Decryptable> for Vec { +impl + Send + Sync, Output: Send + Sync> Decryptable> + for Vec +{ fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { - self.iter().map(|e| e.decrypt(enc, org_id)).collect() + self.into_par_iter() + .map(|e| e.decrypt(enc, org_id)) + .collect() } } -impl, Output, Id: Hash + Eq> Encryptable> - for HashMap +impl + Send + Sync, Output: Send + Sync, Id: Hash + Eq + Send + Sync> + Encryptable> for HashMap { fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { - self.into_iter() + self.into_par_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) .collect() } } -impl, Output, Id: Hash + Eq + Copy> Decryptable> - for HashMap +impl< + T: Decryptable + Send + Sync, + Output: Send + Sync, + Id: Hash + Eq + Copy + Send + Sync, + > Decryptable> for HashMap { fn decrypt( &self, enc: &dyn KeyContainer, org_id: &Option, ) -> Result> { - self.iter() + self.into_par_iter() .map(|(id, e)| Ok((*id, e.decrypt(enc, org_id)?))) .collect() } diff --git a/crates/bitwarden-crypto/src/keys/key_encryptable.rs b/crates/bitwarden-crypto/src/keys/key_encryptable.rs index 852b55c62..750647ee8 100644 --- a/crates/bitwarden-crypto/src/keys/key_encryptable.rs +++ b/crates/bitwarden-crypto/src/keys/key_encryptable.rs @@ -1,5 +1,7 @@ use std::{collections::HashMap, hash::Hash}; +use rayon::prelude::*; + use crate::error::Result; pub trait CryptoKey {} @@ -44,37 +46,55 @@ impl, Key: CryptoKey, Output> KeyDecryptable, Key: CryptoKey, Output> KeyEncryptable> - for Vec +impl< + T: KeyEncryptable + Send + Sync, + Key: CryptoKey + Send + Sync, + Output: Send + Sync, + > KeyEncryptable> for Vec { fn encrypt_with_key(self, key: &Key) -> Result> { - self.into_iter().map(|e| e.encrypt_with_key(key)).collect() + self.into_par_iter() + .map(|e| e.encrypt_with_key(key)) + .collect() } } -impl, Key: CryptoKey, Output> KeyDecryptable> - for Vec +impl< + T: KeyDecryptable + Send + Sync, + Key: CryptoKey + Send + Sync, + Output: Send + Sync, + > KeyDecryptable> for Vec { fn decrypt_with_key(&self, key: &Key) -> Result> { - self.iter().map(|e| e.decrypt_with_key(key)).collect() + self.into_par_iter() + .map(|e| e.decrypt_with_key(key)) + .collect() } } -impl, Key: CryptoKey, Output, Id: Hash + Eq> - KeyEncryptable> for HashMap +impl< + T: KeyEncryptable + Send + Sync, + Key: CryptoKey + Send + Sync, + Output: Send + Sync, + Id: Hash + Eq + Send + Sync, + > KeyEncryptable> for HashMap { fn encrypt_with_key(self, key: &Key) -> Result> { - self.into_iter() + self.into_par_iter() .map(|(id, e)| Ok((id, e.encrypt_with_key(key)?))) .collect() } } -impl, Key: CryptoKey, Output, Id: Hash + Eq + Copy> - KeyDecryptable> for HashMap +impl< + T: KeyDecryptable + Send + Sync, + Key: CryptoKey + Send + Sync, + Output: Send + Sync, + Id: Hash + Eq + Copy + Send + Sync, + > KeyDecryptable> for HashMap { fn decrypt_with_key(&self, key: &Key) -> Result> { - self.iter() + self.into_par_iter() .map(|(id, e)| Ok((*id, e.decrypt_with_key(key)?))) .collect() } From 6882a2096b6c1d2865d83bf22c05aa1ddae244c8 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 9 Feb 2024 09:47:35 +0100 Subject: [PATCH 273/378] [PM-6165] Update bindings with enum names (#594) Update the generated bindings to use `x-enum-varname` which allows us to generate semantically useful enums instead of `Variant0`. Depends on https://github.com/bitwarden/server/pull/3767 --- README.md | 16 +- .../.openapi-generator-ignore | 2 - .../.openapi-generator/FILES | 1 + .../bitwarden-api-api/src/models/algorithm.rs | 50 +-- .../src/models/auth_request_type.rs | 14 +- .../src/models/bitwarden_product_type.rs | 34 -- .../src/models/cipher_reprompt_type.rs | 10 +- ...pher_response_model_list_response_model.rs | 29 -- .../src/models/cipher_type.rs | 18 +- .../src/models/device_type.rs | 106 ++--- .../models/emergency_access_status_type.rs | 22 +- .../src/models/emergency_access_type.rs | 10 +- .../src/models/event_system_user.rs | 10 +- .../src/models/event_type.rs | 298 +++++++------- .../src/models/field_type.rs | 18 +- .../src/models/file_upload_type.rs | 10 +- .../models/global_equivalent_domains_type.rs | 366 +++++++++--------- .../src/models/iap_check_request_model.rs | 23 -- .../src/models/inner_project.rs | 26 -- .../src/models/inner_secret.rs | 44 --- .../bitwarden-api-api/src/models/kdf_type.rs | 10 +- .../src/models/license_type.rs | 10 +- .../src/models/member_decryption_type.rs | 14 +- .../open_id_connect_redirect_behavior.rs | 10 +- .../src/models/organization_api_key_type.rs | 14 +- .../models/organization_connection_type.rs | 10 +- ...on_enroll_secrets_manager_request_model.rs | 21 - .../models/organization_user_status_type.rs | 18 +- .../src/models/organization_user_type.rs | 22 +- .../src/models/payment_method_type.rs | 34 +- .../src/models/plan_sponsorship_type.rs | 6 +- .../bitwarden-api-api/src/models/plan_type.rs | 70 ++-- .../src/models/policy_type.rs | 50 +-- .../src/models/product_type.rs | 22 +- .../src/models/provider_type.rs | 10 +- .../src/models/provider_user_status_type.rs | 14 +- .../src/models/provider_user_type.rs | 10 +- .../bitwarden-api-api/src/models/push_type.rs | 70 ++-- .../src/models/saml2_binding_type.rs | 10 +- .../src/models/saml2_name_id_format.rs | 38 +- .../src/models/saml2_signing_behavior.rs | 14 +- .../src/models/secure_note_type.rs | 6 +- .../bitwarden-api-api/src/models/send_type.rs | 10 +- ..._account_access_policies_response_model.rs | 34 -- ...ount_response_model_list_response_model.rs | 29 -- .../bitwarden-api-api/src/models/sso_type.rs | 10 +- .../src/models/transaction_type.rs | 22 +- .../src/models/two_factor_provider_type.rs | 34 +- .../src/models/uri_match_type.rs | 26 +- .../src/models/web_authn_prf_status.rs | 14 +- .../src/models/kdf_type.rs | 10 +- crates/bitwarden/src/admin_console/policy.rs | 32 +- .../api/response/identity_success_response.rs | 2 +- .../bitwarden/src/auth/login/auth_request.rs | 2 +- crates/bitwarden/src/auth/login/mod.rs | 4 +- crates/bitwarden/src/auth/register.rs | 2 +- crates/bitwarden/src/vault/cipher/cipher.rs | 12 +- crates/bitwarden/src/vault/cipher/field.rs | 8 +- crates/bitwarden/src/vault/cipher/login.rs | 12 +- .../bitwarden/src/vault/cipher/secure_note.rs | 2 +- crates/bitwarden/src/vault/send.rs | 4 +- support/build-api.sh | 26 ++ 62 files changed, 832 insertions(+), 1053 deletions(-) delete mode 100644 crates/bitwarden-api-api/src/models/bitwarden_product_type.rs delete mode 100644 crates/bitwarden-api-api/src/models/cipher_response_model_list_response_model.rs delete mode 100644 crates/bitwarden-api-api/src/models/iap_check_request_model.rs delete mode 100644 crates/bitwarden-api-api/src/models/inner_project.rs delete mode 100644 crates/bitwarden-api-api/src/models/inner_secret.rs delete mode 100644 crates/bitwarden-api-api/src/models/organization_enroll_secrets_manager_request_model.rs delete mode 100644 crates/bitwarden-api-api/src/models/service_account_access_policies_response_model.rs delete mode 100644 crates/bitwarden-api-api/src/models/service_account_response_model_list_response_model.rs create mode 100755 support/build-api.sh diff --git a/README.md b/README.md index dbf4e4f2c..9e3aa325f 100644 --- a/README.md +++ b/README.md @@ -68,21 +68,7 @@ ASPNETCORE_ENVIRONMENT=development dotnet swagger tofile --output ../../identity Runs from the root of the SDK project. ```bash -npx openapi-generator-cli generate \ - -i ../server/api.json \ - -g rust \ - -o crates/bitwarden-api-api \ - --package-name bitwarden-api-api \ - -t ./support/openapi-template \ - --additional-properties=packageVersion=1.0.0 - -npx openapi-generator-cli generate \ - -i ../server/identity.json \ - -g rust \ - -o crates/bitwarden-api-identity \ - --package-name bitwarden-api-identity \ - -t ./support/openapi-template \ - --additional-properties=packageVersion=1.0.0 +./support/build-api.sh ``` OpenApi Generator works using templates, we have customized our templates to work better with our diff --git a/crates/bitwarden-api-api/.openapi-generator-ignore b/crates/bitwarden-api-api/.openapi-generator-ignore index b72fc90d8..0a3fec13f 100644 --- a/crates/bitwarden-api-api/.openapi-generator-ignore +++ b/crates/bitwarden-api-api/.openapi-generator-ignore @@ -25,5 +25,3 @@ docs/*.md .travis.yml git_push.sh - -src/models/organization_user_status_type.rs diff --git a/crates/bitwarden-api-api/.openapi-generator/FILES b/crates/bitwarden-api-api/.openapi-generator/FILES index 4566fa01c..206ad61b2 100644 --- a/crates/bitwarden-api-api/.openapi-generator/FILES +++ b/crates/bitwarden-api-api/.openapi-generator/FILES @@ -253,6 +253,7 @@ src/models/organization_user_public_key_response_model_list_response_model.rs src/models/organization_user_reset_password_details_response_model.rs src/models/organization_user_reset_password_enrollment_request_model.rs src/models/organization_user_reset_password_request_model.rs +src/models/organization_user_status_type.rs src/models/organization_user_type.rs src/models/organization_user_update_groups_request_model.rs src/models/organization_user_update_request_model.rs diff --git a/crates/bitwarden-api-api/src/models/algorithm.rs b/crates/bitwarden-api-api/src/models/algorithm.rs index 315879d54..2c302de0a 100644 --- a/crates/bitwarden-api-api/src/models/algorithm.rs +++ b/crates/bitwarden-api-api/src/models/algorithm.rs @@ -14,41 +14,41 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum Algorithm { - Variant65535 = -65535, - Variant259 = -259, - Variant258 = -258, - Variant257 = -257, - Variant47 = -47, - Variant39 = -39, - Variant38 = -38, - Variant37 = -37, - Variant36 = -36, - Variant35 = -35, - Variant8 = -8, - Variant7 = -7, + RS1 = -65535, + RS512 = -259, + RS384 = -258, + RS256 = -257, + ES256K = -47, + PS512 = -39, + PS384 = -38, + PS256 = -37, + ES512 = -36, + ES384 = -35, + EdDSA = -8, + ES256 = -7, } impl ToString for Algorithm { fn to_string(&self) -> String { match self { - Self::Variant65535 => String::from("-65535"), - Self::Variant259 => String::from("-259"), - Self::Variant258 => String::from("-258"), - Self::Variant257 => String::from("-257"), - Self::Variant47 => String::from("-47"), - Self::Variant39 => String::from("-39"), - Self::Variant38 => String::from("-38"), - Self::Variant37 => String::from("-37"), - Self::Variant36 => String::from("-36"), - Self::Variant35 => String::from("-35"), - Self::Variant8 => String::from("-8"), - Self::Variant7 => String::from("-7"), + Self::RS1 => String::from("-65535"), + Self::RS512 => String::from("-259"), + Self::RS384 => String::from("-258"), + Self::RS256 => String::from("-257"), + Self::ES256K => String::from("-47"), + Self::PS512 => String::from("-39"), + Self::PS384 => String::from("-38"), + Self::PS256 => String::from("-37"), + Self::ES512 => String::from("-36"), + Self::ES384 => String::from("-35"), + Self::EdDSA => String::from("-8"), + Self::ES256 => String::from("-7"), } } } impl Default for Algorithm { fn default() -> Algorithm { - Self::Variant65535 + Self::RS1 } } diff --git a/crates/bitwarden-api-api/src/models/auth_request_type.rs b/crates/bitwarden-api-api/src/models/auth_request_type.rs index fbcfb8e9f..1ca3f7790 100644 --- a/crates/bitwarden-api-api/src/models/auth_request_type.rs +++ b/crates/bitwarden-api-api/src/models/auth_request_type.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum AuthRequestType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, + AuthenticateAndUnlock = 0, + Unlock = 1, + AdminApproval = 2, } impl ToString for AuthRequestType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::AuthenticateAndUnlock => String::from("0"), + Self::Unlock => String::from("1"), + Self::AdminApproval => String::from("2"), } } } impl Default for AuthRequestType { fn default() -> AuthRequestType { - Self::Variant0 + Self::AuthenticateAndUnlock } } diff --git a/crates/bitwarden-api-api/src/models/bitwarden_product_type.rs b/crates/bitwarden-api-api/src/models/bitwarden_product_type.rs deleted file mode 100644 index 2224e9781..000000000 --- a/crates/bitwarden-api-api/src/models/bitwarden_product_type.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -/// -#[repr(i64)] -#[derive( - Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, -)] -pub enum BitwardenProductType { - Variant0 = 0, - Variant1 = 1, -} - -impl ToString for BitwardenProductType { - fn to_string(&self) -> String { - match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - } - } -} - -impl Default for BitwardenProductType { - fn default() -> BitwardenProductType { - Self::Variant0 - } -} diff --git a/crates/bitwarden-api-api/src/models/cipher_reprompt_type.rs b/crates/bitwarden-api-api/src/models/cipher_reprompt_type.rs index d20cef2db..4443b8c03 100644 --- a/crates/bitwarden-api-api/src/models/cipher_reprompt_type.rs +++ b/crates/bitwarden-api-api/src/models/cipher_reprompt_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum CipherRepromptType { - Variant0 = 0, - Variant1 = 1, + None = 0, + Password = 1, } impl ToString for CipherRepromptType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::None => String::from("0"), + Self::Password => String::from("1"), } } } impl Default for CipherRepromptType { fn default() -> CipherRepromptType { - Self::Variant0 + Self::None } } diff --git a/crates/bitwarden-api-api/src/models/cipher_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/cipher_response_model_list_response_model.rs deleted file mode 100644 index ca2541930..000000000 --- a/crates/bitwarden-api-api/src/models/cipher_response_model_list_response_model.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct CipherResponseModelListResponseModel { - #[serde(rename = "object", skip_serializing_if = "Option::is_none")] - pub object: Option, - #[serde(rename = "data", skip_serializing_if = "Option::is_none")] - pub data: Option>, - #[serde(rename = "continuationToken", skip_serializing_if = "Option::is_none")] - pub continuation_token: Option, -} - -impl CipherResponseModelListResponseModel { - pub fn new() -> CipherResponseModelListResponseModel { - CipherResponseModelListResponseModel { - object: None, - data: None, - continuation_token: None, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/cipher_type.rs b/crates/bitwarden-api-api/src/models/cipher_type.rs index 1420ac6a4..044349ef8 100644 --- a/crates/bitwarden-api-api/src/models/cipher_type.rs +++ b/crates/bitwarden-api-api/src/models/cipher_type.rs @@ -14,25 +14,25 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum CipherType { - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, + Login = 1, + SecureNote = 2, + Card = 3, + Identity = 4, } impl ToString for CipherType { fn to_string(&self) -> String { match self { - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), + Self::Login => String::from("1"), + Self::SecureNote => String::from("2"), + Self::Card => String::from("3"), + Self::Identity => String::from("4"), } } } impl Default for CipherType { fn default() -> CipherType { - Self::Variant1 + Self::Login } } diff --git a/crates/bitwarden-api-api/src/models/device_type.rs b/crates/bitwarden-api-api/src/models/device_type.rs index 26bbc7a52..12e162ce6 100644 --- a/crates/bitwarden-api-api/src/models/device_type.rs +++ b/crates/bitwarden-api-api/src/models/device_type.rs @@ -14,69 +14,69 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum DeviceType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, - Variant9 = 9, - Variant10 = 10, - Variant11 = 11, - Variant12 = 12, - Variant13 = 13, - Variant14 = 14, - Variant15 = 15, - Variant16 = 16, - Variant17 = 17, - Variant18 = 18, - Variant19 = 19, - Variant20 = 20, - Variant21 = 21, - Variant22 = 22, - Variant23 = 23, - Variant24 = 24, - Variant25 = 25, + Android = 0, + iOS = 1, + ChromeExtension = 2, + FirefoxExtension = 3, + OperaExtension = 4, + EdgeExtension = 5, + WindowsDesktop = 6, + MacOsDesktop = 7, + LinuxDesktop = 8, + ChromeBrowser = 9, + FirefoxBrowser = 10, + OperaBrowser = 11, + EdgeBrowser = 12, + IEBrowser = 13, + UnknownBrowser = 14, + AndroidAmazon = 15, + UWP = 16, + SafariBrowser = 17, + VivaldiBrowser = 18, + VivaldiExtension = 19, + SafariExtension = 20, + SDK = 21, + Server = 22, + WindowsCLI = 23, + MacOsCLI = 24, + LinuxCLI = 25, } impl ToString for DeviceType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), - Self::Variant9 => String::from("9"), - Self::Variant10 => String::from("10"), - Self::Variant11 => String::from("11"), - Self::Variant12 => String::from("12"), - Self::Variant13 => String::from("13"), - Self::Variant14 => String::from("14"), - Self::Variant15 => String::from("15"), - Self::Variant16 => String::from("16"), - Self::Variant17 => String::from("17"), - Self::Variant18 => String::from("18"), - Self::Variant19 => String::from("19"), - Self::Variant20 => String::from("20"), - Self::Variant21 => String::from("21"), - Self::Variant22 => String::from("22"), - Self::Variant23 => String::from("23"), - Self::Variant24 => String::from("24"), - Self::Variant25 => String::from("25"), + Self::Android => String::from("0"), + Self::iOS => String::from("1"), + Self::ChromeExtension => String::from("2"), + Self::FirefoxExtension => String::from("3"), + Self::OperaExtension => String::from("4"), + Self::EdgeExtension => String::from("5"), + Self::WindowsDesktop => String::from("6"), + Self::MacOsDesktop => String::from("7"), + Self::LinuxDesktop => String::from("8"), + Self::ChromeBrowser => String::from("9"), + Self::FirefoxBrowser => String::from("10"), + Self::OperaBrowser => String::from("11"), + Self::EdgeBrowser => String::from("12"), + Self::IEBrowser => String::from("13"), + Self::UnknownBrowser => String::from("14"), + Self::AndroidAmazon => String::from("15"), + Self::UWP => String::from("16"), + Self::SafariBrowser => String::from("17"), + Self::VivaldiBrowser => String::from("18"), + Self::VivaldiExtension => String::from("19"), + Self::SafariExtension => String::from("20"), + Self::SDK => String::from("21"), + Self::Server => String::from("22"), + Self::WindowsCLI => String::from("23"), + Self::MacOsCLI => String::from("24"), + Self::LinuxCLI => String::from("25"), } } } impl Default for DeviceType { fn default() -> DeviceType { - Self::Variant0 + Self::Android } } diff --git a/crates/bitwarden-api-api/src/models/emergency_access_status_type.rs b/crates/bitwarden-api-api/src/models/emergency_access_status_type.rs index a4766cec4..9b046f3eb 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_status_type.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_status_type.rs @@ -14,27 +14,27 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum EmergencyAccessStatusType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, + Invited = 0, + Accepted = 1, + Confirmed = 2, + RecoveryInitiated = 3, + RecoveryApproved = 4, } impl ToString for EmergencyAccessStatusType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), + Self::Invited => String::from("0"), + Self::Accepted => String::from("1"), + Self::Confirmed => String::from("2"), + Self::RecoveryInitiated => String::from("3"), + Self::RecoveryApproved => String::from("4"), } } } impl Default for EmergencyAccessStatusType { fn default() -> EmergencyAccessStatusType { - Self::Variant0 + Self::Invited } } diff --git a/crates/bitwarden-api-api/src/models/emergency_access_type.rs b/crates/bitwarden-api-api/src/models/emergency_access_type.rs index 007df25a2..317c42f94 100644 --- a/crates/bitwarden-api-api/src/models/emergency_access_type.rs +++ b/crates/bitwarden-api-api/src/models/emergency_access_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum EmergencyAccessType { - Variant0 = 0, - Variant1 = 1, + View = 0, + Takeover = 1, } impl ToString for EmergencyAccessType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::View => String::from("0"), + Self::Takeover => String::from("1"), } } } impl Default for EmergencyAccessType { fn default() -> EmergencyAccessType { - Self::Variant0 + Self::View } } diff --git a/crates/bitwarden-api-api/src/models/event_system_user.rs b/crates/bitwarden-api-api/src/models/event_system_user.rs index 8a1795433..afb1333e8 100644 --- a/crates/bitwarden-api-api/src/models/event_system_user.rs +++ b/crates/bitwarden-api-api/src/models/event_system_user.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum EventSystemUser { - Variant1 = 1, - Variant2 = 2, + SCIM = 1, + DomainVerification = 2, } impl ToString for EventSystemUser { fn to_string(&self) -> String { match self { - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::SCIM => String::from("1"), + Self::DomainVerification => String::from("2"), } } } impl Default for EventSystemUser { fn default() -> EventSystemUser { - Self::Variant1 + Self::SCIM } } diff --git a/crates/bitwarden-api-api/src/models/event_type.rs b/crates/bitwarden-api-api/src/models/event_type.rs index cc4e96c14..2826c1fb4 100644 --- a/crates/bitwarden-api-api/src/models/event_type.rs +++ b/crates/bitwarden-api-api/src/models/event_type.rs @@ -14,165 +14,165 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum EventType { - Variant1000 = 1000, - Variant1001 = 1001, - Variant1002 = 1002, - Variant1003 = 1003, - Variant1004 = 1004, - Variant1005 = 1005, - Variant1006 = 1006, - Variant1007 = 1007, - Variant1008 = 1008, - Variant1009 = 1009, - Variant1010 = 1010, - Variant1100 = 1100, - Variant1101 = 1101, - Variant1102 = 1102, - Variant1103 = 1103, - Variant1104 = 1104, - Variant1105 = 1105, - Variant1106 = 1106, - Variant1107 = 1107, - Variant1108 = 1108, - Variant1109 = 1109, - Variant1110 = 1110, - Variant1111 = 1111, - Variant1112 = 1112, - Variant1113 = 1113, - Variant1114 = 1114, - Variant1115 = 1115, - Variant1116 = 1116, - Variant1117 = 1117, - Variant1300 = 1300, - Variant1301 = 1301, - Variant1302 = 1302, - Variant1400 = 1400, - Variant1401 = 1401, - Variant1402 = 1402, - Variant1500 = 1500, - Variant1501 = 1501, - Variant1502 = 1502, - Variant1503 = 1503, - Variant1504 = 1504, - Variant1505 = 1505, - Variant1506 = 1506, - Variant1507 = 1507, - Variant1508 = 1508, - Variant1509 = 1509, - Variant1510 = 1510, - Variant1511 = 1511, - Variant1512 = 1512, - Variant1513 = 1513, - Variant1514 = 1514, - Variant1600 = 1600, - Variant1601 = 1601, - Variant1602 = 1602, - Variant1603 = 1603, - Variant1604 = 1604, - Variant1605 = 1605, - Variant1606 = 1606, - Variant1607 = 1607, - Variant1608 = 1608, - Variant1609 = 1609, - Variant1700 = 1700, - Variant1800 = 1800, - Variant1801 = 1801, - Variant1802 = 1802, - Variant1803 = 1803, - Variant1900 = 1900, - Variant1901 = 1901, - Variant1902 = 1902, - Variant1903 = 1903, - Variant2000 = 2000, - Variant2001 = 2001, - Variant2002 = 2002, - Variant2003 = 2003, - Variant2100 = 2100, + User_LoggedIn = 1000, + User_ChangedPassword = 1001, + User_Updated2fa = 1002, + User_Disabled2fa = 1003, + User_Recovered2fa = 1004, + User_FailedLogIn = 1005, + User_FailedLogIn2fa = 1006, + User_ClientExportedVault = 1007, + User_UpdatedTempPassword = 1008, + User_MigratedKeyToKeyConnector = 1009, + User_RequestedDeviceApproval = 1010, + Cipher_Created = 1100, + Cipher_Updated = 1101, + Cipher_Deleted = 1102, + Cipher_AttachmentCreated = 1103, + Cipher_AttachmentDeleted = 1104, + Cipher_Shared = 1105, + Cipher_UpdatedCollections = 1106, + Cipher_ClientViewed = 1107, + Cipher_ClientToggledPasswordVisible = 1108, + Cipher_ClientToggledHiddenFieldVisible = 1109, + Cipher_ClientToggledCardCodeVisible = 1110, + Cipher_ClientCopiedPassword = 1111, + Cipher_ClientCopiedHiddenField = 1112, + Cipher_ClientCopiedCardCode = 1113, + Cipher_ClientAutofilled = 1114, + Cipher_SoftDeleted = 1115, + Cipher_Restored = 1116, + Cipher_ClientToggledCardNumberVisible = 1117, + Collection_Created = 1300, + Collection_Updated = 1301, + Collection_Deleted = 1302, + Group_Created = 1400, + Group_Updated = 1401, + Group_Deleted = 1402, + OrganizationUser_Invited = 1500, + OrganizationUser_Confirmed = 1501, + OrganizationUser_Updated = 1502, + OrganizationUser_Removed = 1503, + OrganizationUser_UpdatedGroups = 1504, + OrganizationUser_UnlinkedSso = 1505, + OrganizationUser_ResetPassword_Enroll = 1506, + OrganizationUser_ResetPassword_Withdraw = 1507, + OrganizationUser_AdminResetPassword = 1508, + OrganizationUser_ResetSsoLink = 1509, + OrganizationUser_FirstSsoLogin = 1510, + OrganizationUser_Revoked = 1511, + OrganizationUser_Restored = 1512, + OrganizationUser_ApprovedAuthRequest = 1513, + OrganizationUser_RejectedAuthRequest = 1514, + Organization_Updated = 1600, + Organization_PurgedVault = 1601, + Organization_ClientExportedVault = 1602, + Organization_VaultAccessed = 1603, + Organization_EnabledSso = 1604, + Organization_DisabledSso = 1605, + Organization_EnabledKeyConnector = 1606, + Organization_DisabledKeyConnector = 1607, + Organization_SponsorshipsSynced = 1608, + Organization_CollectionManagement_Updated = 1609, + Policy_Updated = 1700, + ProviderUser_Invited = 1800, + ProviderUser_Confirmed = 1801, + ProviderUser_Updated = 1802, + ProviderUser_Removed = 1803, + ProviderOrganization_Created = 1900, + ProviderOrganization_Added = 1901, + ProviderOrganization_Removed = 1902, + ProviderOrganization_VaultAccessed = 1903, + OrganizationDomain_Added = 2000, + OrganizationDomain_Removed = 2001, + OrganizationDomain_Verified = 2002, + OrganizationDomain_NotVerified = 2003, + Secret_Retrieved = 2100, } impl ToString for EventType { fn to_string(&self) -> String { match self { - Self::Variant1000 => String::from("1000"), - Self::Variant1001 => String::from("1001"), - Self::Variant1002 => String::from("1002"), - Self::Variant1003 => String::from("1003"), - Self::Variant1004 => String::from("1004"), - Self::Variant1005 => String::from("1005"), - Self::Variant1006 => String::from("1006"), - Self::Variant1007 => String::from("1007"), - Self::Variant1008 => String::from("1008"), - Self::Variant1009 => String::from("1009"), - Self::Variant1010 => String::from("1010"), - Self::Variant1100 => String::from("1100"), - Self::Variant1101 => String::from("1101"), - Self::Variant1102 => String::from("1102"), - Self::Variant1103 => String::from("1103"), - Self::Variant1104 => String::from("1104"), - Self::Variant1105 => String::from("1105"), - Self::Variant1106 => String::from("1106"), - Self::Variant1107 => String::from("1107"), - Self::Variant1108 => String::from("1108"), - Self::Variant1109 => String::from("1109"), - Self::Variant1110 => String::from("1110"), - Self::Variant1111 => String::from("1111"), - Self::Variant1112 => String::from("1112"), - Self::Variant1113 => String::from("1113"), - Self::Variant1114 => String::from("1114"), - Self::Variant1115 => String::from("1115"), - Self::Variant1116 => String::from("1116"), - Self::Variant1117 => String::from("1117"), - Self::Variant1300 => String::from("1300"), - Self::Variant1301 => String::from("1301"), - Self::Variant1302 => String::from("1302"), - Self::Variant1400 => String::from("1400"), - Self::Variant1401 => String::from("1401"), - Self::Variant1402 => String::from("1402"), - Self::Variant1500 => String::from("1500"), - Self::Variant1501 => String::from("1501"), - Self::Variant1502 => String::from("1502"), - Self::Variant1503 => String::from("1503"), - Self::Variant1504 => String::from("1504"), - Self::Variant1505 => String::from("1505"), - Self::Variant1506 => String::from("1506"), - Self::Variant1507 => String::from("1507"), - Self::Variant1508 => String::from("1508"), - Self::Variant1509 => String::from("1509"), - Self::Variant1510 => String::from("1510"), - Self::Variant1511 => String::from("1511"), - Self::Variant1512 => String::from("1512"), - Self::Variant1513 => String::from("1513"), - Self::Variant1514 => String::from("1514"), - Self::Variant1600 => String::from("1600"), - Self::Variant1601 => String::from("1601"), - Self::Variant1602 => String::from("1602"), - Self::Variant1603 => String::from("1603"), - Self::Variant1604 => String::from("1604"), - Self::Variant1605 => String::from("1605"), - Self::Variant1606 => String::from("1606"), - Self::Variant1607 => String::from("1607"), - Self::Variant1608 => String::from("1608"), - Self::Variant1609 => String::from("1609"), - Self::Variant1700 => String::from("1700"), - Self::Variant1800 => String::from("1800"), - Self::Variant1801 => String::from("1801"), - Self::Variant1802 => String::from("1802"), - Self::Variant1803 => String::from("1803"), - Self::Variant1900 => String::from("1900"), - Self::Variant1901 => String::from("1901"), - Self::Variant1902 => String::from("1902"), - Self::Variant1903 => String::from("1903"), - Self::Variant2000 => String::from("2000"), - Self::Variant2001 => String::from("2001"), - Self::Variant2002 => String::from("2002"), - Self::Variant2003 => String::from("2003"), - Self::Variant2100 => String::from("2100"), + Self::User_LoggedIn => String::from("1000"), + Self::User_ChangedPassword => String::from("1001"), + Self::User_Updated2fa => String::from("1002"), + Self::User_Disabled2fa => String::from("1003"), + Self::User_Recovered2fa => String::from("1004"), + Self::User_FailedLogIn => String::from("1005"), + Self::User_FailedLogIn2fa => String::from("1006"), + Self::User_ClientExportedVault => String::from("1007"), + Self::User_UpdatedTempPassword => String::from("1008"), + Self::User_MigratedKeyToKeyConnector => String::from("1009"), + Self::User_RequestedDeviceApproval => String::from("1010"), + Self::Cipher_Created => String::from("1100"), + Self::Cipher_Updated => String::from("1101"), + Self::Cipher_Deleted => String::from("1102"), + Self::Cipher_AttachmentCreated => String::from("1103"), + Self::Cipher_AttachmentDeleted => String::from("1104"), + Self::Cipher_Shared => String::from("1105"), + Self::Cipher_UpdatedCollections => String::from("1106"), + Self::Cipher_ClientViewed => String::from("1107"), + Self::Cipher_ClientToggledPasswordVisible => String::from("1108"), + Self::Cipher_ClientToggledHiddenFieldVisible => String::from("1109"), + Self::Cipher_ClientToggledCardCodeVisible => String::from("1110"), + Self::Cipher_ClientCopiedPassword => String::from("1111"), + Self::Cipher_ClientCopiedHiddenField => String::from("1112"), + Self::Cipher_ClientCopiedCardCode => String::from("1113"), + Self::Cipher_ClientAutofilled => String::from("1114"), + Self::Cipher_SoftDeleted => String::from("1115"), + Self::Cipher_Restored => String::from("1116"), + Self::Cipher_ClientToggledCardNumberVisible => String::from("1117"), + Self::Collection_Created => String::from("1300"), + Self::Collection_Updated => String::from("1301"), + Self::Collection_Deleted => String::from("1302"), + Self::Group_Created => String::from("1400"), + Self::Group_Updated => String::from("1401"), + Self::Group_Deleted => String::from("1402"), + Self::OrganizationUser_Invited => String::from("1500"), + Self::OrganizationUser_Confirmed => String::from("1501"), + Self::OrganizationUser_Updated => String::from("1502"), + Self::OrganizationUser_Removed => String::from("1503"), + Self::OrganizationUser_UpdatedGroups => String::from("1504"), + Self::OrganizationUser_UnlinkedSso => String::from("1505"), + Self::OrganizationUser_ResetPassword_Enroll => String::from("1506"), + Self::OrganizationUser_ResetPassword_Withdraw => String::from("1507"), + Self::OrganizationUser_AdminResetPassword => String::from("1508"), + Self::OrganizationUser_ResetSsoLink => String::from("1509"), + Self::OrganizationUser_FirstSsoLogin => String::from("1510"), + Self::OrganizationUser_Revoked => String::from("1511"), + Self::OrganizationUser_Restored => String::from("1512"), + Self::OrganizationUser_ApprovedAuthRequest => String::from("1513"), + Self::OrganizationUser_RejectedAuthRequest => String::from("1514"), + Self::Organization_Updated => String::from("1600"), + Self::Organization_PurgedVault => String::from("1601"), + Self::Organization_ClientExportedVault => String::from("1602"), + Self::Organization_VaultAccessed => String::from("1603"), + Self::Organization_EnabledSso => String::from("1604"), + Self::Organization_DisabledSso => String::from("1605"), + Self::Organization_EnabledKeyConnector => String::from("1606"), + Self::Organization_DisabledKeyConnector => String::from("1607"), + Self::Organization_SponsorshipsSynced => String::from("1608"), + Self::Organization_CollectionManagement_Updated => String::from("1609"), + Self::Policy_Updated => String::from("1700"), + Self::ProviderUser_Invited => String::from("1800"), + Self::ProviderUser_Confirmed => String::from("1801"), + Self::ProviderUser_Updated => String::from("1802"), + Self::ProviderUser_Removed => String::from("1803"), + Self::ProviderOrganization_Created => String::from("1900"), + Self::ProviderOrganization_Added => String::from("1901"), + Self::ProviderOrganization_Removed => String::from("1902"), + Self::ProviderOrganization_VaultAccessed => String::from("1903"), + Self::OrganizationDomain_Added => String::from("2000"), + Self::OrganizationDomain_Removed => String::from("2001"), + Self::OrganizationDomain_Verified => String::from("2002"), + Self::OrganizationDomain_NotVerified => String::from("2003"), + Self::Secret_Retrieved => String::from("2100"), } } } impl Default for EventType { fn default() -> EventType { - Self::Variant1000 + Self::User_LoggedIn } } diff --git a/crates/bitwarden-api-api/src/models/field_type.rs b/crates/bitwarden-api-api/src/models/field_type.rs index fbaa9b728..3a6209399 100644 --- a/crates/bitwarden-api-api/src/models/field_type.rs +++ b/crates/bitwarden-api-api/src/models/field_type.rs @@ -14,25 +14,25 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum FieldType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, + Text = 0, + Hidden = 1, + Boolean = 2, + Linked = 3, } impl ToString for FieldType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), + Self::Text => String::from("0"), + Self::Hidden => String::from("1"), + Self::Boolean => String::from("2"), + Self::Linked => String::from("3"), } } } impl Default for FieldType { fn default() -> FieldType { - Self::Variant0 + Self::Text } } diff --git a/crates/bitwarden-api-api/src/models/file_upload_type.rs b/crates/bitwarden-api-api/src/models/file_upload_type.rs index 765bc7563..79327b3cb 100644 --- a/crates/bitwarden-api-api/src/models/file_upload_type.rs +++ b/crates/bitwarden-api-api/src/models/file_upload_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum FileUploadType { - Variant0 = 0, - Variant1 = 1, + Direct = 0, + Azure = 1, } impl ToString for FileUploadType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::Direct => String::from("0"), + Self::Azure => String::from("1"), } } } impl Default for FileUploadType { fn default() -> FileUploadType { - Self::Variant0 + Self::Direct } } diff --git a/crates/bitwarden-api-api/src/models/global_equivalent_domains_type.rs b/crates/bitwarden-api-api/src/models/global_equivalent_domains_type.rs index f5e1c3655..f30b2d5e7 100644 --- a/crates/bitwarden-api-api/src/models/global_equivalent_domains_type.rs +++ b/crates/bitwarden-api-api/src/models/global_equivalent_domains_type.rs @@ -14,199 +14,199 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum GlobalEquivalentDomainsType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, - Variant9 = 9, - Variant10 = 10, - Variant11 = 11, - Variant12 = 12, - Variant13 = 13, - Variant14 = 14, - Variant15 = 15, - Variant16 = 16, - Variant17 = 17, - Variant18 = 18, - Variant19 = 19, - Variant20 = 20, - Variant21 = 21, - Variant22 = 22, - Variant23 = 23, - Variant24 = 24, - Variant25 = 25, - Variant26 = 26, - Variant27 = 27, - Variant28 = 28, - Variant29 = 29, - Variant30 = 30, - Variant31 = 31, - Variant32 = 32, - Variant33 = 33, - Variant34 = 34, - Variant35 = 35, - Variant36 = 36, - Variant37 = 37, - Variant38 = 38, - Variant39 = 39, - Variant40 = 40, - Variant41 = 41, - Variant42 = 42, - Variant43 = 43, - Variant44 = 44, - Variant45 = 45, - Variant46 = 46, - Variant47 = 47, - Variant48 = 48, - Variant49 = 49, - Variant50 = 50, - Variant51 = 51, - Variant52 = 52, - Variant53 = 53, - Variant54 = 54, - Variant55 = 55, - Variant56 = 56, - Variant57 = 57, - Variant58 = 58, - Variant59 = 59, - Variant60 = 60, - Variant61 = 61, - Variant62 = 62, - Variant63 = 63, - Variant64 = 64, - Variant65 = 65, - Variant66 = 66, - Variant67 = 67, - Variant68 = 68, - Variant69 = 69, - Variant70 = 70, - Variant71 = 71, - Variant72 = 72, - Variant73 = 73, - Variant74 = 74, - Variant75 = 75, - Variant76 = 76, - Variant77 = 77, - Variant78 = 78, - Variant79 = 79, - Variant80 = 80, - Variant81 = 81, - Variant82 = 82, - Variant83 = 83, - Variant84 = 84, - Variant85 = 85, - Variant86 = 86, - Variant87 = 87, - Variant88 = 88, - Variant89 = 89, - Variant90 = 90, + Google = 0, + Apple = 1, + Ameritrade = 2, + BoA = 3, + Sprint = 4, + WellsFargo = 5, + Merrill = 6, + Citi = 7, + Cnet = 8, + Gap = 9, + Microsoft = 10, + United = 11, + Yahoo = 12, + Zonelabs = 13, + PayPal = 14, + Avon = 15, + Diapers = 16, + Contacts = 17, + Amazon = 18, + Cox = 19, + Norton = 20, + Verizon = 21, + Buy = 22, + Sirius = 23, + Ea = 24, + Basecamp = 25, + Steam = 26, + Chart = 27, + Gotomeeting = 28, + Gogo = 29, + Oracle = 30, + Discover = 31, + Dcu = 32, + Healthcare = 33, + Pepco = 34, + Century21 = 35, + Comcast = 36, + Cricket = 37, + Mtb = 38, + Dropbox = 39, + Snapfish = 40, + Alibaba = 41, + Playstation = 42, + Mercado = 43, + Zendesk = 44, + Autodesk = 45, + RailNation = 46, + Wpcu = 47, + Mathletics = 48, + Discountbank = 49, + Mi = 50, + Facebook = 51, + Postepay = 52, + Skysports = 53, + Disney = 54, + Pokemon = 55, + Uv = 56, + Yahavo = 57, + Mdsol = 58, + Sears = 59, + Xiami = 60, + Belkin = 61, + Turbotax = 62, + Shopify = 63, + Ebay = 64, + Techdata = 65, + Schwab = 66, + Mozilla = 67, + Tesla = 68, + MorganStanley = 69, + TaxAct = 70, + Wikimedia = 71, + Airbnb = 72, + Eventbrite = 73, + StackExchange = 74, + Docusign = 75, + Envato = 76, + X10Hosting = 77, + Cisco = 78, + CedarFair = 79, + Ubiquiti = 80, + Discord = 81, + Netcup = 82, + Yandex = 83, + Sony = 84, + Proton = 85, + Ubisoft = 86, + TransferWise = 87, + TakeawayEU = 88, + Atlassian = 89, + Pinterest = 90, } impl ToString for GlobalEquivalentDomainsType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), - Self::Variant9 => String::from("9"), - Self::Variant10 => String::from("10"), - Self::Variant11 => String::from("11"), - Self::Variant12 => String::from("12"), - Self::Variant13 => String::from("13"), - Self::Variant14 => String::from("14"), - Self::Variant15 => String::from("15"), - Self::Variant16 => String::from("16"), - Self::Variant17 => String::from("17"), - Self::Variant18 => String::from("18"), - Self::Variant19 => String::from("19"), - Self::Variant20 => String::from("20"), - Self::Variant21 => String::from("21"), - Self::Variant22 => String::from("22"), - Self::Variant23 => String::from("23"), - Self::Variant24 => String::from("24"), - Self::Variant25 => String::from("25"), - Self::Variant26 => String::from("26"), - Self::Variant27 => String::from("27"), - Self::Variant28 => String::from("28"), - Self::Variant29 => String::from("29"), - Self::Variant30 => String::from("30"), - Self::Variant31 => String::from("31"), - Self::Variant32 => String::from("32"), - Self::Variant33 => String::from("33"), - Self::Variant34 => String::from("34"), - Self::Variant35 => String::from("35"), - Self::Variant36 => String::from("36"), - Self::Variant37 => String::from("37"), - Self::Variant38 => String::from("38"), - Self::Variant39 => String::from("39"), - Self::Variant40 => String::from("40"), - Self::Variant41 => String::from("41"), - Self::Variant42 => String::from("42"), - Self::Variant43 => String::from("43"), - Self::Variant44 => String::from("44"), - Self::Variant45 => String::from("45"), - Self::Variant46 => String::from("46"), - Self::Variant47 => String::from("47"), - Self::Variant48 => String::from("48"), - Self::Variant49 => String::from("49"), - Self::Variant50 => String::from("50"), - Self::Variant51 => String::from("51"), - Self::Variant52 => String::from("52"), - Self::Variant53 => String::from("53"), - Self::Variant54 => String::from("54"), - Self::Variant55 => String::from("55"), - Self::Variant56 => String::from("56"), - Self::Variant57 => String::from("57"), - Self::Variant58 => String::from("58"), - Self::Variant59 => String::from("59"), - Self::Variant60 => String::from("60"), - Self::Variant61 => String::from("61"), - Self::Variant62 => String::from("62"), - Self::Variant63 => String::from("63"), - Self::Variant64 => String::from("64"), - Self::Variant65 => String::from("65"), - Self::Variant66 => String::from("66"), - Self::Variant67 => String::from("67"), - Self::Variant68 => String::from("68"), - Self::Variant69 => String::from("69"), - Self::Variant70 => String::from("70"), - Self::Variant71 => String::from("71"), - Self::Variant72 => String::from("72"), - Self::Variant73 => String::from("73"), - Self::Variant74 => String::from("74"), - Self::Variant75 => String::from("75"), - Self::Variant76 => String::from("76"), - Self::Variant77 => String::from("77"), - Self::Variant78 => String::from("78"), - Self::Variant79 => String::from("79"), - Self::Variant80 => String::from("80"), - Self::Variant81 => String::from("81"), - Self::Variant82 => String::from("82"), - Self::Variant83 => String::from("83"), - Self::Variant84 => String::from("84"), - Self::Variant85 => String::from("85"), - Self::Variant86 => String::from("86"), - Self::Variant87 => String::from("87"), - Self::Variant88 => String::from("88"), - Self::Variant89 => String::from("89"), - Self::Variant90 => String::from("90"), + Self::Google => String::from("0"), + Self::Apple => String::from("1"), + Self::Ameritrade => String::from("2"), + Self::BoA => String::from("3"), + Self::Sprint => String::from("4"), + Self::WellsFargo => String::from("5"), + Self::Merrill => String::from("6"), + Self::Citi => String::from("7"), + Self::Cnet => String::from("8"), + Self::Gap => String::from("9"), + Self::Microsoft => String::from("10"), + Self::United => String::from("11"), + Self::Yahoo => String::from("12"), + Self::Zonelabs => String::from("13"), + Self::PayPal => String::from("14"), + Self::Avon => String::from("15"), + Self::Diapers => String::from("16"), + Self::Contacts => String::from("17"), + Self::Amazon => String::from("18"), + Self::Cox => String::from("19"), + Self::Norton => String::from("20"), + Self::Verizon => String::from("21"), + Self::Buy => String::from("22"), + Self::Sirius => String::from("23"), + Self::Ea => String::from("24"), + Self::Basecamp => String::from("25"), + Self::Steam => String::from("26"), + Self::Chart => String::from("27"), + Self::Gotomeeting => String::from("28"), + Self::Gogo => String::from("29"), + Self::Oracle => String::from("30"), + Self::Discover => String::from("31"), + Self::Dcu => String::from("32"), + Self::Healthcare => String::from("33"), + Self::Pepco => String::from("34"), + Self::Century21 => String::from("35"), + Self::Comcast => String::from("36"), + Self::Cricket => String::from("37"), + Self::Mtb => String::from("38"), + Self::Dropbox => String::from("39"), + Self::Snapfish => String::from("40"), + Self::Alibaba => String::from("41"), + Self::Playstation => String::from("42"), + Self::Mercado => String::from("43"), + Self::Zendesk => String::from("44"), + Self::Autodesk => String::from("45"), + Self::RailNation => String::from("46"), + Self::Wpcu => String::from("47"), + Self::Mathletics => String::from("48"), + Self::Discountbank => String::from("49"), + Self::Mi => String::from("50"), + Self::Facebook => String::from("51"), + Self::Postepay => String::from("52"), + Self::Skysports => String::from("53"), + Self::Disney => String::from("54"), + Self::Pokemon => String::from("55"), + Self::Uv => String::from("56"), + Self::Yahavo => String::from("57"), + Self::Mdsol => String::from("58"), + Self::Sears => String::from("59"), + Self::Xiami => String::from("60"), + Self::Belkin => String::from("61"), + Self::Turbotax => String::from("62"), + Self::Shopify => String::from("63"), + Self::Ebay => String::from("64"), + Self::Techdata => String::from("65"), + Self::Schwab => String::from("66"), + Self::Mozilla => String::from("67"), + Self::Tesla => String::from("68"), + Self::MorganStanley => String::from("69"), + Self::TaxAct => String::from("70"), + Self::Wikimedia => String::from("71"), + Self::Airbnb => String::from("72"), + Self::Eventbrite => String::from("73"), + Self::StackExchange => String::from("74"), + Self::Docusign => String::from("75"), + Self::Envato => String::from("76"), + Self::X10Hosting => String::from("77"), + Self::Cisco => String::from("78"), + Self::CedarFair => String::from("79"), + Self::Ubiquiti => String::from("80"), + Self::Discord => String::from("81"), + Self::Netcup => String::from("82"), + Self::Yandex => String::from("83"), + Self::Sony => String::from("84"), + Self::Proton => String::from("85"), + Self::Ubisoft => String::from("86"), + Self::TransferWise => String::from("87"), + Self::TakeawayEU => String::from("88"), + Self::Atlassian => String::from("89"), + Self::Pinterest => String::from("90"), } } } impl Default for GlobalEquivalentDomainsType { fn default() -> GlobalEquivalentDomainsType { - Self::Variant0 + Self::Google } } diff --git a/crates/bitwarden-api-api/src/models/iap_check_request_model.rs b/crates/bitwarden-api-api/src/models/iap_check_request_model.rs deleted file mode 100644 index f18b4b017..000000000 --- a/crates/bitwarden-api-api/src/models/iap_check_request_model.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct IapCheckRequestModel { - #[serde(rename = "paymentMethodType")] - pub payment_method_type: crate::models::PaymentMethodType, -} - -impl IapCheckRequestModel { - pub fn new(payment_method_type: crate::models::PaymentMethodType) -> IapCheckRequestModel { - IapCheckRequestModel { - payment_method_type, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/inner_project.rs b/crates/bitwarden-api-api/src/models/inner_project.rs deleted file mode 100644 index 59ecb7f07..000000000 --- a/crates/bitwarden-api-api/src/models/inner_project.rs +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct InnerProject { - #[serde(rename = "id", skip_serializing_if = "Option::is_none")] - pub id: Option, - #[serde(rename = "name", skip_serializing_if = "Option::is_none")] - pub name: Option, -} - -impl InnerProject { - pub fn new() -> InnerProject { - InnerProject { - id: None, - name: None, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/inner_secret.rs b/crates/bitwarden-api-api/src/models/inner_secret.rs deleted file mode 100644 index 43deb0f1a..000000000 --- a/crates/bitwarden-api-api/src/models/inner_secret.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct InnerSecret { - #[serde(rename = "id", skip_serializing_if = "Option::is_none")] - pub id: Option, - #[serde(rename = "organizationId", skip_serializing_if = "Option::is_none")] - pub organization_id: Option, - #[serde(rename = "key", skip_serializing_if = "Option::is_none")] - pub key: Option, - #[serde(rename = "creationDate", skip_serializing_if = "Option::is_none")] - pub creation_date: Option, - #[serde(rename = "revisionDate", skip_serializing_if = "Option::is_none")] - pub revision_date: Option, - #[serde(rename = "projects", skip_serializing_if = "Option::is_none")] - pub projects: Option>, - #[serde(rename = "read", skip_serializing_if = "Option::is_none")] - pub read: Option, - #[serde(rename = "write", skip_serializing_if = "Option::is_none")] - pub write: Option, -} - -impl InnerSecret { - pub fn new() -> InnerSecret { - InnerSecret { - id: None, - organization_id: None, - key: None, - creation_date: None, - revision_date: None, - projects: None, - read: None, - write: None, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/kdf_type.rs b/crates/bitwarden-api-api/src/models/kdf_type.rs index 83b611680..e371ee156 100644 --- a/crates/bitwarden-api-api/src/models/kdf_type.rs +++ b/crates/bitwarden-api-api/src/models/kdf_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum KdfType { - Variant0 = 0, - Variant1 = 1, + PBKDF2_SHA256 = 0, + Argon2id = 1, } impl ToString for KdfType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::PBKDF2_SHA256 => String::from("0"), + Self::Argon2id => String::from("1"), } } } impl Default for KdfType { fn default() -> KdfType { - Self::Variant0 + Self::PBKDF2_SHA256 } } diff --git a/crates/bitwarden-api-api/src/models/license_type.rs b/crates/bitwarden-api-api/src/models/license_type.rs index 0f887fa79..178b3433f 100644 --- a/crates/bitwarden-api-api/src/models/license_type.rs +++ b/crates/bitwarden-api-api/src/models/license_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum LicenseType { - Variant0 = 0, - Variant1 = 1, + User = 0, + Organization = 1, } impl ToString for LicenseType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::User => String::from("0"), + Self::Organization => String::from("1"), } } } impl Default for LicenseType { fn default() -> LicenseType { - Self::Variant0 + Self::User } } diff --git a/crates/bitwarden-api-api/src/models/member_decryption_type.rs b/crates/bitwarden-api-api/src/models/member_decryption_type.rs index e36344a9f..dba1b793b 100644 --- a/crates/bitwarden-api-api/src/models/member_decryption_type.rs +++ b/crates/bitwarden-api-api/src/models/member_decryption_type.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum MemberDecryptionType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, + MasterPassword = 0, + KeyConnector = 1, + TrustedDeviceEncryption = 2, } impl ToString for MemberDecryptionType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::MasterPassword => String::from("0"), + Self::KeyConnector => String::from("1"), + Self::TrustedDeviceEncryption => String::from("2"), } } } impl Default for MemberDecryptionType { fn default() -> MemberDecryptionType { - Self::Variant0 + Self::MasterPassword } } diff --git a/crates/bitwarden-api-api/src/models/open_id_connect_redirect_behavior.rs b/crates/bitwarden-api-api/src/models/open_id_connect_redirect_behavior.rs index 73fb93eb8..792a2dd9e 100644 --- a/crates/bitwarden-api-api/src/models/open_id_connect_redirect_behavior.rs +++ b/crates/bitwarden-api-api/src/models/open_id_connect_redirect_behavior.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum OpenIdConnectRedirectBehavior { - Variant0 = 0, - Variant1 = 1, + RedirectGet = 0, + FormPost = 1, } impl ToString for OpenIdConnectRedirectBehavior { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::RedirectGet => String::from("0"), + Self::FormPost => String::from("1"), } } } impl Default for OpenIdConnectRedirectBehavior { fn default() -> OpenIdConnectRedirectBehavior { - Self::Variant0 + Self::RedirectGet } } diff --git a/crates/bitwarden-api-api/src/models/organization_api_key_type.rs b/crates/bitwarden-api-api/src/models/organization_api_key_type.rs index 4790406e5..83f76baaa 100644 --- a/crates/bitwarden-api-api/src/models/organization_api_key_type.rs +++ b/crates/bitwarden-api-api/src/models/organization_api_key_type.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum OrganizationApiKeyType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, + Default = 0, + BillingSync = 1, + Scim = 2, } impl ToString for OrganizationApiKeyType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::Default => String::from("0"), + Self::BillingSync => String::from("1"), + Self::Scim => String::from("2"), } } } impl Default for OrganizationApiKeyType { fn default() -> OrganizationApiKeyType { - Self::Variant0 + Self::Default } } diff --git a/crates/bitwarden-api-api/src/models/organization_connection_type.rs b/crates/bitwarden-api-api/src/models/organization_connection_type.rs index eddf5460c..201c03ed2 100644 --- a/crates/bitwarden-api-api/src/models/organization_connection_type.rs +++ b/crates/bitwarden-api-api/src/models/organization_connection_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum OrganizationConnectionType { - Variant1 = 1, - Variant2 = 2, + CloudBillingSync = 1, + Scim = 2, } impl ToString for OrganizationConnectionType { fn to_string(&self) -> String { match self { - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::CloudBillingSync => String::from("1"), + Self::Scim => String::from("2"), } } } impl Default for OrganizationConnectionType { fn default() -> OrganizationConnectionType { - Self::Variant1 + Self::CloudBillingSync } } diff --git a/crates/bitwarden-api-api/src/models/organization_enroll_secrets_manager_request_model.rs b/crates/bitwarden-api-api/src/models/organization_enroll_secrets_manager_request_model.rs deleted file mode 100644 index 16c34a3c5..000000000 --- a/crates/bitwarden-api-api/src/models/organization_enroll_secrets_manager_request_model.rs +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct OrganizationEnrollSecretsManagerRequestModel { - #[serde(rename = "enabled", skip_serializing_if = "Option::is_none")] - pub enabled: Option, -} - -impl OrganizationEnrollSecretsManagerRequestModel { - pub fn new() -> OrganizationEnrollSecretsManagerRequestModel { - OrganizationEnrollSecretsManagerRequestModel { enabled: None } - } -} diff --git a/crates/bitwarden-api-api/src/models/organization_user_status_type.rs b/crates/bitwarden-api-api/src/models/organization_user_status_type.rs index 7486cab57..5d3c99199 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_status_type.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_status_type.rs @@ -14,25 +14,25 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum OrganizationUserStatusType { - _0 = 0, - _1 = 1, - _2 = 2, - __1 = -1, + Invited = 0, + Accepted = 1, + Confirmed = 2, + Revoked = -1, } impl ToString for OrganizationUserStatusType { fn to_string(&self) -> String { match self { - Self::_0 => String::from("0"), - Self::_1 => String::from("1"), - Self::_2 => String::from("2"), - Self::__1 => String::from("-1"), + Self::Invited => String::from("0"), + Self::Accepted => String::from("1"), + Self::Confirmed => String::from("2"), + Self::Revoked => String::from("-1"), } } } impl Default for OrganizationUserStatusType { fn default() -> OrganizationUserStatusType { - Self::_0 + Self::Invited } } diff --git a/crates/bitwarden-api-api/src/models/organization_user_type.rs b/crates/bitwarden-api-api/src/models/organization_user_type.rs index e3642946d..38e415f05 100644 --- a/crates/bitwarden-api-api/src/models/organization_user_type.rs +++ b/crates/bitwarden-api-api/src/models/organization_user_type.rs @@ -14,27 +14,27 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum OrganizationUserType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, + Owner = 0, + Admin = 1, + User = 2, + Manager = 3, + Custom = 4, } impl ToString for OrganizationUserType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), + Self::Owner => String::from("0"), + Self::Admin => String::from("1"), + Self::User => String::from("2"), + Self::Manager => String::from("3"), + Self::Custom => String::from("4"), } } } impl Default for OrganizationUserType { fn default() -> OrganizationUserType { - Self::Variant0 + Self::Owner } } diff --git a/crates/bitwarden-api-api/src/models/payment_method_type.rs b/crates/bitwarden-api-api/src/models/payment_method_type.rs index 8df2830a4..c4d6cf93c 100644 --- a/crates/bitwarden-api-api/src/models/payment_method_type.rs +++ b/crates/bitwarden-api-api/src/models/payment_method_type.rs @@ -14,33 +14,33 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum PaymentMethodType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant8 = 8, - Variant255 = 255, + Card = 0, + BankAccount = 1, + PayPal = 2, + BitPay = 3, + Credit = 4, + WireTransfer = 5, + Check = 8, + None = 255, } impl ToString for PaymentMethodType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant8 => String::from("8"), - Self::Variant255 => String::from("255"), + Self::Card => String::from("0"), + Self::BankAccount => String::from("1"), + Self::PayPal => String::from("2"), + Self::BitPay => String::from("3"), + Self::Credit => String::from("4"), + Self::WireTransfer => String::from("5"), + Self::Check => String::from("8"), + Self::None => String::from("255"), } } } impl Default for PaymentMethodType { fn default() -> PaymentMethodType { - Self::Variant0 + Self::Card } } diff --git a/crates/bitwarden-api-api/src/models/plan_sponsorship_type.rs b/crates/bitwarden-api-api/src/models/plan_sponsorship_type.rs index 5e2a55824..02a750f3d 100644 --- a/crates/bitwarden-api-api/src/models/plan_sponsorship_type.rs +++ b/crates/bitwarden-api-api/src/models/plan_sponsorship_type.rs @@ -14,19 +14,19 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum PlanSponsorshipType { - Variant0 = 0, + FamiliesForEnterprise = 0, } impl ToString for PlanSponsorshipType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), + Self::FamiliesForEnterprise => String::from("0"), } } } impl Default for PlanSponsorshipType { fn default() -> PlanSponsorshipType { - Self::Variant0 + Self::FamiliesForEnterprise } } diff --git a/crates/bitwarden-api-api/src/models/plan_type.rs b/crates/bitwarden-api-api/src/models/plan_type.rs index a43634b19..109e9250e 100644 --- a/crates/bitwarden-api-api/src/models/plan_type.rs +++ b/crates/bitwarden-api-api/src/models/plan_type.rs @@ -14,51 +14,51 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum PlanType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, - Variant9 = 9, - Variant10 = 10, - Variant11 = 11, - Variant12 = 12, - Variant13 = 13, - Variant14 = 14, - Variant15 = 15, - Variant16 = 16, + Free = 0, + FamiliesAnnually2019 = 1, + TeamsMonthly2019 = 2, + TeamsAnnually2019 = 3, + EnterpriseMonthly2019 = 4, + EnterpriseAnnually2019 = 5, + Custom = 6, + FamiliesAnnually = 7, + TeamsMonthly2020 = 8, + TeamsAnnually2020 = 9, + EnterpriseMonthly2020 = 10, + EnterpriseAnnually2020 = 11, + TeamsMonthly = 12, + TeamsAnnually = 13, + EnterpriseMonthly = 14, + EnterpriseAnnually = 15, + TeamsStarter = 16, } impl ToString for PlanType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), - Self::Variant9 => String::from("9"), - Self::Variant10 => String::from("10"), - Self::Variant11 => String::from("11"), - Self::Variant12 => String::from("12"), - Self::Variant13 => String::from("13"), - Self::Variant14 => String::from("14"), - Self::Variant15 => String::from("15"), - Self::Variant16 => String::from("16"), + Self::Free => String::from("0"), + Self::FamiliesAnnually2019 => String::from("1"), + Self::TeamsMonthly2019 => String::from("2"), + Self::TeamsAnnually2019 => String::from("3"), + Self::EnterpriseMonthly2019 => String::from("4"), + Self::EnterpriseAnnually2019 => String::from("5"), + Self::Custom => String::from("6"), + Self::FamiliesAnnually => String::from("7"), + Self::TeamsMonthly2020 => String::from("8"), + Self::TeamsAnnually2020 => String::from("9"), + Self::EnterpriseMonthly2020 => String::from("10"), + Self::EnterpriseAnnually2020 => String::from("11"), + Self::TeamsMonthly => String::from("12"), + Self::TeamsAnnually => String::from("13"), + Self::EnterpriseMonthly => String::from("14"), + Self::EnterpriseAnnually => String::from("15"), + Self::TeamsStarter => String::from("16"), } } } impl Default for PlanType { fn default() -> PlanType { - Self::Variant0 + Self::Free } } diff --git a/crates/bitwarden-api-api/src/models/policy_type.rs b/crates/bitwarden-api-api/src/models/policy_type.rs index dbb186a21..fc9e6ca63 100644 --- a/crates/bitwarden-api-api/src/models/policy_type.rs +++ b/crates/bitwarden-api-api/src/models/policy_type.rs @@ -14,41 +14,41 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum PolicyType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, - Variant9 = 9, - Variant10 = 10, - Variant11 = 11, + TwoFactorAuthentication = 0, + MasterPassword = 1, + PasswordGenerator = 2, + SingleOrg = 3, + RequireSso = 4, + PersonalOwnership = 5, + DisableSend = 6, + SendOptions = 7, + ResetPassword = 8, + MaximumVaultTimeout = 9, + DisablePersonalVaultExport = 10, + ActivateAutofill = 11, } impl ToString for PolicyType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), - Self::Variant9 => String::from("9"), - Self::Variant10 => String::from("10"), - Self::Variant11 => String::from("11"), + Self::TwoFactorAuthentication => String::from("0"), + Self::MasterPassword => String::from("1"), + Self::PasswordGenerator => String::from("2"), + Self::SingleOrg => String::from("3"), + Self::RequireSso => String::from("4"), + Self::PersonalOwnership => String::from("5"), + Self::DisableSend => String::from("6"), + Self::SendOptions => String::from("7"), + Self::ResetPassword => String::from("8"), + Self::MaximumVaultTimeout => String::from("9"), + Self::DisablePersonalVaultExport => String::from("10"), + Self::ActivateAutofill => String::from("11"), } } } impl Default for PolicyType { fn default() -> PolicyType { - Self::Variant0 + Self::TwoFactorAuthentication } } diff --git a/crates/bitwarden-api-api/src/models/product_type.rs b/crates/bitwarden-api-api/src/models/product_type.rs index aa4ebedc5..e60a9c57c 100644 --- a/crates/bitwarden-api-api/src/models/product_type.rs +++ b/crates/bitwarden-api-api/src/models/product_type.rs @@ -14,27 +14,27 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum ProductType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, + Free = 0, + Families = 1, + Teams = 2, + Enterprise = 3, + TeamsStarter = 4, } impl ToString for ProductType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), + Self::Free => String::from("0"), + Self::Families => String::from("1"), + Self::Teams => String::from("2"), + Self::Enterprise => String::from("3"), + Self::TeamsStarter => String::from("4"), } } } impl Default for ProductType { fn default() -> ProductType { - Self::Variant0 + Self::Free } } diff --git a/crates/bitwarden-api-api/src/models/provider_type.rs b/crates/bitwarden-api-api/src/models/provider_type.rs index 340210d32..f2d30a6cd 100644 --- a/crates/bitwarden-api-api/src/models/provider_type.rs +++ b/crates/bitwarden-api-api/src/models/provider_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum ProviderType { - Variant0 = 0, - Variant1 = 1, + Msp = 0, + Reseller = 1, } impl ToString for ProviderType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::Msp => String::from("0"), + Self::Reseller => String::from("1"), } } } impl Default for ProviderType { fn default() -> ProviderType { - Self::Variant0 + Self::Msp } } diff --git a/crates/bitwarden-api-api/src/models/provider_user_status_type.rs b/crates/bitwarden-api-api/src/models/provider_user_status_type.rs index 0918fe1d6..653dabbeb 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_status_type.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_status_type.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum ProviderUserStatusType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, + Invited = 0, + Accepted = 1, + Confirmed = 2, } impl ToString for ProviderUserStatusType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::Invited => String::from("0"), + Self::Accepted => String::from("1"), + Self::Confirmed => String::from("2"), } } } impl Default for ProviderUserStatusType { fn default() -> ProviderUserStatusType { - Self::Variant0 + Self::Invited } } diff --git a/crates/bitwarden-api-api/src/models/provider_user_type.rs b/crates/bitwarden-api-api/src/models/provider_user_type.rs index 28b130f8d..c51a3b932 100644 --- a/crates/bitwarden-api-api/src/models/provider_user_type.rs +++ b/crates/bitwarden-api-api/src/models/provider_user_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum ProviderUserType { - Variant0 = 0, - Variant1 = 1, + ProviderAdmin = 0, + ServiceUser = 1, } impl ToString for ProviderUserType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::ProviderAdmin => String::from("0"), + Self::ServiceUser => String::from("1"), } } } impl Default for ProviderUserType { fn default() -> ProviderUserType { - Self::Variant0 + Self::ProviderAdmin } } diff --git a/crates/bitwarden-api-api/src/models/push_type.rs b/crates/bitwarden-api-api/src/models/push_type.rs index fe38f85a7..8e69b5a73 100644 --- a/crates/bitwarden-api-api/src/models/push_type.rs +++ b/crates/bitwarden-api-api/src/models/push_type.rs @@ -14,51 +14,51 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum PushType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, - Variant9 = 9, - Variant10 = 10, - Variant11 = 11, - Variant12 = 12, - Variant13 = 13, - Variant14 = 14, - Variant15 = 15, - Variant16 = 16, + SyncCipherUpdate = 0, + SyncCipherCreate = 1, + SyncLoginDelete = 2, + SyncFolderDelete = 3, + SyncCiphers = 4, + SyncVault = 5, + SyncOrgKeys = 6, + SyncFolderCreate = 7, + SyncFolderUpdate = 8, + SyncCipherDelete = 9, + SyncSettings = 10, + LogOut = 11, + SyncSendCreate = 12, + SyncSendUpdate = 13, + SyncSendDelete = 14, + AuthRequest = 15, + AuthRequestResponse = 16, } impl ToString for PushType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), - Self::Variant9 => String::from("9"), - Self::Variant10 => String::from("10"), - Self::Variant11 => String::from("11"), - Self::Variant12 => String::from("12"), - Self::Variant13 => String::from("13"), - Self::Variant14 => String::from("14"), - Self::Variant15 => String::from("15"), - Self::Variant16 => String::from("16"), + Self::SyncCipherUpdate => String::from("0"), + Self::SyncCipherCreate => String::from("1"), + Self::SyncLoginDelete => String::from("2"), + Self::SyncFolderDelete => String::from("3"), + Self::SyncCiphers => String::from("4"), + Self::SyncVault => String::from("5"), + Self::SyncOrgKeys => String::from("6"), + Self::SyncFolderCreate => String::from("7"), + Self::SyncFolderUpdate => String::from("8"), + Self::SyncCipherDelete => String::from("9"), + Self::SyncSettings => String::from("10"), + Self::LogOut => String::from("11"), + Self::SyncSendCreate => String::from("12"), + Self::SyncSendUpdate => String::from("13"), + Self::SyncSendDelete => String::from("14"), + Self::AuthRequest => String::from("15"), + Self::AuthRequestResponse => String::from("16"), } } } impl Default for PushType { fn default() -> PushType { - Self::Variant0 + Self::SyncCipherUpdate } } diff --git a/crates/bitwarden-api-api/src/models/saml2_binding_type.rs b/crates/bitwarden-api-api/src/models/saml2_binding_type.rs index 039309cad..e01b398cd 100644 --- a/crates/bitwarden-api-api/src/models/saml2_binding_type.rs +++ b/crates/bitwarden-api-api/src/models/saml2_binding_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum Saml2BindingType { - Variant1 = 1, - Variant2 = 2, + HttpRedirect = 1, + HttpPost = 2, } impl ToString for Saml2BindingType { fn to_string(&self) -> String { match self { - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::HttpRedirect => String::from("1"), + Self::HttpPost => String::from("2"), } } } impl Default for Saml2BindingType { fn default() -> Saml2BindingType { - Self::Variant1 + Self::HttpRedirect } } diff --git a/crates/bitwarden-api-api/src/models/saml2_name_id_format.rs b/crates/bitwarden-api-api/src/models/saml2_name_id_format.rs index 6399c7f9b..e8680e9a6 100644 --- a/crates/bitwarden-api-api/src/models/saml2_name_id_format.rs +++ b/crates/bitwarden-api-api/src/models/saml2_name_id_format.rs @@ -14,35 +14,35 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum Saml2NameIdFormat { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, - Variant8 = 8, + NotConfigured = 0, + Unspecified = 1, + EmailAddress = 2, + X509SubjectName = 3, + WindowsDomainQualifiedName = 4, + KerberosPrincipalName = 5, + EntityIdentifier = 6, + Persistent = 7, + Transient = 8, } impl ToString for Saml2NameIdFormat { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), - Self::Variant8 => String::from("8"), + Self::NotConfigured => String::from("0"), + Self::Unspecified => String::from("1"), + Self::EmailAddress => String::from("2"), + Self::X509SubjectName => String::from("3"), + Self::WindowsDomainQualifiedName => String::from("4"), + Self::KerberosPrincipalName => String::from("5"), + Self::EntityIdentifier => String::from("6"), + Self::Persistent => String::from("7"), + Self::Transient => String::from("8"), } } } impl Default for Saml2NameIdFormat { fn default() -> Saml2NameIdFormat { - Self::Variant0 + Self::NotConfigured } } diff --git a/crates/bitwarden-api-api/src/models/saml2_signing_behavior.rs b/crates/bitwarden-api-api/src/models/saml2_signing_behavior.rs index 3b0668865..12be578aa 100644 --- a/crates/bitwarden-api-api/src/models/saml2_signing_behavior.rs +++ b/crates/bitwarden-api-api/src/models/saml2_signing_behavior.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum Saml2SigningBehavior { - Variant0 = 0, - Variant1 = 1, - Variant3 = 3, + IfIdpWantAuthnRequestsSigned = 0, + Always = 1, + Never = 3, } impl ToString for Saml2SigningBehavior { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant3 => String::from("3"), + Self::IfIdpWantAuthnRequestsSigned => String::from("0"), + Self::Always => String::from("1"), + Self::Never => String::from("3"), } } } impl Default for Saml2SigningBehavior { fn default() -> Saml2SigningBehavior { - Self::Variant0 + Self::IfIdpWantAuthnRequestsSigned } } diff --git a/crates/bitwarden-api-api/src/models/secure_note_type.rs b/crates/bitwarden-api-api/src/models/secure_note_type.rs index 9fd0a3158..dd8516f6e 100644 --- a/crates/bitwarden-api-api/src/models/secure_note_type.rs +++ b/crates/bitwarden-api-api/src/models/secure_note_type.rs @@ -14,19 +14,19 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum SecureNoteType { - Variant0 = 0, + Generic = 0, } impl ToString for SecureNoteType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), + Self::Generic => String::from("0"), } } } impl Default for SecureNoteType { fn default() -> SecureNoteType { - Self::Variant0 + Self::Generic } } diff --git a/crates/bitwarden-api-api/src/models/send_type.rs b/crates/bitwarden-api-api/src/models/send_type.rs index 5ea1c2504..6364c4af2 100644 --- a/crates/bitwarden-api-api/src/models/send_type.rs +++ b/crates/bitwarden-api-api/src/models/send_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum SendType { - Variant0 = 0, - Variant1 = 1, + Text = 0, + File = 1, } impl ToString for SendType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::Text => String::from("0"), + Self::File => String::from("1"), } } } impl Default for SendType { fn default() -> SendType { - Self::Variant0 + Self::Text } } diff --git a/crates/bitwarden-api-api/src/models/service_account_access_policies_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_access_policies_response_model.rs deleted file mode 100644 index 22db48178..000000000 --- a/crates/bitwarden-api-api/src/models/service_account_access_policies_response_model.rs +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct ServiceAccountAccessPoliciesResponseModel { - #[serde(rename = "object", skip_serializing_if = "Option::is_none")] - pub object: Option, - #[serde(rename = "userAccessPolicies", skip_serializing_if = "Option::is_none")] - pub user_access_policies: - Option>, - #[serde( - rename = "groupAccessPolicies", - skip_serializing_if = "Option::is_none" - )] - pub group_access_policies: - Option>, -} - -impl ServiceAccountAccessPoliciesResponseModel { - pub fn new() -> ServiceAccountAccessPoliciesResponseModel { - ServiceAccountAccessPoliciesResponseModel { - object: None, - user_access_policies: None, - group_access_policies: None, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/service_account_response_model_list_response_model.rs b/crates/bitwarden-api-api/src/models/service_account_response_model_list_response_model.rs deleted file mode 100644 index 41ad4c28a..000000000 --- a/crates/bitwarden-api-api/src/models/service_account_response_model_list_response_model.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Bitwarden Internal API - * - * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) - * - * The version of the OpenAPI document: latest - * - * Generated by: https://openapi-generator.tech - */ - -#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)] -pub struct ServiceAccountResponseModelListResponseModel { - #[serde(rename = "object", skip_serializing_if = "Option::is_none")] - pub object: Option, - #[serde(rename = "data", skip_serializing_if = "Option::is_none")] - pub data: Option>, - #[serde(rename = "continuationToken", skip_serializing_if = "Option::is_none")] - pub continuation_token: Option, -} - -impl ServiceAccountResponseModelListResponseModel { - pub fn new() -> ServiceAccountResponseModelListResponseModel { - ServiceAccountResponseModelListResponseModel { - object: None, - data: None, - continuation_token: None, - } - } -} diff --git a/crates/bitwarden-api-api/src/models/sso_type.rs b/crates/bitwarden-api-api/src/models/sso_type.rs index 3e1aefa4d..9ff337676 100644 --- a/crates/bitwarden-api-api/src/models/sso_type.rs +++ b/crates/bitwarden-api-api/src/models/sso_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum SsoType { - Variant1 = 1, - Variant2 = 2, + OpenIdConnect = 1, + Saml2 = 2, } impl ToString for SsoType { fn to_string(&self) -> String { match self { - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::OpenIdConnect => String::from("1"), + Self::Saml2 => String::from("2"), } } } impl Default for SsoType { fn default() -> SsoType { - Self::Variant1 + Self::OpenIdConnect } } diff --git a/crates/bitwarden-api-api/src/models/transaction_type.rs b/crates/bitwarden-api-api/src/models/transaction_type.rs index c9cda7c76..1bb69ccbb 100644 --- a/crates/bitwarden-api-api/src/models/transaction_type.rs +++ b/crates/bitwarden-api-api/src/models/transaction_type.rs @@ -14,27 +14,27 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum TransactionType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, + Charge = 0, + Credit = 1, + PromotionalCredit = 2, + ReferralCredit = 3, + Refund = 4, } impl ToString for TransactionType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), + Self::Charge => String::from("0"), + Self::Credit => String::from("1"), + Self::PromotionalCredit => String::from("2"), + Self::ReferralCredit => String::from("3"), + Self::Refund => String::from("4"), } } } impl Default for TransactionType { fn default() -> TransactionType { - Self::Variant0 + Self::Charge } } diff --git a/crates/bitwarden-api-api/src/models/two_factor_provider_type.rs b/crates/bitwarden-api-api/src/models/two_factor_provider_type.rs index 00188f0fd..94d20ee2a 100644 --- a/crates/bitwarden-api-api/src/models/two_factor_provider_type.rs +++ b/crates/bitwarden-api-api/src/models/two_factor_provider_type.rs @@ -14,33 +14,33 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum TwoFactorProviderType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, - Variant6 = 6, - Variant7 = 7, + Authenticator = 0, + Email = 1, + Duo = 2, + YubiKey = 3, + U2f = 4, + Remember = 5, + OrganizationDuo = 6, + WebAuthn = 7, } impl ToString for TwoFactorProviderType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), - Self::Variant6 => String::from("6"), - Self::Variant7 => String::from("7"), + Self::Authenticator => String::from("0"), + Self::Email => String::from("1"), + Self::Duo => String::from("2"), + Self::YubiKey => String::from("3"), + Self::U2f => String::from("4"), + Self::Remember => String::from("5"), + Self::OrganizationDuo => String::from("6"), + Self::WebAuthn => String::from("7"), } } } impl Default for TwoFactorProviderType { fn default() -> TwoFactorProviderType { - Self::Variant0 + Self::Authenticator } } diff --git a/crates/bitwarden-api-api/src/models/uri_match_type.rs b/crates/bitwarden-api-api/src/models/uri_match_type.rs index f4ee450c1..6ccf82edb 100644 --- a/crates/bitwarden-api-api/src/models/uri_match_type.rs +++ b/crates/bitwarden-api-api/src/models/uri_match_type.rs @@ -14,29 +14,29 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum UriMatchType { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, - Variant3 = 3, - Variant4 = 4, - Variant5 = 5, + Domain = 0, + Host = 1, + StartsWith = 2, + Exact = 3, + RegularExpression = 4, + Never = 5, } impl ToString for UriMatchType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), - Self::Variant3 => String::from("3"), - Self::Variant4 => String::from("4"), - Self::Variant5 => String::from("5"), + Self::Domain => String::from("0"), + Self::Host => String::from("1"), + Self::StartsWith => String::from("2"), + Self::Exact => String::from("3"), + Self::RegularExpression => String::from("4"), + Self::Never => String::from("5"), } } } impl Default for UriMatchType { fn default() -> UriMatchType { - Self::Variant0 + Self::Domain } } diff --git a/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs b/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs index eb58bfdcc..074c402dc 100644 --- a/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs +++ b/crates/bitwarden-api-api/src/models/web_authn_prf_status.rs @@ -14,23 +14,23 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum WebAuthnPrfStatus { - Variant0 = 0, - Variant1 = 1, - Variant2 = 2, + Enabled = 0, + Supported = 1, + Unsupported = 2, } impl ToString for WebAuthnPrfStatus { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), - Self::Variant2 => String::from("2"), + Self::Enabled => String::from("0"), + Self::Supported => String::from("1"), + Self::Unsupported => String::from("2"), } } } impl Default for WebAuthnPrfStatus { fn default() -> WebAuthnPrfStatus { - Self::Variant0 + Self::Enabled } } diff --git a/crates/bitwarden-api-identity/src/models/kdf_type.rs b/crates/bitwarden-api-identity/src/models/kdf_type.rs index 4b6acaef8..733fba272 100644 --- a/crates/bitwarden-api-identity/src/models/kdf_type.rs +++ b/crates/bitwarden-api-identity/src/models/kdf_type.rs @@ -14,21 +14,21 @@ Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize_repr, Deserialize_repr, )] pub enum KdfType { - Variant0 = 0, - Variant1 = 1, + PBKDF2_SHA256 = 0, + Argon2id = 1, } impl ToString for KdfType { fn to_string(&self) -> String { match self { - Self::Variant0 => String::from("0"), - Self::Variant1 => String::from("1"), + Self::PBKDF2_SHA256 => String::from("0"), + Self::Argon2id => String::from("1"), } } } impl Default for KdfType { fn default() -> KdfType { - Self::Variant0 + Self::PBKDF2_SHA256 } } diff --git a/crates/bitwarden/src/admin_console/policy.rs b/crates/bitwarden/src/admin_console/policy.rs index 9a4b0d16f..7e87b8623 100644 --- a/crates/bitwarden/src/admin_console/policy.rs +++ b/crates/bitwarden/src/admin_console/policy.rs @@ -53,20 +53,28 @@ impl TryFrom for Policy { impl From for PolicyType { fn from(policy_type: bitwarden_api_api::models::PolicyType) -> Self { match policy_type { - bitwarden_api_api::models::PolicyType::Variant0 => PolicyType::TwoFactorAuthentication, - bitwarden_api_api::models::PolicyType::Variant1 => PolicyType::MasterPassword, - bitwarden_api_api::models::PolicyType::Variant2 => PolicyType::PasswordGenerator, - bitwarden_api_api::models::PolicyType::Variant3 => PolicyType::SingleOrg, - bitwarden_api_api::models::PolicyType::Variant4 => PolicyType::RequireSso, - bitwarden_api_api::models::PolicyType::Variant5 => PolicyType::PersonalOwnership, - bitwarden_api_api::models::PolicyType::Variant6 => PolicyType::DisableSend, - bitwarden_api_api::models::PolicyType::Variant7 => PolicyType::SendOptions, - bitwarden_api_api::models::PolicyType::Variant8 => PolicyType::ResetPassword, - bitwarden_api_api::models::PolicyType::Variant9 => PolicyType::MaximumVaultTimeout, - bitwarden_api_api::models::PolicyType::Variant10 => { + bitwarden_api_api::models::PolicyType::TwoFactorAuthentication => { + PolicyType::TwoFactorAuthentication + } + bitwarden_api_api::models::PolicyType::MasterPassword => PolicyType::MasterPassword, + bitwarden_api_api::models::PolicyType::PasswordGenerator => { + PolicyType::PasswordGenerator + } + bitwarden_api_api::models::PolicyType::SingleOrg => PolicyType::SingleOrg, + bitwarden_api_api::models::PolicyType::RequireSso => PolicyType::RequireSso, + bitwarden_api_api::models::PolicyType::PersonalOwnership => { + PolicyType::PersonalOwnership + } + bitwarden_api_api::models::PolicyType::DisableSend => PolicyType::DisableSend, + bitwarden_api_api::models::PolicyType::SendOptions => PolicyType::SendOptions, + bitwarden_api_api::models::PolicyType::ResetPassword => PolicyType::ResetPassword, + bitwarden_api_api::models::PolicyType::MaximumVaultTimeout => { + PolicyType::MaximumVaultTimeout + } + bitwarden_api_api::models::PolicyType::DisablePersonalVaultExport => { PolicyType::DisablePersonalVaultExport } - bitwarden_api_api::models::PolicyType::Variant11 => PolicyType::ActivateAutofill, + bitwarden_api_api::models::PolicyType::ActivateAutofill => PolicyType::ActivateAutofill, } } } diff --git a/crates/bitwarden/src/auth/api/response/identity_success_response.rs b/crates/bitwarden/src/auth/api/response/identity_success_response.rs index e59f91b7b..fb59c1caa 100644 --- a/crates/bitwarden/src/auth/api/response/identity_success_response.rs +++ b/crates/bitwarden/src/auth/api/response/identity_success_response.rs @@ -53,7 +53,7 @@ mod test { private_key: Default::default(), key: Default::default(), two_factor_token: Default::default(), - kdf: KdfType::Variant0, + kdf: KdfType::default(), kdf_iterations: crate::util::default_pbkdf2_iterations(), reset_master_password: Default::default(), force_password_reset: Default::default(), diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs index 30db06124..1d85c75d6 100644 --- a/crates/bitwarden/src/auth/login/auth_request.rs +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -41,7 +41,7 @@ pub(crate) async fn send_new_auth_request( public_key: auth.public_key, device_identifier: device_identifier.clone(), access_code: auth.access_code.clone(), - r#type: AuthRequestType::Variant0, // AuthenticateAndUnlock + r#type: AuthRequestType::AuthenticateAndUnlock, }; let res = auth_requests_post(&config.api, Some(req)).await?; diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index a36d27ae9..53ea712cc 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -67,13 +67,13 @@ pub(crate) fn parse_prelogin(response: PreloginResponseModel) -> Result { let kdf = response.kdf.ok_or("KDF not found")?; Ok(match kdf { - KdfType::Variant0 => Kdf::PBKDF2 { + KdfType::PBKDF2_SHA256 => Kdf::PBKDF2 { iterations: response .kdf_iterations .and_then(|e| NonZeroU32::new(e as u32)) .unwrap_or_else(default_pbkdf2_iterations), }, - KdfType::Variant1 => Kdf::Argon2id { + KdfType::Argon2id => Kdf::Argon2id { iterations: response .kdf_iterations .and_then(|e| NonZeroU32::new(e as u32)) diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 2b0c9503b..31b69c515 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -42,7 +42,7 @@ pub(super) async fn register(client: &mut Client, req: &RegisterRequest) -> Resu })), token: None, organization_user_id: None, - kdf: Some(bitwarden_api_identity::models::KdfType::Variant0), + kdf: Some(bitwarden_api_identity::models::KdfType::PBKDF2_SHA256), kdf_iterations: Some(default_pbkdf2_iterations().get() as i32), kdf_memory: None, kdf_parallelism: None, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index bbd944871..9223462a1 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -385,10 +385,10 @@ impl TryFrom for Cipher { impl From for CipherType { fn from(t: bitwarden_api_api::models::CipherType) -> Self { match t { - bitwarden_api_api::models::CipherType::Variant1 => CipherType::Login, - bitwarden_api_api::models::CipherType::Variant2 => CipherType::SecureNote, - bitwarden_api_api::models::CipherType::Variant3 => CipherType::Card, - bitwarden_api_api::models::CipherType::Variant4 => CipherType::Identity, + bitwarden_api_api::models::CipherType::Login => CipherType::Login, + bitwarden_api_api::models::CipherType::SecureNote => CipherType::SecureNote, + bitwarden_api_api::models::CipherType::Card => CipherType::Card, + bitwarden_api_api::models::CipherType::Identity => CipherType::Identity, } } } @@ -396,8 +396,8 @@ impl From for CipherType { impl From for CipherRepromptType { fn from(t: bitwarden_api_api::models::CipherRepromptType) -> Self { match t { - bitwarden_api_api::models::CipherRepromptType::Variant0 => CipherRepromptType::None, - bitwarden_api_api::models::CipherRepromptType::Variant1 => CipherRepromptType::Password, + bitwarden_api_api::models::CipherRepromptType::None => CipherRepromptType::None, + bitwarden_api_api::models::CipherRepromptType::Password => CipherRepromptType::Password, } } } diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index bde713a05..25a318d6f 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -82,10 +82,10 @@ impl TryFrom for Field { impl From for FieldType { fn from(model: bitwarden_api_api::models::FieldType) -> Self { match model { - bitwarden_api_api::models::FieldType::Variant0 => FieldType::Text, - bitwarden_api_api::models::FieldType::Variant1 => FieldType::Hidden, - bitwarden_api_api::models::FieldType::Variant2 => FieldType::Boolean, - bitwarden_api_api::models::FieldType::Variant3 => FieldType::Linked, + bitwarden_api_api::models::FieldType::Text => FieldType::Text, + bitwarden_api_api::models::FieldType::Hidden => FieldType::Hidden, + bitwarden_api_api::models::FieldType::Boolean => FieldType::Boolean, + bitwarden_api_api::models::FieldType::Linked => FieldType::Linked, } } } diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index ea5b1f357..5e2156a83 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -143,12 +143,12 @@ impl TryFrom for LoginUri { impl From for UriMatchType { fn from(value: bitwarden_api_api::models::UriMatchType) -> Self { match value { - bitwarden_api_api::models::UriMatchType::Variant0 => Self::Domain, - bitwarden_api_api::models::UriMatchType::Variant1 => Self::Host, - bitwarden_api_api::models::UriMatchType::Variant2 => Self::StartsWith, - bitwarden_api_api::models::UriMatchType::Variant3 => Self::Exact, - bitwarden_api_api::models::UriMatchType::Variant4 => Self::RegularExpression, - bitwarden_api_api::models::UriMatchType::Variant5 => Self::Never, + bitwarden_api_api::models::UriMatchType::Domain => Self::Domain, + bitwarden_api_api::models::UriMatchType::Host => Self::Host, + bitwarden_api_api::models::UriMatchType::StartsWith => Self::StartsWith, + bitwarden_api_api::models::UriMatchType::Exact => Self::Exact, + bitwarden_api_api::models::UriMatchType::RegularExpression => Self::RegularExpression, + bitwarden_api_api::models::UriMatchType::Never => Self::Never, } } } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 2433a9c2a..eba4ea2fb 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -56,7 +56,7 @@ impl TryFrom for SecureNote { impl From for SecureNoteType { fn from(model: bitwarden_api_api::models::SecureNoteType) -> Self { match model { - bitwarden_api_api::models::SecureNoteType::Variant0 => SecureNoteType::Generic, + bitwarden_api_api::models::SecureNoteType::Generic => SecureNoteType::Generic, } } } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index aba67e00c..144933899 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -329,8 +329,8 @@ impl TryFrom for Send { impl From for SendType { fn from(t: bitwarden_api_api::models::SendType) -> Self { match t { - bitwarden_api_api::models::SendType::Variant0 => SendType::Text, - bitwarden_api_api::models::SendType::Variant1 => SendType::File, + bitwarden_api_api::models::SendType::Text => SendType::Text, + bitwarden_api_api::models::SendType::File => SendType::File, } } } diff --git a/support/build-api.sh b/support/build-api.sh new file mode 100755 index 000000000..a668b5564 --- /dev/null +++ b/support/build-api.sh @@ -0,0 +1,26 @@ +# Delete old directory to ensure all files are updated +rm -rf crates/bitwarden-api-api/src + +# Generate new API bindings +npx openapi-generator-cli generate \ + -i ../server/api.json \ + -g rust \ + -o crates/bitwarden-api-api \ + --package-name bitwarden-api-api \ + -t ./support/openapi-template \ + --additional-properties=packageVersion=1.0.0 + +# Delete old directory to ensure all files are updated +rm -rf crates/bitwarden-api-identity/src + +# Generate new Identity bindings +npx openapi-generator-cli generate \ + -i ../server/identity.json \ + -g rust \ + -o crates/bitwarden-api-identity \ + --package-name bitwarden-api-identity \ + -t ./support/openapi-template \ + --additional-properties=packageVersion=1.0.0 + +cargo +nightly fmt +npm run prettier From d273a836a3f1c4b8f67539b0b975ae6715f82276 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:39:40 +0100 Subject: [PATCH 274/378] [PM-6256] [deps]: Update Rust crate thiserror to 1.0.57 (#599) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [thiserror](https://togithub.com/dtolnay/thiserror) | dependencies | patch | `1.0.56` -> `1.0.57` | --- ### Release Notes
dtolnay/thiserror (thiserror) ### [`v1.0.57`](https://togithub.com/dtolnay/thiserror/releases/tag/1.0.57) [Compare Source](https://togithub.com/dtolnay/thiserror/compare/1.0.56...1.0.57) - Generate more efficient `Display` impl for error message which do not contain any interpolated value ([#​286](https://togithub.com/dtolnay/thiserror/issues/286), thanks [@​nyurik](https://togithub.com/nyurik))
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). [PM-6256](https://bitwarden.atlassian.net/browse/PM-6256) [PM-6256]: https://bitwarden.atlassian.net/browse/PM-6256?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bws/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e7cc9414..c4536ee0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3395,18 +3395,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 8acc9f92c..97085539b 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -35,7 +35,7 @@ serde = "^1.0.196" serde_json = "^1.0.113" serde_yaml = "0.9" supports-color = "3.0.0" -thiserror = "1.0.56" +thiserror = "1.0.57" tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.9" uuid = { version = "^1.7.0", features = ["serde"] } From 0e8d5978a23fbaf44c253c652e4bdfecc4a5a7c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:39:54 +0100 Subject: [PATCH 275/378] [PM-6255] [deps]: Update Rust crate toml to 0.8.10 (#600) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [toml](https://togithub.com/toml-rs/toml) | dependencies | patch | `0.8.9` -> `0.8.10` | --- ### Release Notes
toml-rs/toml (toml) ### [`v0.8.10`](https://togithub.com/toml-rs/toml/compare/toml-v0.8.9...toml-v0.8.10) [Compare Source](https://togithub.com/toml-rs/toml/compare/toml-v0.8.9...toml-v0.8.10)
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). [PM-6255](https://bitwarden.atlassian.net/browse/PM-6255) [PM-6255]: https://bitwarden.atlassian.net/browse/PM-6255?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 10 +++++----- crates/bws/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4536ee0f..e1caec370 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -629,7 +629,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.9", + "toml 0.8.10", "uuid", ] @@ -3532,9 +3532,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", @@ -3553,9 +3553,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ "indexmap 2.2.2", "serde", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 97085539b..522544204 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -37,7 +37,7 @@ serde_yaml = "0.9" supports-color = "3.0.0" thiserror = "1.0.57" tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } -toml = "0.8.9" +toml = "0.8.10" uuid = { version = "^1.7.0", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } From e53e0c9b4522bc549e99dbc084ceed3e0d1f9c63 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:40:06 +0100 Subject: [PATCH 276/378] [PM-6250] [deps]: Update Rust crate tempfile to 3.10.0 (#605) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [tempfile](https://stebalien.com/projects/tempfile-rs/) ([source](https://togithub.com/Stebalien/tempfile)) | dev-dependencies | minor | `3.9.0` -> `3.10.0` | --- ### Release Notes
Stebalien/tempfile (tempfile) ### [`v3.10.0`](https://togithub.com/Stebalien/tempfile/blob/HEAD/CHANGELOG.md#3100) [Compare Source](https://togithub.com/Stebalien/tempfile/compare/v3.9.0...v3.10.0) - Drop `redox_syscall` dependency, we now use `rustix` for Redox. - Add `Builder::permissions` for setting the permissions on temporary files and directories (thanks to [@​Byron](https://togithub.com/Byron)). - Update rustix to 0.38.31. - Update fastrand to 2.0.1.
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). [PM-6250](https://bitwarden.atlassian.net/browse/PM-6250) [PM-6250]: https://bitwarden.atlassian.net/browse/PM-6250?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 5 ++--- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1caec370..b8f08eed3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3371,13 +3371,12 @@ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall", "rustix", "windows-sys 0.52.0", ] diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 1943e5ad5..32fd03159 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -27,4 +27,4 @@ bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } [dev-dependencies] -tempfile = "3.9.0" +tempfile = "3.10.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 522544204..c7c589b82 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -43,4 +43,4 @@ uuid = { version = "^1.7.0", features = ["serde"] } bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } [dev-dependencies] -tempfile = "3.9.0" +tempfile = "3.10.0" From e84f832ab9a78deae158d1ee519a0e9bb6ec1fbf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:55:24 +0100 Subject: [PATCH 277/378] [deps]: Update Rust crate wiremock to 0.6.0 (#606) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [wiremock](https://togithub.com/LukeMathWalker/wiremock-rs) | dev-dependencies | minor | `0.5.22` -> `0.6.0` | --- ### Release Notes
LukeMathWalker/wiremock-rs (wiremock) ### [`v0.6.0`](https://togithub.com/LukeMathWalker/wiremock-rs/compare/v0.6.0-rc.3...v0.6.0) [Compare Source](https://togithub.com/LukeMathWalker/wiremock-rs/compare/v0.5.22...v0.6.0)
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 349 ++++++++++--------------- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- 3 files changed, 136 insertions(+), 217 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8f08eed3..0c1046267 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,17 +186,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - [[package]] name = "async-compat" version = "0.2.3" @@ -216,7 +205,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 4.0.3", + "event-listener", "event-listener-strategy", "pin-project-lite", ] @@ -253,12 +242,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -348,24 +331,24 @@ checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" name = "bitwarden" version = "0.4.0" dependencies = [ - "base64 0.21.7", + "base64", "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", "bitwarden-exporters", "bitwarden-generators", "chrono", - "getrandom 0.2.12", + "getrandom", "hmac", "log", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "reqwest", "rustls-platform-verifier", "schemars", "serde", "serde_json", - "serde_qs 0.12.0", + "serde_qs", "serde_repr", "sha1", "sha2", @@ -429,7 +412,7 @@ version = "0.1.0" dependencies = [ "aes", "argon2", - "base64 0.21.7", + "base64", "cbc", "generic-array", "hkdf", @@ -437,8 +420,8 @@ dependencies = [ "num-bigint", "num-traits", "pbkdf2", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "rayon", "rsa", "schemars", @@ -457,7 +440,7 @@ dependencies = [ name = "bitwarden-exporters" version = "0.1.0" dependencies = [ - "base64 0.21.7", + "base64", "bitwarden-crypto", "chrono", "csv", @@ -472,8 +455,8 @@ name = "bitwarden-generators" version = "0.1.0" dependencies = [ "bitwarden-crypto", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "reqwest", "schemars", "serde", @@ -1103,14 +1086,13 @@ dependencies = [ [[package]] name = "deadpool" -version = "0.9.5" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "421fe0f90f2ab22016f32a9881be5134fdd71c65298917084b0c7477cbc3856e" +checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" dependencies = [ "async-trait", "deadpool-runtime", "num_cpus", - "retain_mut", "tokio", ] @@ -1270,12 +1252,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - [[package]] name = "event-listener" version = "4.0.3" @@ -1293,7 +1269,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.3", + "event-listener", "pin-project-lite", ] @@ -1317,15 +1293,6 @@ dependencies = [ "regex", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.0.1" @@ -1414,21 +1381,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.30" @@ -1452,12 +1404,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - [[package]] name = "futures-util" version = "0.3.30" @@ -1487,17 +1433,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.12" @@ -1507,7 +1442,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1558,7 +1493,26 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.11", + "indexmap 2.2.2", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.0.0", "indexmap 2.2.2", "slab", "tokio", @@ -1628,6 +1582,17 @@ dependencies = [ "itoa", ] +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1635,29 +1600,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.11", "pin-project-lite", ] [[package]] -name = "http-types" -version = "2.12.0" +name = "http-body" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ - "anyhow", - "async-channel", - "base64 0.13.1", - "futures-lite", - "http", - "infer", + "bytes", + "http 1.0.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +dependencies = [ + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", "pin-project-lite", - "rand 0.7.3", - "serde", - "serde_json", - "serde_qs 0.8.5", - "serde_urlencoded", - "url", ] [[package]] @@ -1688,9 +1655,9 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.24", + "http 0.2.11", + "http-body 0.4.6", "httparse", "httpdate", "itoa", @@ -1702,6 +1669,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.2", + "http 1.0.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "tokio", + "want", +] + [[package]] name = "hyper-rustls" version = "0.24.2" @@ -1709,13 +1696,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http", - "hyper", + "http 0.2.11", + "hyper 0.14.28", "rustls", "tokio", "tokio-rustls", ] +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.1.0", + "pin-project-lite", + "socket2", + "tokio", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1788,12 +1791,6 @@ version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" -[[package]] -name = "infer" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" - [[package]] name = "inout" version = "0.1.3" @@ -1820,15 +1817,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "ipnet" version = "2.9.0" @@ -2021,7 +2009,7 @@ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -2134,7 +2122,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand", "smallvec", "zeroize", ] @@ -2283,7 +2271,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2377,7 +2365,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ - "base64 0.21.7", + "base64", "indexmap 2.2.2", "line-wrap", "quick-xml", @@ -2527,19 +2515,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -2547,18 +2522,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -2568,16 +2533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -2586,16 +2542,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.12", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -2633,7 +2580,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.12", + "getrandom", "libredox", "thiserror", ] @@ -2679,15 +2626,15 @@ version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ - "base64 0.21.7", + "base64", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", + "h2 0.3.24", + "http 0.2.11", + "http-body 0.4.6", + "hyper 0.14.28", "hyper-rustls", "ipnet", "js-sys", @@ -2715,12 +2662,6 @@ dependencies = [ "winreg", ] -[[package]] -name = "retain_mut" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" - [[package]] name = "rgb" version = "0.8.37" @@ -2737,7 +2678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", - "getrandom 0.2.12", + "getrandom", "libc", "spin 0.9.8", "untrusted", @@ -2757,7 +2698,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core 0.6.4", + "rand_core", "signature", "spki", "subtle", @@ -2813,7 +2754,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.7", + "base64", ] [[package]] @@ -3046,17 +2987,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_qs" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" -dependencies = [ - "percent-encoding", - "serde", - "thiserror", -] - [[package]] name = "serde_qs" version = "0.12.0" @@ -3181,7 +3111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3376,7 +3306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if", - "fastrand 2.0.1", + "fastrand", "rustix", "windows-sys 0.52.0", ] @@ -3839,7 +3769,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -3854,7 +3783,7 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ - "getrandom 0.2.12", + "getrandom", "serde", ] @@ -3870,12 +3799,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - [[package]] name = "walkdir" version = "2.4.0" @@ -3895,12 +3818,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4218,24 +4135,26 @@ dependencies = [ [[package]] name = "wiremock" -version = "0.5.22" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a3a53eaf34f390dd30d7b1b078287dd05df2aa2e21a589ccb80f5c7253c2e9" +checksum = "ec874e1eef0df2dcac546057fe5e29186f09c378181cd7b635b4b7bcc98e9d81" dependencies = [ "assert-json-diff", "async-trait", - "base64 0.21.7", + "base64", "deadpool", "futures", - "futures-timer", - "http-types", - "hyper", + "http 1.0.0", + "http-body-util", + "hyper 1.1.0", + "hyper-util", "log", "once_cell", "regex", "serde", "serde_json", "tokio", + "url", ] [[package]] diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index 39eeb3d71..d790cb5d1 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -30,4 +30,4 @@ uniffi = { version = "=0.26.1", optional = true } [dev-dependencies] rand_chacha = "0.3.1" tokio = { version = "1.36.0", features = ["rt", "macros"] } -wiremock = "0.5.22" +wiremock = "0.6.0" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index c6f580282..7f0745fb8 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -78,5 +78,5 @@ reqwest = { version = "*", features = [ [dev-dependencies] rand_chacha = "0.3.1" tokio = { version = "1.36.0", features = ["rt", "macros"] } -wiremock = "0.5.22" +wiremock = "0.6.0" zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } From 65b59f131846c114d6a3893c502e05047523c74d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:01:01 +0100 Subject: [PATCH 278/378] [deps]: Update Rust crate chrono to 0.4.34 (#598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [chrono](https://togithub.com/chronotope/chrono) | dependencies | patch | `0.4.33` -> `0.4.34` | --- ### Release Notes
chronotope/chrono (chrono) ### [`v0.4.34`](https://togithub.com/chronotope/chrono/releases/tag/v0.4.34): 0.4.34 [Compare Source](https://togithub.com/chronotope/chrono/compare/v0.4.33...v0.4.34) ### Notable changes - In chrono 0.4.34 we finished the work to make all methods const where doing so is supported by rust 1.61. - We renamed the `Duration` type to `TimeDelta`. This removes the confusion between chrono's type and the later `Duration` type in the standard library. It will remain available under the old name as a type alias for compatibility. - The Windows implementation of `Local` is rewritten. The new version avoids panics when the date is outside of the range supported by windows (the years 1601 to 30828), and gives more accurate results during DST transitions. - The `Display` format of `TimeDelta` is modified to conform better to ISO 8601. Previously it converted all values greater than 24 hours to a value with days. This is not correct, as doing so changes the duration from an 'accurate' to a 'nominal' representation to use ISO 8601 terms. ### Fixes - Add missing range check in `TimeDelta::milliseconds` ([#​1385](https://togithub.com/chronotope/chrono/issues/1385), thanks [@​danwilliams](https://togithub.com/danwilliams)) - Remove check for `DurationExceedsTimestamp` in `DurationRound` ([#​1403](https://togithub.com/chronotope/chrono/issues/1403), thanks [@​joroKr21](https://togithub.com/joroKr21)) - Fix localized formatting with `%X` (([https://github.com/chronotope/pure-rust-locales/pull/12](https://togithub.com/chronotope/pure-rust-locales/pull/12), [#​1420](https://togithub.com/chronotope/chrono/issues/1420)) - Windows: base implementation on `GetTimeZoneInformationForYear` ([#​1017](https://togithub.com/chronotope/chrono/issues/1017)) ### Additions - Add `TimeDelta::try_milliseconds` ([#​1385](https://togithub.com/chronotope/chrono/issues/1385), thanks [@​danwilliams](https://togithub.com/danwilliams)) - Add `TimeDelta::new` ([#​1337](https://togithub.com/chronotope/chrono/issues/1337)) - Add `StrftimeItems::{parse, parse_to_owned}` and more documentation ([#​1184](https://togithub.com/chronotope/chrono/issues/1184)) - More standard traits and documentation for `format::Locale` (via [https://github.com/chronotope/pure-rust-locales/pull/8](https://togithub.com/chronotope/pure-rust-locales/pull/8)) ### Changes - Rename `Duration` to `TimeDelta`, add type alias ([#​1406](https://togithub.com/chronotope/chrono/issues/1406)) - Make `TimeDelta` methods const ([#​1337](https://togithub.com/chronotope/chrono/issues/1337)) - Make remaining methods of `NaiveDate`, `NaiveWeek`, `NaiveTime` and `NaiveDateTime` const where possible ([#​1337](https://togithub.com/chronotope/chrono/issues/1337)) - Make methods on `DateTime` const where possible ([#​1400](https://togithub.com/chronotope/chrono/issues/1400)) - Make `Display` format of `TimeDelta` conform better to ISO 8601 ([#​1328](https://togithub.com/chronotope/chrono/issues/1328)) ### Documentation - Fix the formatting of `timestamp_micros`'s Example doc ([#​1338](https://togithub.com/chronotope/chrono/issues/1338) via [#​1386](https://togithub.com/chronotope/chrono/issues/1386), thanks [@​emikitas](https://togithub.com/emikitas)) - Specify branch for GitHub Actions badge and fix link ([#​1388](https://togithub.com/chronotope/chrono/issues/1388)) - Don't mention some deprecated methods in docs ([#​1395](https://togithub.com/chronotope/chrono/issues/1395)) - Remove stray documentation from main ([#​1397](https://togithub.com/chronotope/chrono/issues/1397)) - Improved documentation of `TimeDelta` constructors ([#​1385](https://togithub.com/chronotope/chrono/issues/1385), thanks [@​danwilliams](https://togithub.com/danwilliams)) ### Internal - Switch branch names: 0.4.x releases are the `main` branch, work on 0.5 happens in the `0.5.x` branch ([#​1390](https://togithub.com/chronotope/chrono/issues/1390), [#​1402](https://togithub.com/chronotope/chrono/issues/1402)). - Don't use deprecated method in `impl Arbitrary for DateTime` and set up CI test ([#​1336](https://togithub.com/chronotope/chrono/issues/1336)) - Remove workaround for Rust < 1.61 ([#​1393](https://togithub.com/chronotope/chrono/issues/1393)) - Bump `codecov/codecov-action` from 3 to 4 ([#​1404](https://togithub.com/chronotope/chrono/issues/1404)) - Remove partial support for handling `-0000` offset ([#​1411](https://togithub.com/chronotope/chrono/issues/1411)) - Move `TOO_LONG` error out of `parse_internal` ([#​1419](https://togithub.com/chronotope/chrono/issues/1419)) Thanks to all contributors on behalf of the chrono team, [@​djc](https://togithub.com/djc) and [@​pitdicker](https://togithub.com/pitdicker)!
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c1046267..cfcd84ba7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,9 +704,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ "android-tzdata", "iana-time-zone", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index c7c589b82..bbd813e78 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -16,7 +16,7 @@ keywords = ["bitwarden", "secrets-manager", "cli"] bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } -chrono = { version = "0.4.33", features = [ +chrono = { version = "0.4.34", features = [ "clock", "std", ], default-features = false } From 2290bc802259d5966eb05b4b6799ba4095c52958 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:01:52 +0100 Subject: [PATCH 279/378] [deps]: Update rust-wasm-bindgen monorepo (#602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [js-sys](https://rustwasm.github.io/wasm-bindgen/) ([source](https://togithub.com/rustwasm/wasm-bindgen/tree/HEAD/crates/js-sys)) | dependencies | patch | `0.3.67` -> `0.3.68` | | [wasm-bindgen](https://rustwasm.github.io/) ([source](https://togithub.com/rustwasm/wasm-bindgen)) | dependencies | patch | `0.2.90` -> `0.2.91` | | [wasm-bindgen-futures](https://rustwasm.github.io/wasm-bindgen/) ([source](https://togithub.com/rustwasm/wasm-bindgen/tree/HEAD/crates/futures)) | dependencies | patch | `0.4.40` -> `0.4.41` | | [wasm-bindgen-test](https://togithub.com/rustwasm/wasm-bindgen) | dev-dependencies | patch | `0.3.40` -> `0.3.41` | --- ### Release Notes
rustwasm/wasm-bindgen (wasm-bindgen) ### [`v0.2.91`](https://togithub.com/rustwasm/wasm-bindgen/blob/HEAD/CHANGELOG.md#0291) [Compare Source](https://togithub.com/rustwasm/wasm-bindgen/compare/0.2.90...0.2.91) Released 2024-02-06 ##### Added - Added bindings for the `RTCRtpTransceiver.setCodecPreferences()` and unstable bindings for the `RTCRtpEncodingParameters.scalabilityMode`. [#​3828](https://togithub.com/rustwasm/wasm-bindgen/pull/3828) - Add unstable bindings for the FileSystemAccess API [#​3810](https://togithub.com/rustwasm/wasm-bindgen/pull/3810) - Added support for running tests in shared and service workers with `wasm_bindgen_test_configure!` `run_in_shared_worker` and `run_in_service_worker`. [#​3804](https://togithub.com/rustwasm/wasm-bindgen/pull/3804) - Accept the `--skip` flag with `wasm-bindgen-test-runner`. [#​3803](https://togithub.com/rustwasm/wasm-bindgen/pull/3803) - Introduce environment variable `WASM_BINDGEN_TEST_NO_ORIGIN_ISOLATION` to disable origin isolation for `wasm-bindgen-test-runner`. [#​3807](https://togithub.com/rustwasm/wasm-bindgen/pull/3807) - Add bindings for `USBDevice.forget()`. [#​3821](https://togithub.com/rustwasm/wasm-bindgen/pull/3821) ##### Changed - Stabilize `ClipboardEvent`. [#​3791](https://togithub.com/rustwasm/wasm-bindgen/pull/3791) - Use immutable buffers in `SubtleCrypto` methods. [#​3797](https://togithub.com/rustwasm/wasm-bindgen/pull/3797) - Deprecate `wasm_bindgen_test_configure!`s `run_in_worker` in favor of `run_in_dedicated_worker`. [#​3804](https://togithub.com/rustwasm/wasm-bindgen/pull/3804) - Updated the WebGPU WebIDL to the current draft as of 2024-01-30. Note that this retains the previous update's workaround for `GPUPipelineError`, and holds back an update to the `buffer` argument of the `GPUQueue.{writeBuffer,writeTexture}` methods. [#​3816](https://togithub.com/rustwasm/wasm-bindgen/pull/3816) - Depreate `--weak-refs` and `WASM_BINDGEN_WEAKREF` in favor of automatic run-time detection. [#​3822](https://togithub.com/rustwasm/wasm-bindgen/pull/3822) ##### Fixed - Fixed UB when freeing strings received from JS if not using the default allocator. [#​3808](https://togithub.com/rustwasm/wasm-bindgen/pull/3808) - Fixed temporary folder detection by `wasm-bindgen-test-runner` on MacOS. [#​3817](https://togithub.com/rustwasm/wasm-bindgen/pull/3817) - Fixed using `#[wasm_bindgen(js_name = default)]` with `#[wasm_bindgen(module = ...)]`. [#​3823](https://togithub.com/rustwasm/wasm-bindgen/pull/3823) - Fixed nighly build of `wasm-bindgen-futures`. [#​3827](https://togithub.com/rustwasm/wasm-bindgen/pull/3827) ***
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 36 ++++++++++++++++---------------- crates/bitwarden-wasm/Cargo.toml | 8 +++---- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cfcd84ba7..6b1bd3669 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1875,9 +1875,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -3826,9 +3826,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "serde", @@ -3838,9 +3838,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", @@ -3853,9 +3853,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -3865,9 +3865,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3875,9 +3875,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", @@ -3888,15 +3888,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-bindgen-test" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c" +checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3908,9 +3908,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" +checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89" dependencies = [ "proc-macro2", "quote", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index bd2a064a1..d0ae7482e 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -10,11 +10,11 @@ crate-type = ["cdylib"] [dependencies] console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } -js-sys = "0.3.67" +js-sys = "0.3.68" log = "0.4.20" serde = { version = "1.0.196", features = ["derive"] } -wasm-bindgen = { version = "0.2.90", features = ["serde-serialize"] } -wasm-bindgen-futures = "0.4.40" +wasm-bindgen = { version = "0.2.91", features = ["serde-serialize"] } +wasm-bindgen-futures = "0.4.41" bitwarden-json = { path = "../bitwarden-json", features = [ "secrets", @@ -22,4 +22,4 @@ bitwarden-json = { path = "../bitwarden-json", features = [ ] } [dev-dependencies] -wasm-bindgen-test = "0.3.40" +wasm-bindgen-test = "0.3.41" From 8bed619df7c28b720e65427a9eb83c2757732e58 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:26:07 +0100 Subject: [PATCH 280/378] [deps]: Lock file maintenance (#607) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 116 +++++++++++----------- crates/bitwarden-napi/package-lock.json | 6 +- languages/js/example/package-lock.json | 60 ++++++----- languages/js/sdk-client/package-lock.json | 6 +- package-lock.json | 12 +-- 5 files changed, 99 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6b1bd3669..0562c76fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,9 +78,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -618,9 +618,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.1" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" [[package]] name = "byteorder" @@ -651,9 +651,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -730,9 +730,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" dependencies = [ "clap_builder", "clap_derive", @@ -740,30 +740,30 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] name = "clap_complete" -version = "4.4.10" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3" +checksum = "299353be8209bd133b049bf1c63582d184a8b39fd9c04f15fe65f50f88bdfe6c" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" dependencies = [ "heck", "proc-macro2", @@ -773,9 +773,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "clircle" @@ -1069,7 +1069,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -1194,9 +1194,9 @@ checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "encode_unicode" @@ -1468,7 +1468,7 @@ dependencies = [ "bstr", "log", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -1494,7 +1494,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.11", - "indexmap 2.2.2", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", @@ -1513,7 +1513,7 @@ dependencies = [ "futures-sink", "futures-util", "http 1.0.0", - "indexmap 2.2.2", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", @@ -1540,9 +1540,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "hkdf" @@ -1777,9 +1777,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2035,9 +2035,9 @@ checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" [[package]] name = "napi-derive" -version = "2.15.0" +version = "2.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7622f0dbe0968af2dacdd64870eee6dee94f93c989c841f1ad8f300cf1abd514" +checksum = "8d56bb899c164ab1be5e542ae7db8b26750c864bf2eef07295f17754e6358777" dependencies = [ "cfg-if", "convert_case", @@ -2049,9 +2049,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec514d65fce18a959be55e7f683ac89c6cb850fb59b09e25ab777fd5a4a8d9e" +checksum = "6cf2d74ac66fd1cccb646be75fdd1c1dce8acfe20a68f61566a31da0d3eb9786" dependencies = [ "convert_case", "once_cell", @@ -2135,19 +2135,18 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -2156,9 +2155,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -2366,7 +2365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64", - "indexmap 2.2.2", + "indexmap 2.2.3", "line-wrap", "quick-xml", "serde", @@ -2594,7 +2593,7 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] @@ -2605,15 +2604,9 @@ checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - [[package]] name = "regex-syntax" version = "0.8.2" @@ -3036,7 +3029,7 @@ version = "0.9.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" dependencies = [ - "indexmap 2.2.2", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -3191,6 +3184,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + [[package]] name = "strum" version = "0.25.0" @@ -3255,9 +3254,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "syntect" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" dependencies = [ "bincode", "bitflags 1.3.2", @@ -3265,8 +3264,9 @@ dependencies = [ "fnv", "once_cell", "onig", - "regex-syntax 0.7.5", + "regex-syntax", "serde", + "serde_derive", "serde_json", "thiserror", "walkdir", @@ -3486,7 +3486,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ - "indexmap 2.2.2", + "indexmap 2.2.3", "serde", "serde_spanned", "toml_datetime", @@ -3590,9 +3590,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" @@ -3919,9 +3919,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", @@ -4116,9 +4116,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.37" +version = "0.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" dependencies = [ "memchr", ] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 9c9d87de9..25da5b8e5 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", "dev": true, "peer": true, "dependencies": { diff --git a/languages/js/example/package-lock.json b/languages/js/example/package-lock.json index f6cab6536..d48fd43be 100644 --- a/languages/js/example/package-lock.json +++ b/languages/js/example/package-lock.json @@ -1,34 +1,32 @@ { - "name": "sdk-example", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "sdk-example", - "dependencies": { - "@bitwarden/sdk-client": "../sdk-client", - "@bitwarden/sdk-wasm": "../wasm" - } - }, - "../sdk-client": { - "name": "@bitwarden/sdk-client", - "devDependencies": { - "@types/node": "^18.15.11", - "rimraf": "^5.0.0", - "typescript": "^5.0.3" - } - }, - "../wasm": { - "name": "@bitwarden/sdk-wasm", - "version": "0.1.0" - }, - "node_modules/@bitwarden/sdk-client": { - "resolved": "../sdk-client", - "link": true - }, - "node_modules/@bitwarden/sdk-wasm": { - "resolved": "../wasm", - "link": true - } + "name": "sdk-example", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "sdk-example", + "dependencies": { + "@bitwarden/sdk-client": "../sdk-client", + "@bitwarden/sdk-wasm": "../wasm" + } + }, + "../sdk-client": { + "devDependencies": { + "@types/node": "^18.15.11", + "rimraf": "^5.0.0", + "typescript": "^5.0.3" + } + }, + "../wasm": { + "version": "0.1.0" + }, + "node_modules/@bitwarden/sdk-client": { + "resolved": "../sdk-client", + "link": true + }, + "node_modules/@bitwarden/sdk-wasm": { + "resolved": "../wasm", + "link": true } + } } diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index eb8d010db..aec6ec5e0 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.14.tgz", - "integrity": "sha512-EnQ4Us2rmOS64nHDWr0XqAD8DsO6f3XR6lf9UIIrZQpUzPVdN/oPuEzfDWNHSyXLvoGgjuEm/sPwFGSSs35Wtg==", + "version": "18.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.15.tgz", + "integrity": "sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/package-lock.json b/package-lock.json index bdb82563e..d6befe7f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -346,9 +346,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", + "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", "dev": true, "peer": true, "dependencies": { @@ -852,9 +852,9 @@ "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" From ff57485bb04b3b37f26c3a1b2c5f1926566a56ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=9C=A8=20Audrey=20=E2=9C=A8?= Date: Mon, 12 Feb 2024 10:00:29 -0500 Subject: [PATCH 281/378] allow empty word separator in passphrases (#597) Allow the passphrase word separator to be the empty string `''`. This change recently merged [in the clients repository](https://github.com/bitwarden/clients/commit/bb031f6779fe19afff3b89a8b9aff947c869cd41). --- crates/bitwarden-generators/src/passphrase.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/bitwarden-generators/src/passphrase.rs b/crates/bitwarden-generators/src/passphrase.rs index f8329a80c..d99728219 100644 --- a/crates/bitwarden-generators/src/passphrase.rs +++ b/crates/bitwarden-generators/src/passphrase.rs @@ -10,8 +10,6 @@ use crate::util::capitalize_first_letter; pub enum PassphraseError { #[error("'num_words' must be between {} and {}", minimum, maximum)] InvalidNumWords { minimum: u8, maximum: u8 }, - #[error("'word_separator' cannot be empty")] - EmptyWordSeparator, } /// Passphrase generator request options. @@ -69,10 +67,6 @@ impl PassphraseGeneratorRequest { }); } - if self.word_separator.chars().next().is_none() { - return Err(PassphraseError::EmptyWordSeparator); - }; - Ok(ValidPassphraseGeneratorOptions { num_words: self.num_words, word_separator: self.word_separator, From 8ea2f79c6bdddbfb1a6fa051d0461a1a9fb724c5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 10:33:22 -0500 Subject: [PATCH 282/378] [deps]: Update gh minor (#601) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 10 +++++----- .github/workflows/build-dotnet.yml | 12 ++++++------ .github/workflows/build-java.yml | 10 +++++----- .github/workflows/build-napi.yml | 6 +++--- .github/workflows/build-python-wheels.yml | 8 ++++---- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/generate_schemas.yml | 16 ++++++++-------- .github/workflows/lint.yml | 2 +- .github/workflows/publish-dotnet.yml | 10 +++++----- .github/workflows/publish-php.yml | 8 ++++---- .github/workflows/publish-ruby.yml | 10 +++++----- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 4 ++-- .github/workflows/release-napi.yml | 4 ++-- 15 files changed, 54 insertions(+), 54 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index efa8c7bf0..cad899ef3 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -46,7 +46,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so @@ -86,7 +86,7 @@ jobs: java-version: 17 - name: Download Artifacts - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 - name: Move artifacts working-directory: languages/kotlin/sdk/src/main/jniLibs diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 769c9bea3..970db7396 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -99,7 +99,7 @@ jobs: run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip @@ -118,12 +118,12 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download x86_64-apple-darwin artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: bws-x86_64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip - name: Download aarch64-apple-darwin artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: bws-aarch64-apple-darwin-${{ env._PACKAGE_VERSION }}.zip @@ -142,7 +142,7 @@ jobs: run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip path: ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip @@ -177,7 +177,7 @@ jobs: sed -i.bak 's/\$NAME\$/Bitwarden Secrets Manager CLI/g' THIRDPARTY.html - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: THIRDPARTY.html path: ./crates/bws/THIRDPARTY.html diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index e56bd2282..58bbd5dfa 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -35,25 +35,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/linux-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 @@ -71,7 +71,7 @@ jobs: working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: Bitwarden.Sdk.0.0.1.nupkg path: | diff --git a/.github/workflows/build-java.yml b/.github/workflows/build-java.yml index 2559f659c..3b3c4ba5a 100644 --- a/.github/workflows/build-java.yml +++ b/.github/workflows/build-java.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download Java schemas artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: sdk-schemas-java path: languages/java/src/main/java/bit/sdk/schema/ @@ -37,25 +37,25 @@ jobs: java-version: 17 - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/java/src/main/resources/darwin-x86-64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/java/src/main/resources/darwin-aarch64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/java/src/main/resources/linux-x86-64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/java/src/main/resources/win32-x86-64 diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index c1088a220..aa1cfdd16 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -54,7 +54,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 18 cache: "npm" @@ -72,7 +72,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.ts path: ${{ github.workspace }}/crates/bitwarden-napi/src-ts/bitwarden_client/ @@ -84,7 +84,7 @@ jobs: run: ${{ matrix.settings.build }} - name: Upload artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: sdk-bitwarden-napi-${{ matrix.settings.target }} path: ${{ github.workspace }}/crates/bitwarden-napi/sdk-napi.*.node diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index 5dc5b8d23..7ffc2f24f 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -66,7 +66,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 18 @@ -82,7 +82,7 @@ jobs: key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} - name: Retrieve schemas - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk @@ -109,14 +109,14 @@ jobs: working-directory: ${{ github.workspace }}/languages/python - name: Upload wheels - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-${{ matrix.settings.target }} path: ${{ github.workspace }}/target/wheels/bitwarden_sdk*.whl - name: Upload sdists if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} # we only need one sdist - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: bitwarden_sdk-${{ env._PACKAGE_VERSION }}-sdist path: ${{ github.workspace }}/target/wheels/bitwarden_sdk-*.tar.gz diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 8529ab484..89b75cbab 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -41,7 +41,7 @@ jobs: run: cargo build --target ${{ matrix.settings.target }} --release - name: Upload Artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: libbitwarden_c_files-${{ matrix.settings.target }} path: | diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 99e13089c..025b85105 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -21,7 +21,7 @@ jobs: toolchain: stable - name: Set up Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: cache: "npm" cache-dependency-path: "package-lock.json" @@ -37,48 +37,48 @@ jobs: run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.ts path: ${{ github.workspace }}/languages/js/sdk-client/src/schemas.ts if-no-files-found: error - name: Upload c# schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.cs path: ${{ github.workspace }}/languages/csharp/Bitwarden.Sdk/schemas.cs if-no-files-found: error - name: Upload python schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.py path: ${{ github.workspace }}/languages/python/bitwarden_sdk/schemas.py if-no-files-found: error - name: Upload ruby schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 2f8989f91..1c2279b3d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,7 +36,7 @@ jobs: run: cargo +nightly fmt --check - name: Set up Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: cache: "npm" cache-dependency-path: "package-lock.json" diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 031a8b36f..2f9304903 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -26,7 +26,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.cs path: languages/csharp/Bitwarden.Sdk @@ -37,25 +37,25 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/linux-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index 7406aae33..00b34c23f 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -33,25 +33,25 @@ jobs: working-directory: languages/php/ - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/linux-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 12abd18f0..3dce457b2 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -28,31 +28,31 @@ jobs: ruby-version: 3.2 - name: Download Ruby schemas artifact - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.rb path: languages/ruby/bitwarden_sdk/lib - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-apple-darwin path: temp/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/linux-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index 2f3ea6380..e3b2a1626 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -149,7 +149,7 @@ jobs: - name: Create GitHub deployment if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 + uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7 id: deployment with: token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index fa1ffc346..daf6dd622 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -49,7 +49,7 @@ jobs: - name: Create GitHub deployment if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 + uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7 id: deployment with: token: "${{ secrets.GITHUB_TOKEN }}" @@ -84,7 +84,7 @@ jobs: - name: Create release if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 + uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 env: PKG_VERSION: ${{ steps.version.outputs.version }} with: diff --git a/.github/workflows/release-napi.yml b/.github/workflows/release-napi.yml index 02e29c527..de97249a3 100644 --- a/.github/workflows/release-napi.yml +++ b/.github/workflows/release-napi.yml @@ -56,7 +56,7 @@ jobs: - name: Create GitHub deployment if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: chrnorm/deployment-action@d42cde7132fcec920de534fffc3be83794335c00 # v2.0.5 + uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7 id: deployment with: token: "${{ secrets.GITHUB_TOKEN }}" @@ -93,7 +93,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup Node - uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 18 cache: "npm" From 42ca1b047135048f5fec78888036bc9a2c03540e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 13 Feb 2024 11:17:47 +0100 Subject: [PATCH 283/378] Update MSRV to 1.71 and add CI test (#589) Update MSRV in Cargo.toml and Readme to be up to date with the dependencies that we're using, plus add a test to check that we don't deviate from it. The dependency causing the bump is `env_logger` with a MSRV of 1.71 (released July 2023) https://github.com/rust-cli/env_logger/blob/9303b0c0393c33046a791b0a6497b0f03ef1f434/Cargo.toml#L8 The issue seems to also be affecting other crates in the workspace that don't depend on that crate because the MSRV bump is due to some cargo changes regarding `dep:` features and so it seems to affect the version resolution of the entire workspace. Note that this required a small change to exporters, apparently older rust versions have trouble disambiguating the `csv` crate with the `csv` module. --- .github/workflows/minimum-rust-version.yml | 46 ++++++++++++++++++++++ crates/bitwarden-c/Cargo.toml | 2 +- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bitwarden-crypto/Cargo.toml | 2 +- crates/bitwarden-exporters/src/lib.rs | 2 +- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden-json/Cargo.toml | 2 +- crates/bitwarden-napi/Cargo.toml | 2 +- crates/bitwarden-py/Cargo.toml | 2 +- crates/bitwarden-uniffi/Cargo.toml | 2 +- crates/bitwarden-wasm/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 2 +- crates/bitwarden/README.md | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- crates/sdk-schemas/Cargo.toml | 2 +- crates/uniffi-bindgen/Cargo.toml | 2 +- 17 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/minimum-rust-version.yml diff --git a/.github/workflows/minimum-rust-version.yml b/.github/workflows/minimum-rust-version.yml new file mode 100644 index 000000000..d3eccf653 --- /dev/null +++ b/.github/workflows/minimum-rust-version.yml @@ -0,0 +1,46 @@ +--- +name: Minimum Rust Version + +on: + pull_request: + push: + branches: + - "main" + - "rc" + - "hotfix-rc" + workflow_dispatch: + +defaults: + run: + shell: bash + +jobs: + msrv: + name: Check MSRV for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} + runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} + strategy: + fail-fast: false + matrix: + settings: + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + # Important: When updating this, make sure to update the Readme file + # and also the `rust-version` field in all the `Cargo.toml`. + toolchain: 1.71.0 + targets: ${{ matrix.settings.target }} + + - name: Cache cargo registry + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + with: + key: msrv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} + + - name: cargo check MSRV + run: cargo check -p bitwarden --all-features diff --git a/crates/bitwarden-c/Cargo.toml b/crates/bitwarden-c/Cargo.toml index c6f0ec7f3..211a482e9 100644 --- a/crates/bitwarden-c/Cargo.toml +++ b/crates/bitwarden-c/Cargo.toml @@ -2,7 +2,7 @@ name = "bitwarden-c" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [lib] crate-type = ["lib", "staticlib", "cdylib"] diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 4248c9189..cf28447d3 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -2,7 +2,7 @@ name = "bitwarden-cli" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [dependencies] clap = { version = "4.4.18", features = ["derive"] } diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index f0eac0d0a..54a9f760e 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -10,7 +10,7 @@ Internal crate for the bitwarden crate. Do not use. """ keywords = ["bitwarden"] edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] default = [] diff --git a/crates/bitwarden-exporters/src/lib.rs b/crates/bitwarden-exporters/src/lib.rs index 814633489..f17d31a2d 100644 --- a/crates/bitwarden-exporters/src/lib.rs +++ b/crates/bitwarden-exporters/src/lib.rs @@ -4,7 +4,7 @@ use thiserror::Error; use uuid::Uuid; mod csv; -use csv::export_csv; +use crate::csv::export_csv; mod json; use json::export_json; mod encrypted_json; diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index d790cb5d1..8f06de664 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -10,7 +10,7 @@ Internal crate for the bitwarden crate. Do not use. """ keywords = ["bitwarden"] edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] mobile = ["uniffi"] # Mobile-specific features diff --git a/crates/bitwarden-json/Cargo.toml b/crates/bitwarden-json/Cargo.toml index 1e0473c44..5949ce8cf 100644 --- a/crates/bitwarden-json/Cargo.toml +++ b/crates/bitwarden-json/Cargo.toml @@ -11,7 +11,7 @@ JSON bindings for the Bitwarden Secret Manager SDK keywords = ["bitwarden", "secrets manager"] categories = ["api-bindings"] edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] internal = ["bitwarden/internal"] # Internal testing methods diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 4b6ff4ed1..296f5f45f 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -10,7 +10,7 @@ N-API bindings for the Bitwarden Secrets Manager SDK """ keywords = ["bitwarden", "secrets manager"] edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [lib] crate-type = ["cdylib", "rlib"] diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index e81f2f5a8..f954b0a20 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -2,7 +2,7 @@ name = "bitwarden-py" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [lib] name = "bitwarden_py" diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 7f780558b..eb316ceca 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -2,7 +2,7 @@ name = "bitwarden-uniffi" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] docs = ["dep:schemars"] # Docs diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index d0ae7482e..547ea25ff 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -2,7 +2,7 @@ name = "bitwarden-wasm" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [lib] crate-type = ["cdylib"] diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 7f0745fb8..9950a788a 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -10,7 +10,7 @@ Bitwarden Secrets Manager SDK """ keywords = ["bitwarden", "secrets-manager"] edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] default = ["secrets"] diff --git a/crates/bitwarden/README.md b/crates/bitwarden/README.md index abb2b5dd4..0846651eb 100644 --- a/crates/bitwarden/README.md +++ b/crates/bitwarden/README.md @@ -13,7 +13,7 @@ bitwarden = { "*", features = ["secrets"] } ## Minimum Supported Rust Version -Rust **1.57** or higher. +Rust **1.71** or higher. ## Example diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 32fd03159..068094039 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -2,7 +2,7 @@ name = "bw" version = "0.0.2" edition = "2021" -rust-version = "1.60" +rust-version = "1.71" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index bbd813e78..2ceab6499 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -2,7 +2,7 @@ name = "bws" version = "0.4.0" edition = "2021" -rust-version = "1.60" +rust-version = "1.71" authors = ["Bitwarden Inc"] license-file = "LICENSE" repository = "https://github.com/bitwarden/sdk" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 81a9d76ca..dda54e86a 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -2,7 +2,7 @@ name = "sdk-schemas" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [features] internal = [ diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index e8f6f3f3d..9809eeb72 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -2,7 +2,7 @@ name = "uniffi-bindgen" version = "0.1.0" edition = "2021" -rust-version = "1.57" +rust-version = "1.71" [[bin]] # This can be whatever name makes sense for your project, but the rest of this tutorial assumes uniffi-bindgen. From d722e17a06010605f89fe9b938655877afd23aaa Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 13 Feb 2024 11:21:00 +0100 Subject: [PATCH 284/378] [PM-6261] Add Uniffi bindings for TDE (#608) Add Uniffi bindings for the TDE functionality. --- .../bitwarden-crypto/src/keys/device_key.rs | 39 ++++++++++++++----- crates/bitwarden-crypto/src/uniffi_support.rs | 18 ++++++++- crates/bitwarden-uniffi/src/auth/mod.rs | 7 +++- crates/bitwarden/src/auth/client_auth.rs | 2 +- crates/bitwarden/src/mobile/crypto.rs | 21 ++++++++++ crates/bitwarden/src/uniffi_support.rs | 21 +++------- 6 files changed, 79 insertions(+), 29 deletions(-) diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs index 37bcd58f9..876ae7b75 100644 --- a/crates/bitwarden-crypto/src/keys/device_key.rs +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -1,6 +1,8 @@ +use std::str::FromStr; + use crate::{ - error::Result, AsymmetricCryptoKey, AsymmetricEncString, EncString, KeyDecryptable, - KeyEncryptable, SymmetricCryptoKey, UserKey, + error::Result, AsymmetricCryptoKey, AsymmetricEncString, CryptoError, EncString, + KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, }; /// Device Key @@ -11,8 +13,10 @@ use crate::{ pub struct DeviceKey(SymmetricCryptoKey); #[derive(Debug)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct TrustDeviceResponse { - pub device_key: DeviceKey, + /// Base64 encoded device key + pub device_key: String, /// UserKey encrypted with DevicePublicKey pub protected_user_key: AsymmetricEncString, /// DevicePrivateKey encrypted with [DeviceKey] @@ -47,7 +51,7 @@ impl DeviceKey { .encrypt_with_key(&device_key.0)?; Ok(TrustDeviceResponse { - device_key, + device_key: device_key.to_base64(), protected_user_key, protected_device_private_key, protected_device_public_key, @@ -59,14 +63,27 @@ impl DeviceKey { &self, protected_device_private_key: EncString, protected_user_key: AsymmetricEncString, - ) -> Result { + ) -> Result { let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; let device_private_key = AsymmetricCryptoKey::from_der(device_private_key.as_slice())?; let mut dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; let user_key: SymmetricCryptoKey = dec.as_mut_slice().try_into()?; - Ok(UserKey(user_key)) + Ok(user_key) + } + + fn to_base64(&self) -> String { + self.0.to_base64() + } +} + +impl FromStr for DeviceKey { + type Err = CryptoError; + + fn from_str(s: &str) -> Result { + let key = s.parse::()?; + Ok(DeviceKey(key)) } } @@ -83,14 +100,16 @@ mod tests { let decrypted = result .device_key + .parse::() + .unwrap() .decrypt_user_key( result.protected_device_private_key, result.protected_user_key, ) .unwrap(); - assert_eq!(key.key, decrypted.0.key); - assert_eq!(key.mac_key, decrypted.0.mac_key); + assert_eq!(key.key, decrypted.key); + assert_eq!(key.mac_key, decrypted.mac_key); } #[test] @@ -120,7 +139,7 @@ mod tests { .decrypt_user_key(protected_device_private_key, protected_user_key) .unwrap(); - assert_eq!(decrypted.0.key, user_key.key); - assert_eq!(decrypted.0.mac_key, user_key.mac_key); + assert_eq!(decrypted.key, user_key.key); + assert_eq!(decrypted.mac_key, user_key.mac_key); } } diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index 0ff0194f9..7f1249da0 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,6 +1,6 @@ -use std::num::NonZeroU32; +use std::{num::NonZeroU32, str::FromStr}; -use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; +use crate::{AsymmetricEncString, CryptoError, EncString, UniffiCustomTypeConverter}; uniffi::custom_type!(NonZeroU32, u32); @@ -29,3 +29,17 @@ impl UniffiCustomTypeConverter for EncString { obj.to_string() } } + +uniffi::custom_type!(AsymmetricEncString, String); + +impl UniffiCustomTypeConverter for AsymmetricEncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::from_str(&val).map_err(|e| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 75e0c5656..34d0de93f 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use bitwarden::auth::{ password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, }; -use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf}; +use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf, TrustDeviceResponse}; use crate::{error::Result, Client}; @@ -128,4 +128,9 @@ impl ClientAuth { .auth() .approve_auth_request(public_key)?) } + + /// Trust the current device + pub async fn t(&self) -> Result { + Ok(self.0 .0.write().await.auth().trust_device()?) + } } diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index f08daf0b7..5f2002133 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -122,7 +122,7 @@ impl<'a> ClientAuth<'a> { approve_auth_request(self.client, public_key) } - pub async fn trust_device(&self) -> Result { + pub fn trust_device(&self) -> Result { trust_device(self.client) } } diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 37bb3b905..a48b29b15 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -57,6 +57,14 @@ pub enum InitUserCryptoMethod { method: AuthRequestMethod, }, + DeviceKey { + /// The device's DeviceKey + device_key: String, + /// The Device Private Key + protected_device_private_key: EncString, + /// The user's symmetric crypto key, encrypted with the Device Key. + device_protected_user_key: AsymmetricEncString, + }, } #[cfg(feature = "internal")] @@ -78,6 +86,8 @@ pub enum AuthRequestMethod { #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { + use bitwarden_crypto::DeviceKey; + use crate::auth::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { @@ -123,6 +133,17 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ }; client.initialize_user_crypto_decrypted_key(user_key, private_key)?; } + InitUserCryptoMethod::DeviceKey { + device_key, + protected_device_private_key, + device_protected_user_key, + } => { + let device_key = device_key.parse::()?; + let user_key = device_key + .decrypt_user_key(protected_device_private_key, device_protected_user_key)?; + + client.initialize_user_crypto_decrypted_key(user_key, private_key)?; + } } Ok(()) diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 7da53c8b5..b23a9cbef 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,4 +1,4 @@ -use std::{num::NonZeroU32, str::FromStr}; +use std::num::NonZeroU32; use bitwarden_crypto::{AsymmetricEncString, EncString}; use uuid::Uuid; @@ -7,20 +7,11 @@ use crate::UniffiCustomTypeConverter; uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); - -uniffi::custom_type!(AsymmetricEncString, String); - -impl UniffiCustomTypeConverter for AsymmetricEncString { - type Builtin = String; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::from_str(&val).map_err(|e| e.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.to_string() - } -} +uniffi::ffi_converter_forward!( + AsymmetricEncString, + bitwarden_crypto::UniFfiTag, + crate::UniFfiTag +); type DateTime = chrono::DateTime; uniffi::custom_type!(DateTime, std::time::SystemTime); From d282ab5dc4f8dd955c76600ee1bfafce51c5f03d Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 13 Feb 2024 02:26:13 -0800 Subject: [PATCH 285/378] Add dockerfile to renovate (#609) Add Dockerfile to renovate config. Needed to keep the base Rust image up-to-date. --- .github/renovate.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index ddfc900dc..0e2492512 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -2,7 +2,7 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["github>bitwarden/renovate-config:non-pinned"], "separateMajorMinor": true, - "enabledManagers": ["cargo", "github-actions", "npm", "nuget"], + "enabledManagers": ["cargo", "dockerfile", "github-actions", "npm", "nuget"], "packageRules": [ { "matchManagers": ["cargo"], @@ -10,6 +10,11 @@ "matchUpdateTypes": ["minor", "patch"], "groupName": "pyo3 non-major" }, + { + "groupName": "dockerfile minor", + "matchManagers": ["dockerfile"], + "matchUpdateTypes": ["minor", "patch"] + }, { "groupName": "gh minor", "matchManagers": ["github-actions"], From 1b636e3601684cd7df01a3fa5be1b3da2a3c999b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 11:38:08 +0100 Subject: [PATCH 286/378] [PM-6274] [deps]: Update rust Docker tag to v1.76 (#611) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | rust | stage | minor | `1.73` -> `1.76` | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). [PM-6274](https://bitwarden.atlassian.net/browse/PM-6274) [PM-6274]: https://bitwarden.atlassian.net/browse/PM-6274?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Dockerfile b/crates/bws/Dockerfile index d75494648..f50a3e7a6 100644 --- a/crates/bws/Dockerfile +++ b/crates/bws/Dockerfile @@ -1,7 +1,7 @@ ############################################### # Build stage # ############################################### -FROM --platform=$BUILDPLATFORM rust:1.73 AS build +FROM --platform=$BUILDPLATFORM rust:1.76 AS build # Docker buildx supplies the value for this arg ARG TARGETPLATFORM From 1076d84f031e3b4f35576bbb82fc771016fd6e29 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 13:53:27 +0100 Subject: [PATCH 287/378] [deps]: Update Rust crate clap to 4.5.0 (#603) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap](https://togithub.com/clap-rs/clap) | dependencies | patch | `4.4.18` -> `4.5.0` | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index cf28447d3..522f93580 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.71" [dependencies] -clap = { version = "4.4.18", features = ["derive"] } +clap = { version = "4.5.0", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "3.0.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 068094039..6cf5a909d 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.4.18", features = ["derive", "env"] } +clap = { version = "4.5.0", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.11.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 2ceab6499..8fc72f3ae 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.34", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.4.18", features = ["derive", "env", "string"] } +clap = { version = "4.5.0", features = ["derive", "env", "string"] } clap_complete = "4.4.10" color-eyre = "0.6" comfy-table = "^7.1.0" From f509a4ecdf88a92f006c551678d6d87f883c16e5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:14:21 +0100 Subject: [PATCH 288/378] [deps]: Update Rust crate clap_complete to 4.5.0 (#604) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap_complete](https://togithub.com/clap-rs/clap) ([source](https://togithub.com/clap-rs/clap/tree/HEAD/clap_complete)) | dependencies | patch | `4.4.10` -> `4.5.0` | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- crates/bws/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 8fc72f3ae..782d0557f 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -21,7 +21,7 @@ chrono = { version = "0.4.34", features = [ "std", ], default-features = false } clap = { version = "4.5.0", features = ["derive", "env", "string"] } -clap_complete = "4.4.10" +clap_complete = "4.5.0" color-eyre = "0.6" comfy-table = "^7.1.0" directories = "5.0.1" From 16f4cc5b78be2f9cfcbd80d41fccb4ce774e0134 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Tue, 13 Feb 2024 10:20:20 -0500 Subject: [PATCH 289/378] SM-1098: Update Python Wrapper README Instructions (#592) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ``` ## Objective Update the Python Wrapper README, now that we are using [maturin](https://pypi.org/project/maturin). --- languages/python/.gitignore | 1 + languages/python/README.md | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/languages/python/.gitignore b/languages/python/.gitignore index baa13a078..495f6296b 100644 --- a/languages/python/.gitignore +++ b/languages/python/.gitignore @@ -1,3 +1,4 @@ *.egg-info bitwarden_py*.so __pycache__ +.venv diff --git a/languages/python/README.md b/languages/python/README.md index f41fd8a12..e5fe5ae70 100644 --- a/languages/python/README.md +++ b/languages/python/README.md @@ -33,3 +33,26 @@ Set the `ORGANIZATION_ID` and `ACCESS_TOKEN` environment variables to your organ ```bash python3 ./example.py ``` + +# Using Virtual Environments + +If you would like to build & run the script within a virtual environment you can do the following. + +## Build + +```bash +npm run schemas # generate schemas.py + +cd languages/python/ +python3 -m venv .venv +maturin develop +``` + +## Run + +```bash +source .venv/bin/activate +python3 ./example.py + +deactivate # run this to close the virtual session +``` From 5a9411984dcc2694fbadb4c6910025339c89ffd7 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 13 Feb 2024 20:41:39 +0100 Subject: [PATCH 290/378] Expose exporters for mobile (#612) We forgot to expose the ClientsExporters in the uniffi bindings. --- crates/bitwarden-uniffi/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 13253d9a6..b29441fdd 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -20,7 +20,7 @@ pub mod docs; use crypto::ClientCrypto; use error::Result; use platform::ClientPlatform; -use tool::ClientGenerators; +use tool::{ClientExporters, ClientGenerators}; use vault::ClientVault; #[derive(uniffi::Object)] @@ -53,6 +53,11 @@ impl Client { Arc::new(ClientGenerators(self)) } + /// Exporters + pub fn exporters(self: Arc) -> Arc { + Arc::new(ClientExporters(self)) + } + /// Auth operations pub fn auth(self: Arc) -> Arc { Arc::new(ClientAuth(self)) From cfced90327c06dd0963b9102225f0bec31015e0b Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 13 Feb 2024 21:30:16 +0100 Subject: [PATCH 291/378] Update readme (#610) Update the readme to better reflect the current state of the SDK. --- README.md | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9e3aa325f..bab08af9a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,16 @@ -# Bitwarden Secrets Manager SDK +# Bitwarden SDK -This repository houses the Bitwarden Secrets Manager SDK. The core SDK is written in Rust and -provides a Rust API, CLI and Node-API bindings. In the future more language bindings might be added. +This repository houses the Bitwarden SDKs. We currently provide a public Secrets Manager SDK and an +internal SDK for the Bitwarden Password Manager which is used for the native mobile applications. +The SDK is written in Rust and provides a Rust API, CLI and various language bindings. + +### Disclaimer + +The password manager SDK is not intended for public use and is not supported by Bitwarden at this +stage. It is solely intended to centralize the business logic and to provide a single source of +truth for the internal applications. As the SDK evolves into a more stable and feature complete +state we will re-evaluate the possibility of publishing stable bindings for the public. **The +password manager interface is unstable and will change without warning.** # We're Hiring! @@ -17,7 +26,8 @@ cargo build ## Crates -The project is structured as a monorepo using cargo workspaces. +The project is structured as a monorepo using cargo workspaces. Some of the more noteworthy crates +are: - [`bitwarden`](./crates/bitwarden/): Rust friendly API for interacting with the secrets manager. - [`bitwarden-api-api`](./crates/bitwarden-api-api/): Auto-generated API bindings for the API @@ -28,7 +38,8 @@ The project is structured as a monorepo using cargo workspaces. - [`bitwarden-json`](./crates/bitwarden-json/): JSON wrapper around the `bitwarden` crate. Powers the other language bindings. - [`bitwarden-napi`](./crates/bitwarden-napi/): Node-API bindings. -- [`bws`](./crates/bws/): CLI for interacting with the secrets manager. +- [`bws`](./crates/bws/): CLI for interacting with the [Bitwarden Secrets Manager][secrets-manager]. + Review the [CLI documentation][bws-help]. - [`sdk-schemas`](./crates/sdk-schemas/): Generator for the _json schemas_. ## Schemas @@ -65,21 +76,15 @@ ASPNETCORE_ENVIRONMENT=development dotnet swagger tofile --output ../../identity ### OpenApi Generator -Runs from the root of the SDK project. +To generate a new version of the bindings run the following script from the root of the SDK project. ```bash ./support/build-api.sh ``` -OpenApi Generator works using templates, we have customized our templates to work better with our -codebase. - -- https://github.com/OpenAPITools/openapi-generator/issues/10977 -- https://github.com/OpenAPITools/openapi-generator/issues/12464 - -There is also a scenario where we have a negative integer enum which completely breaks the openapi -generation. In that case we excluded the file from being generated and manually patched it. -`crates/bitwarden-api-api/src/models/organization_user_status_type.rs` +This project uses customized templates which lives in the `support/openapi-templates` directory. +These templates resolves some outstanding issues we've experienced with the rust generator. But we +strive towards modifying the templates as little as possible to ease future upgrades. -The hope going forward is that we can continue to use the generator with minimal manual -intervention. +[secrets-manager]: https://bitwarden.com/products/secrets-manager/ +[bws-help]: https://bitwarden.com/help/secrets-manager-cli/ From c03bcf5521bc2da05e6c9ab6e1e29c8a8cebe862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 15 Feb 2024 12:43:23 +0100 Subject: [PATCH 292/378] [DEVOPS-1814] Fix SM CLI for ubuntu 20.04 (#613) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective https://bitwarden.atlassian.net/browse/DEVOPS-1814 https://bitwarden.atlassian.net/browse/SM-1113 ## Code changes - **.github/workflows/build-cli.yml:** Change runner for linux CLI build for ubuntu-20.04 ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/build-cli.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 970db7396..4f1404b6e 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -53,10 +53,10 @@ jobs: - os: windows-2022 target: aarch64-pc-windows-msvc - - os: ubuntu-22.04 + - os: ubuntu-20.04 target: x86_64-unknown-linux-gnu - - os: ubuntu-22.04 + - os: ubuntu-20.04 target: aarch64-unknown-linux-gnu steps: - name: Checkout repo From 5a0575e722a832c5ba481be0afb94e9ac8119937 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Thu, 15 Feb 2024 14:00:32 -0500 Subject: [PATCH 293/378] SM-1082: Add SM State to Go SDK Wrapper (#559) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add the ability to easily use SM state in Go to the `bitwarden_client.go`. ## Code changes - **bitwarden_client.go:** Add the `statePath` parameter - **example.go:** Set state in the example ## Before you submit - Please add **unit tests** where it makes sense to do so --- languages/go/README.md | 6 ++++-- languages/go/bitwarden_client.go | 4 ++-- languages/go/example/example.go | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/languages/go/README.md b/languages/go/README.md index e57badf7e..cea02e282 100644 --- a/languages/go/README.md +++ b/languages/go/README.md @@ -36,10 +36,12 @@ bitwardenClient, _ := sdk.NewBitwardenClient(&apiURL, &identityURL) ### Login -To login using an access token: +To login using an access token. Define some `statePath` and pass it to use state, or pass `nil` instead to not use state. ```go -apiKeyLogin, err := bitwardenClient.AccessTokenLogin(accessToken) +statePath := os.Getenv("STATE_PATH") + +err := bitwardenClient.AccessTokenLogin(accessToken, &statePath) ``` --- diff --git a/languages/go/bitwarden_client.go b/languages/go/bitwarden_client.go index 5e1108ce1..bd236de71 100644 --- a/languages/go/bitwarden_client.go +++ b/languages/go/bitwarden_client.go @@ -45,8 +45,8 @@ func NewBitwardenClient(apiURL *string, identityURL *string) (*BitwardenClient, }, nil } -func (c *BitwardenClient) AccessTokenLogin(accessToken string) error { - req := AccessTokenLoginRequest{AccessToken: accessToken} +func (c *BitwardenClient) AccessTokenLogin(accessToken string, statePath *string) error { + req := AccessTokenLoginRequest{AccessToken: accessToken, StateFile: statePath} command := Command{AccessTokenLogin: &req} responseStr, err := c.commandRunner.RunCommand(command) diff --git a/languages/go/example/example.go b/languages/go/example/example.go index 154c14618..deb353565 100644 --- a/languages/go/example/example.go +++ b/languages/go/example/example.go @@ -19,11 +19,15 @@ func main() { organizationIDStr := os.Getenv("ORGANIZATION_ID") projectName := os.Getenv("PROJECT_NAME") + // Configuring the statePath is optional, pass nil + // in AccessTokenLogin() to not use state + statePath := os.Getenv("STATE_PATH") + if projectName == "" { projectName = "NewTestProject" // default value } - err := bitwardenClient.AccessTokenLogin(accessToken) + err := bitwardenClient.AccessTokenLogin(accessToken, &statePath) if err != nil { panic(err) } From 50078bee16a1017c5f1284f5d2475f83062651ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:29:41 +0100 Subject: [PATCH 294/378] [deps]: Update Rust crate clap to 4.5.1 (#617) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [clap](https://togithub.com/clap-rs/clap) | dependencies | patch | `4.5.0` -> `4.5.1` | --- ### Release Notes
clap-rs/clap (clap) ### [`v4.5.1`](https://togithub.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#451---2024-02-16) [Compare Source](https://togithub.com/clap-rs/clap/compare/v4.5.0...v4.5.1) ##### Fixes - *(error)* Include suggestion to add `--` even if there is a "did you mean" so long as `last` or `trailing_var_arg` is used
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bw/Cargo.toml | 2 +- crates/bws/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0562c76fe..920f2bf2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -730,9 +730,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -740,9 +740,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 522f93580..0c32ce556 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" rust-version = "1.71" [dependencies] -clap = { version = "4.5.0", features = ["derive"] } +clap = { version = "4.5.1", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "3.0.0" diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 6cf5a909d..3d2762ac3 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -13,7 +13,7 @@ Bitwarden Password Manager CLI keywords = ["bitwarden", "password-manager", "cli"] [dependencies] -clap = { version = "4.5.0", features = ["derive", "env"] } +clap = { version = "4.5.1", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.11.1" inquire = "0.6.2" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 782d0557f..2a0a13f49 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -20,7 +20,7 @@ chrono = { version = "0.4.34", features = [ "clock", "std", ], default-features = false } -clap = { version = "4.5.0", features = ["derive", "env", "string"] } +clap = { version = "4.5.1", features = ["derive", "env", "string"] } clap_complete = "4.5.0" color-eyre = "0.6" comfy-table = "^7.1.0" From d5c04a99d84d2957fbb90078791442371c7e3833 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:00:02 +0100 Subject: [PATCH 295/378] [deps]: Lock file maintenance (#619) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Update | Change | |---|---| | lockFileMaintenance | All locks refreshed | 🔧 This Pull Request updates lock files to use the latest dependency versions. --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://togithub.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 129 +++++++++++----------- crates/bitwarden-napi/package-lock.json | 12 +- languages/js/sdk-client/package-lock.json | 6 +- package-lock.json | 12 +- 4 files changed, 80 insertions(+), 79 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 920f2bf2a..7efce8973 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arc-swap" @@ -158,7 +158,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -218,7 +218,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -571,9 +571,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" [[package]] name = "bw" @@ -752,9 +752,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "299353be8209bd133b049bf1c63582d184a8b39fd9c04f15fe65f50f88bdfe6c" +checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" dependencies = [ "clap", ] @@ -768,7 +768,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -938,9 +938,9 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -1046,7 +1046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -1225,9 +1225,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e7cf40684ae96ade6232ed84582f40ce0a66efcd43a5117aef610534f8e0b8" +checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" dependencies = [ "anstream", "anstyle", @@ -1389,7 +1389,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -1540,9 +1540,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" [[package]] name = "hkdf" @@ -2015,9 +2015,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.15.1" +version = "2.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43792514b0c95c5beec42996da0c1b39265b02b75c97baa82d163d3ef55cbfa7" +checksum = "02bd92040344a83763379b122f4e714932ccaa700439e647f1e90481dd1999cb" dependencies = [ "bitflags 2.4.2", "ctor", @@ -2029,29 +2029,29 @@ dependencies = [ [[package]] name = "napi-build" -version = "2.1.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b4532cf86bfef556348ac65e561e3123879f0e7566cca6d43a6ff5326f13df" +checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43" [[package]] name = "napi-derive" -version = "2.15.1" +version = "2.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d56bb899c164ab1be5e542ae7db8b26750c864bf2eef07295f17754e6358777" +checksum = "bef56a31cf81a1d183aa991c85128e6f27c312b72227e506b1854068c2ac7d53" dependencies = [ "cfg-if", "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] name = "napi-derive-backend" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf2d74ac66fd1cccb646be75fdd1c1dce8acfe20a68f61566a31da0d3eb9786" +checksum = "d03b8f403a37007cad225039fc0323b961bb40d697eea744140920ebb689ff1d" dependencies = [ "convert_case", "once_cell", @@ -2059,7 +2059,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2348,9 +2348,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plain" @@ -2475,7 +2475,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2487,7 +2487,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2666,16 +2666,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2795,9 +2796,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "safemem" @@ -2879,7 +2880,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2931,9 +2932,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] @@ -2955,7 +2956,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2999,7 +3000,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3025,9 +3026,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.31" +version = "0.9.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf8a49373e98a4c5f0ceb5d05aa7c648d75f63774981ed95b7c7443bbd50c6e" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" dependencies = [ "indexmap 2.2.3", "itoa", @@ -3206,7 +3207,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3237,9 +3238,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" dependencies = [ "proc-macro2", "quote", @@ -3313,9 +3314,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" dependencies = [ "smawk", "unicode-linebreak", @@ -3339,7 +3340,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3423,7 +3424,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3482,9 +3483,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.4" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" +checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" dependencies = [ "indexmap 2.2.3", "serde", @@ -3665,7 +3666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72775b3afa6adb30e0c92b3107858d2fcb0ff1a417ac242db1f648b0e2dd0ef2" dependencies = [ "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3698,7 +3699,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.48", + "syn 2.0.49", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3847,7 +3848,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-shared", ] @@ -3881,7 +3882,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3914,7 +3915,7 @@ checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -4116,9 +4117,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.39" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" +checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401" dependencies = [ "memchr", ] @@ -4174,7 +4175,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] diff --git a/crates/bitwarden-napi/package-lock.json b/crates/bitwarden-napi/package-lock.json index 25da5b8e5..c1c3f1a86 100644 --- a/crates/bitwarden-napi/package-lock.json +++ b/crates/bitwarden-napi/package-lock.json @@ -30,9 +30,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -95,9 +95,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", - "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dev": true, "peer": true, "dependencies": { diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index aec6ec5e0..036117a72 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.15.tgz", - "integrity": "sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==", + "version": "18.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.17.tgz", + "integrity": "sha512-SzyGKgwPzuWp2SHhlpXKzCX0pIOfcI4V2eF37nNBJOhwlegQ83omtVQ1XxZpDE06V/d6AQvfQdPfnw0tRC//Ng==", "dev": true, "dependencies": { "undici-types": "~5.26.4" diff --git a/package-lock.json b/package-lock.json index d6befe7f3..2c4b9b478 100644 --- a/package-lock.json +++ b/package-lock.json @@ -145,9 +145,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -346,9 +346,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.17.tgz", - "integrity": "sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dev": true, "peer": true, "dependencies": { From ff94313e209daebb1ccd5fb7b576256ae5a767b2 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:40:28 -0800 Subject: [PATCH 296/378] Use non-root user in Docker (#571) ## Type of change - [ ] Bug fix - [x] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Use a non-root user in Docker. There doesn't seem to be an agreed upon standard for what to name the non-root user, so I named it _app_, as I followed the general guidance from [this MS blog post](https://devblogs.microsoft.com/dotnet/securing-containers-with-rootless/). A `BWS_CONFIG_FILE` environment variable was added to `bws` as well to make it easier to avoid guessing where the correct config file dir is if you are unaware of the _app_ user's name (and therefor, their home directory). ## Code changes - **crates/bws/Dockerfile:** Use a non-root user. - **crates/bws/README.md:** Document using the CLI with Docker. - **crates/bws/src/main.rs:** Add `BWS_CONFIG_FILE` environment variable. - **crates/bws/CHANGELOG.md:** Update changelog. ## Before you submit - Please add **unit tests** where it makes sense to do so --- crates/bws/CHANGELOG.md | 1 + crates/bws/Dockerfile | 9 ++++++++- crates/bws/README.md | 18 ++++++++++++++++++ crates/bws/src/main.rs | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index d5ba27061..2bb431485 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -10,6 +10,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed - Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. +- Add a `BWS_CONFIG_FILE` environment variable to specify the location of the config file (#571) ## [0.4.0] - 2023-12-21 diff --git a/crates/bws/Dockerfile b/crates/bws/Dockerfile index f50a3e7a6..4f16f8e6c 100644 --- a/crates/bws/Dockerfile +++ b/crates/bws/Dockerfile @@ -30,5 +30,12 @@ WORKDIR /usr/local/bin COPY --from=build /app/target/release/bws . COPY --from=build /etc/ssl/certs /etc/ssl/certs -ENTRYPOINT ["bws"] +# Create a non-root user +RUN useradd -ms /bin/bash app + +# Switch to the non-root user +USER app +WORKDIR /home/app + +ENTRYPOINT ["bws"] diff --git a/crates/bws/README.md b/crates/bws/README.md index 11ea23814..cb9c268fb 100644 --- a/crates/bws/README.md +++ b/crates/bws/README.md @@ -44,3 +44,21 @@ echo 'source <(/path/to/bws completions bash)' >> ~/.bashrc For more detailed documentation, please refer to the [Secrets Manager CLI help article](https://bitwarden.com/help/secrets-manager-cli/). + +## Docker + +We also provide a docker image preloaded with the `bws` cli. + +```bash +# From the root of the repository +docker build -f crates/bws/Dockerfile -t bitwarden/bws . + +docker run --rm -it bitwarden/bws --help +``` + +To use a configuration file, utilize docker +[bind mounting](https://docs.docker.com/storage/bind-mounts/) to expose it to the container: + +```bash +docker run --rm -it -v "$HOME"/.bws:/home/app/.bws bitwarden/bws --help +``` diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index e55df5082..cb130b52c 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -47,6 +47,7 @@ struct Cli { short = 'f', long, global = true, + env = CONFIG_FILE_KEY_VAR_NAME, help = format!("[default: ~/{}/{}] Config file to use", config::DIRECTORY, config::FILENAME) )] config_file: Option, @@ -228,6 +229,7 @@ async fn main() -> Result<()> { } const ACCESS_TOKEN_KEY_VAR_NAME: &str = "BWS_ACCESS_TOKEN"; +const CONFIG_FILE_KEY_VAR_NAME: &str = "BWS_CONFIG_FILE"; const PROFILE_KEY_VAR_NAME: &str = "BWS_PROFILE"; const SERVER_URL_KEY_VAR_NAME: &str = "BWS_SERVER_URL"; From 0366e860dac04dfca2101dd95b085d96b97d6a90 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Wed, 21 Feb 2024 18:53:04 +0100 Subject: [PATCH 297/378] Rename ruby SDK to bitwarden-sdk-secrets (#618) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Rename the ruby sdk to `bitwarden-sdk-secrets` to denote it's the secrets manager SDK. Updates the Also includes #565 since it won't run without that change. ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> --- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/publish-ruby.yml | 16 +++---- languages/ruby/.gitignore | 3 +- languages/ruby/README.md | 42 +++++++++++++++---- languages/ruby/bitwarden_sdk_secrets/Gemfile | 10 +++++ .../Rakefile | 3 ++ .../bitwarden-sdk-secrets.gemspec} | 6 +-- .../lib/bitwarden-sdk-secrets.rb} | 6 +-- .../lib/bitwarden_error.rb | 2 +- .../lib/bitwarden_lib.rb | 2 +- .../lib/command_runner.rb | 2 +- .../lib/extended_schemas/schemas.rb | 2 +- .../lib/projects.rb | 2 +- .../lib/secrets.rb | 2 +- .../lib/version.rb | 2 +- .../sig/bitwarden-sdk.rbs | 0 .../sig/bitwarden_settings.rbs | 0 .../sig/command_runner.rbs | 0 .../sig/projects_client.rbs | 0 .../sig/sdk.rbs | 0 .../sig/secrets_client.rbs | 0 .../spec/settings_spec.rb | 15 +++++++ languages/ruby/examples/example.rb | 6 +-- support/scripts/schemas.ts | 2 +- 24 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 languages/ruby/bitwarden_sdk_secrets/Gemfile rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/Rakefile (69%) rename languages/ruby/{bitwarden_sdk/bitwarden-sdk.gemspec => bitwarden_sdk_secrets/bitwarden-sdk-secrets.gemspec} (93%) rename languages/ruby/{bitwarden_sdk/lib/bitwarden-sdk.rb => bitwarden_sdk_secrets/lib/bitwarden-sdk-secrets.rb} (91%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/bitwarden_error.rb (85%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/bitwarden_lib.rb (98%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/command_runner.rb (91%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/extended_schemas/schemas.rb (98%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/projects.rb (99%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/secrets.rb (99%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/lib/version.rb (67%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/bitwarden-sdk.rbs (100%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/bitwarden_settings.rbs (100%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/command_runner.rbs (100%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/projects_client.rbs (100%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/sdk.rbs (100%) rename languages/ruby/{bitwarden_sdk => bitwarden_sdk_secrets}/sig/secrets_client.rbs (100%) create mode 100644 languages/ruby/bitwarden_sdk_secrets/spec/settings_spec.rb diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 025b85105..301a9a805 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -61,7 +61,7 @@ jobs: uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: schemas.rb - path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk/lib/schemas.rb + path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk_secrets/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 3dce457b2..e8c2f8254 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -31,7 +31,7 @@ jobs: uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 with: name: schemas.rb - path: languages/ruby/bitwarden_sdk/lib + path: languages/ruby/bitwarden_sdk_secrets/lib - name: Download x86_64-apple-darwin files uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 @@ -59,22 +59,22 @@ jobs: - name: Copy lib files run: | - mkdir -p languages/ruby/bitwarden_sdk/lib/macos-arm64 - mkdir -p languages/ruby/bitwarden_sdk/lib/linux-x64 - mkdir -p languages/ruby/bitwarden_sdk/lib/macos-x64 - mkdir -p languages/ruby/bitwarden_sdk/lib/windows-x64 + mkdir -p languages/ruby/bitwarden_sdk_secrets/lib/macos-arm64 + mkdir -p languages/ruby/bitwarden_sdk_secrets/lib/linux-x64 + mkdir -p languages/ruby/bitwarden_sdk_secrets/lib/macos-x64 + mkdir -p languages/ruby/bitwarden_sdk_secrets/lib/windows-x64 platforms=("macos-arm64" "linux-x64" "macos-x64" "windows-x64") files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") for ((i=0; i<${#platforms[@]}; i++)); do - cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk/lib/${platforms[$i]}/${files[$i]}" + cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk_secrets/lib/${platforms[$i]}/${files[$i]}" done shell: bash - name: Build gem run: gem build bitwarden-sdk.gemspec - working-directory: languages/ruby/bitwarden_sdk + working-directory: languages/ruby/bitwarden_sdk_secrets - name: Push gem to Rubygems run: | @@ -85,4 +85,4 @@ jobs: gem push *.gem env: GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }} - working-directory: languages/ruby/bitwarden_sdk + working-directory: languages/ruby/bitwarden_sdk_secrets diff --git a/languages/ruby/.gitignore b/languages/ruby/.gitignore index f0e7bd4c1..92b76b424 100644 --- a/languages/ruby/.gitignore +++ b/languages/ruby/.gitignore @@ -1,3 +1,4 @@ *.lock *.gem -bitwarden_sdk/lib/schemas.rb +bitwarden_sdk_secrets/lib/schemas.rb +bitwarden_sdk_secrets/pkg diff --git a/languages/ruby/README.md b/languages/ruby/README.md index d02d5c500..e9fb61e0c 100644 --- a/languages/ruby/README.md +++ b/languages/ruby/README.md @@ -1,24 +1,23 @@ # Bitwarden Secrets Manager SDK -Ruby bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might be missing some functionality. +Ruby bindings for interacting with the [Bitwarden Secrets Manager]. This is a beta release and might +be missing some functionality. ## Installation Requirements: Ruby >= 3.0 -Install gem: `gem install bitwarden-sdk` - -Import it: require 'bitwarden-sdk' +Install gem: `gem install bitwarden-sdk-secrets` +Import it: require 'bitwarden-sdk-secrets' ## Usage -To interact with client first you need to obtain access token from Bitwarden. -Client will be initialized with default client settings if they are not provided -via env variables. +To interact with client first you need to obtain access token from Bitwarden. Client will be +initialized with default client settings if they are not provided via env variables. ```ruby -require 'bitwarden-sdk' +require 'bitwarden-sdk-secrets' # then you can initialize BitwardenSettings: bitwarden_settings = BitwardenSDK::BitwardenSettings.new( @@ -34,6 +33,7 @@ puts response ``` After successful authorization you can interact with client to manage your projects and secrets. + ```ruby # CREATE project @@ -61,6 +61,7 @@ puts response ``` Similarly, you interact with secrets: + ```ruby # CREATE secret key = 'AWS-SES' @@ -92,4 +93,29 @@ puts response response = bw_client.secrets_client.delete_secret([secret_id]) puts response ``` + +## Development + +```bash +# Build and copy the bitwarden-c library +cargo build --package bitwarden-c +cp ../../target/debug/libbitwarden_c.dylib ./bitwarden_sdk_secrets/lib/macos-arm64/libbitwarden_c.dylib + +# Install ruby dependencies +cd ./bitwarden_sdk_secrets +bundle install + +# Install the gem +bundle exec rake install + +## Run example tests +cd .. +export ACCESS_TOKEN="" +export ORGANIZATION_ID="" + +export API_URL=https://localhost:8080/api +export IDENTITY_URL=https://localhost:8080/identity +ruby examples/example.rb +``` + [Bitwarden Secrets Manager]: https://bitwarden.com/products/secrets-manager/ diff --git a/languages/ruby/bitwarden_sdk_secrets/Gemfile b/languages/ruby/bitwarden_sdk_secrets/Gemfile new file mode 100644 index 000000000..0f3963489 --- /dev/null +++ b/languages/ruby/bitwarden_sdk_secrets/Gemfile @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# Specify your gem's dependencies in exmp.gemspec +gemspec + +gem "rake", "~> 13.0" +gem "rspec", "~> 3.0" +gem "rubocop", "~> 1.21" diff --git a/languages/ruby/bitwarden_sdk/Rakefile b/languages/ruby/bitwarden_sdk_secrets/Rakefile similarity index 69% rename from languages/ruby/bitwarden_sdk/Rakefile rename to languages/ruby/bitwarden_sdk_secrets/Rakefile index 192414345..30550c5de 100644 --- a/languages/ruby/bitwarden_sdk/Rakefile +++ b/languages/ruby/bitwarden_sdk_secrets/Rakefile @@ -2,6 +2,9 @@ require "bundler/gem_tasks" require "rubocop/rake_task" +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new RuboCop::RakeTask.new diff --git a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec b/languages/ruby/bitwarden_sdk_secrets/bitwarden-sdk-secrets.gemspec similarity index 93% rename from languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec rename to languages/ruby/bitwarden_sdk_secrets/bitwarden-sdk-secrets.gemspec index d11a57f38..457e60a3e 100644 --- a/languages/ruby/bitwarden_sdk/bitwarden-sdk.gemspec +++ b/languages/ruby/bitwarden_sdk_secrets/bitwarden-sdk-secrets.gemspec @@ -3,8 +3,8 @@ require_relative 'lib/version' Gem::Specification.new do |spec| - spec.name = 'bitwarden-sdk' - spec.version = BitwardenSDK::VERSION + spec.name = 'bitwarden-sdk-secrets' + spec.version = BitwardenSDKSecrets::VERSION spec.authors = ['Bitwarden Inc.'] spec.email = ['hello@bitwarden_sdk.com'] @@ -21,7 +21,7 @@ Gem::Specification.new do |spec| # The `git ls-files -z` loads the files in the RubyGem that have been added into git. spec.files = Dir.chdir(__dir__) do `git ls-files -z`.split("\x0").reject do |f| - (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor]) + (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile]) end end diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden-sdk-secrets.rb similarity index 91% rename from languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/bitwarden-sdk-secrets.rb index b023402da..15cd115d1 100644 --- a/languages/ruby/bitwarden_sdk/lib/bitwarden-sdk.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden-sdk-secrets.rb @@ -11,7 +11,7 @@ require_relative 'projects' require_relative 'secrets' -module BitwardenSDK +module BitwardenSDKSecrets class BitwardenSettings attr_accessor :api_url, :identity_url @@ -43,8 +43,8 @@ def initialize(bitwarden_settings) @secrets_client = SecretsClient.new(@command_runner) end - def access_token_login(access_token) - access_token_request = AccessTokenLoginRequest.new(access_token: access_token) + def access_token_login(access_token, state_file = nil) + access_token_request = AccessTokenLoginRequest.new(access_token: access_token, state_file: state_file) @command_runner.run(SelectiveCommand.new(access_token_login: access_token_request)) nil end diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_error.rb similarity index 85% rename from languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_error.rb index ec9adf932..b2239e29b 100644 --- a/languages/ruby/bitwarden_sdk/lib/bitwarden_error.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_error.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module BitwardenSDK +module BitwardenSDKSecrets class BitwardenError < StandardError def initialize(message = 'Error getting response') super(message) diff --git a/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_lib.rb similarity index 98% rename from languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_lib.rb index 8217d87b0..05ab51421 100644 --- a/languages/ruby/bitwarden_sdk/lib/bitwarden_lib.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/bitwarden_lib.rb @@ -2,7 +2,7 @@ require 'ffi' -module BitwardenSDK +module BitwardenSDKSecrets module BitwardenLib extend FFI::Library diff --git a/languages/ruby/bitwarden_sdk/lib/command_runner.rb b/languages/ruby/bitwarden_sdk_secrets/lib/command_runner.rb similarity index 91% rename from languages/ruby/bitwarden_sdk/lib/command_runner.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/command_runner.rb index 7da2269b6..80e846a80 100644 --- a/languages/ruby/bitwarden_sdk/lib/command_runner.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/command_runner.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module BitwardenSDK +module BitwardenSDKSecrets class CommandRunner def initialize(bitwarden_sdk, handle) @bitwarden_sdk = bitwarden_sdk diff --git a/languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb b/languages/ruby/bitwarden_sdk_secrets/lib/extended_schemas/schemas.rb similarity index 98% rename from languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/extended_schemas/schemas.rb index be7ca2cbc..e2352237f 100644 --- a/languages/ruby/bitwarden_sdk/lib/extended_schemas/schemas.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/extended_schemas/schemas.rb @@ -1,5 +1,5 @@ -module BitwardenSDK +module BitwardenSDKSecrets class SelectiveCommand < Command attribute :password_login, PasswordLoginRequest.optional.default(nil) attribute :api_key_login, APIKeyLoginRequest.optional.default(nil) diff --git a/languages/ruby/bitwarden_sdk/lib/projects.rb b/languages/ruby/bitwarden_sdk_secrets/lib/projects.rb similarity index 99% rename from languages/ruby/bitwarden_sdk/lib/projects.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/projects.rb index 4363fcb9e..957a7d31d 100644 --- a/languages/ruby/bitwarden_sdk/lib/projects.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/projects.rb @@ -2,7 +2,7 @@ require_relative 'bitwarden_error' -module BitwardenSDK +module BitwardenSDKSecrets class ProjectsClient def initialize(command_runner) @command_runner = command_runner diff --git a/languages/ruby/bitwarden_sdk/lib/secrets.rb b/languages/ruby/bitwarden_sdk_secrets/lib/secrets.rb similarity index 99% rename from languages/ruby/bitwarden_sdk/lib/secrets.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/secrets.rb index 0eca98993..709d8f8b1 100644 --- a/languages/ruby/bitwarden_sdk/lib/secrets.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/secrets.rb @@ -2,7 +2,7 @@ require 'json' -module BitwardenSDK +module BitwardenSDKSecrets class SecretsClient def initialize(command_runner) @command_runner = command_runner diff --git a/languages/ruby/bitwarden_sdk/lib/version.rb b/languages/ruby/bitwarden_sdk_secrets/lib/version.rb similarity index 67% rename from languages/ruby/bitwarden_sdk/lib/version.rb rename to languages/ruby/bitwarden_sdk_secrets/lib/version.rb index 1fd8c02c1..199ec8ca6 100644 --- a/languages/ruby/bitwarden_sdk/lib/version.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -module BitwardenSDK +module BitwardenSDKSecrets VERSION = '0.0.0' end diff --git a/languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/bitwarden-sdk.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/bitwarden-sdk.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/bitwarden-sdk.rbs diff --git a/languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/bitwarden_settings.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/bitwarden_settings.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/bitwarden_settings.rbs diff --git a/languages/ruby/bitwarden_sdk/sig/command_runner.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/command_runner.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/command_runner.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/command_runner.rbs diff --git a/languages/ruby/bitwarden_sdk/sig/projects_client.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/projects_client.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/projects_client.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/projects_client.rbs diff --git a/languages/ruby/bitwarden_sdk/sig/sdk.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/sdk.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/sdk.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/sdk.rbs diff --git a/languages/ruby/bitwarden_sdk/sig/secrets_client.rbs b/languages/ruby/bitwarden_sdk_secrets/sig/secrets_client.rbs similarity index 100% rename from languages/ruby/bitwarden_sdk/sig/secrets_client.rbs rename to languages/ruby/bitwarden_sdk_secrets/sig/secrets_client.rbs diff --git a/languages/ruby/bitwarden_sdk_secrets/spec/settings_spec.rb b/languages/ruby/bitwarden_sdk_secrets/spec/settings_spec.rb new file mode 100644 index 000000000..9db0e340d --- /dev/null +++ b/languages/ruby/bitwarden_sdk_secrets/spec/settings_spec.rb @@ -0,0 +1,15 @@ +require 'schemas' +require 'extended_schemas/schemas' + +describe ClientSettings do + it "test" do + client_settings = ClientSettings.new( + api_url: nil, + identity_url: nil, + user_agent: 'Bitwarden RUBY-SDK', + device_type: nil + ) + + expect(client_settings.to_dynamic.compact.to_json).to eq('{"userAgent":"Bitwarden RUBY-SDK"}') + end +end diff --git a/languages/ruby/examples/example.rb b/languages/ruby/examples/example.rb index 09192aa5d..3c8e2045d 100644 --- a/languages/ruby/examples/example.rb +++ b/languages/ruby/examples/example.rb @@ -1,5 +1,5 @@ # NOTE - for example purpose only - import gem instead -require 'bitwarden-sdk' +require 'bitwarden-sdk-secrets' token = ENV['ACCESS_TOKEN'] organization_id = ENV['ORGANIZATION_ID'] @@ -8,9 +8,9 @@ api_url = ENV['API_URL'] identity_url = ENV['IDENTITY_URL'] -bitwarden_settings = BitwardenSDK::BitwardenSettings.new(api_url, identity_url) +bitwarden_settings = BitwardenSDKSecrets::BitwardenSettings.new(api_url, identity_url) -bw_client = BitwardenSDK::BitwardenClient.new(bitwarden_settings) +bw_client = BitwardenSDKSecrets::BitwardenClient.new(bitwarden_settings) response = bw_client.access_token_login(token) puts response diff --git a/support/scripts/schemas.ts b/support/scripts/schemas.ts index f045b0f5a..757878334 100644 --- a/support/scripts/schemas.ts +++ b/support/scripts/schemas.ts @@ -60,7 +60,7 @@ async function main() { }, }); - writeToFile("./languages/ruby/bitwarden_sdk/lib/schemas.rb", ruby.lines); + writeToFile("./languages/ruby/bitwarden_sdk_secrets/lib/schemas.rb", ruby.lines); const csharp = await quicktype({ inputData, From 412ae78ef5455eaf8521852d6cfefe44655b7cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 22 Feb 2024 11:45:57 +0100 Subject: [PATCH 298/378] [DEVOPS-1785] Update release pipeline for ruby sdk (#614) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective https://bitwarden.atlassian.net/browse/DEVOPS-1785 ## Code changes - **.github/workflows/build-rust-cross-platform.yml:** Trigger on push to `main`, `rc` and `hotfix-rc` - **.github/workflows/generate_schemas.yml** Trigger on push to `main`, `rc` and `hotfix-rc` - **.github/workflows/publish-ruby.yml** Publish ruby only on workflow dispatch get the artifacts from build workflows instead of triggering them - **.github/workflows/version-bump.yml** Add ruby sdk to bump version workflow ## Before you submit - Please add **unit tests** where it makes sense to do so --- .../workflows/build-rust-cross-platform.yml | 8 ++ .github/workflows/generate_schemas.yml | 6 ++ .github/workflows/publish-ruby.yml | 94 ++++++++++++------- .github/workflows/version-bump.yml | 6 ++ 4 files changed, 81 insertions(+), 33 deletions(-) diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 89b75cbab..2eb1d12a8 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -2,6 +2,14 @@ name: Build Rust Cross Platform on: workflow_call: + workflow_dispatch: + push: + branches: + - main + - rc + - hotfix-rc + paths: + - "crates/**" jobs: build_rust: diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 301a9a805..bd206b21e 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -2,6 +2,12 @@ name: Generate schemas on: workflow_call: + workflow_dispatch: + push: + branches: + - main + - rc + - hotfix-rc env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index e8c2f8254..e22217a21 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -1,23 +1,43 @@ name: Publish Ruby SDK +run-name: Publish Ruby SDK ${{ inputs.release_type }} on: - push: - branches: - - main + workflow_dispatch: + inputs: + release_type: + description: "Release Options" + required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + permissions: + id-token: write + contents: write jobs: - generate_schemas: - uses: ./.github/workflows/generate_schemas.yml + setup: + name: Setup + runs-on: ubuntu-22.04 + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - build_rust: - uses: ./.github/workflows/build-rust-cross-platform.yml + - name: Branch check + if: ${{ github.event.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 - build_ruby: - name: Build Ruby + publish_ruby: + name: Publish Ruby runs-on: ubuntu-22.04 - needs: - - generate_schemas - - build_rust + needs: setup steps: - name: Checkout Repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -27,33 +47,48 @@ jobs: with: ruby-version: 3.2 - - name: Download Ruby schemas artifact - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@main with: - name: schemas.rb + workflow: generate_schemas.yml path: languages/ruby/bitwarden_sdk_secrets/lib + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + name: schemas.rb - - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Download x86_64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main with: - name: libbitwarden_c_files-x86_64-apple-darwin + workflow: generate_schemas.yml path: temp/macos-x64 + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + name: libbitwarden_c_files-x86_64-apple-darwin - - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Download aarch64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main with: + workflow: generate_schemas.yml + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} name: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Download x86_64-unknown-linux-gnu artifact + uses: bitwarden/gh-actions/download-artifacts@main with: + workflow: generate_schemas.yml + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} name: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/linux-x64 - - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Download x86_64-pc-windows-msvc artifact + uses: bitwarden/gh-actions/download-artifacts@main with: + workflow: generate_schemas.yml + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} name: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 @@ -77,12 +112,5 @@ jobs: working-directory: languages/ruby/bitwarden_sdk_secrets - name: Push gem to Rubygems - run: | - mkdir -p $HOME/.gem - touch $HOME/.gem/credentials - chmod 0600 $HOME/.gem/credentials - printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials - gem push *.gem - env: - GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }} - working-directory: languages/ruby/bitwarden_sdk_secrets + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: rubygems/release-gem@48512b949a6517699b78f000b4f36e641d321ed3 # v1.0.0 diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index e40f68a8e..8abe4b018 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -19,6 +19,7 @@ on: - cli - napi - python-sdk + - ruby-sdk version_number: description: "New version (example: '2024.1.0')" required: true @@ -150,6 +151,11 @@ jobs: sed -i 's/version = "[0-9]\.[0-9]\.[0-9]"/version = "${{ inputs.version_number }}"/' ./languages/python/pyproject.toml sed -i 's/__version__ = "[0-9]\.[0-9]\.[0-9]"/__version__ = "${{ inputs.version_number }}"/' ./languages/python/bitwarden_sdk/__init__.py + ### ruby sdk + - name: Bump ruby-sdk Version + if: ${{ inputs.project == 'ruby-sdk' }} + run: sed -i "s/VERSION = '[0-9]\.[0-9]\.[0-9]'/VERSION = '${{ inputs.version_number }}'/" ./languages/ruby/bitwarden_sdk/lib/version.rb + ############################ # VERSION BUMP SECTION END # ############################ From d935d016c0937b2aebbef126c0c6622bee512b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 22 Feb 2024 13:58:23 +0100 Subject: [PATCH 299/378] [DEVOPS-1785] Fix Ruby publish workflow (#622) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/publish-ruby.yml:** Fix artifact parameter name, update `rubygems/release-gem` to fix publishing. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-ruby.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index e22217a21..2be1eab85 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -54,42 +54,42 @@ jobs: path: languages/ruby/bitwarden_sdk_secrets/lib workflow_conclusion: success branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - name: schemas.rb + artifacts: schemas.rb - name: Download x86_64-apple-darwin artifact uses: bitwarden/gh-actions/download-artifacts@main with: - workflow: generate_schemas.yml + workflow: build-rust-cross-platform.yml path: temp/macos-x64 workflow_conclusion: success branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - name: libbitwarden_c_files-x86_64-apple-darwin + artifacts: libbitwarden_c_files-x86_64-apple-darwin - name: Download aarch64-apple-darwin artifact uses: bitwarden/gh-actions/download-artifacts@main with: - workflow: generate_schemas.yml + workflow: build-rust-cross-platform.yml workflow_conclusion: success branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - name: libbitwarden_c_files-aarch64-apple-darwin + artifacts: libbitwarden_c_files-aarch64-apple-darwin path: temp/macos-arm64 - name: Download x86_64-unknown-linux-gnu artifact uses: bitwarden/gh-actions/download-artifacts@main with: - workflow: generate_schemas.yml + workflow: build-rust-cross-platform.yml workflow_conclusion: success branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - name: libbitwarden_c_files-x86_64-unknown-linux-gnu + artifacts: libbitwarden_c_files-x86_64-unknown-linux-gnu path: temp/linux-x64 - name: Download x86_64-pc-windows-msvc artifact uses: bitwarden/gh-actions/download-artifacts@main with: - workflow: generate_schemas.yml + workflow: build-rust-cross-platform.yml workflow_conclusion: success branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - name: libbitwarden_c_files-x86_64-pc-windows-msvc + artifacts: libbitwarden_c_files-x86_64-pc-windows-msvc path: temp/windows-x64 - name: Copy lib files @@ -108,9 +108,9 @@ jobs: shell: bash - name: Build gem - run: gem build bitwarden-sdk.gemspec + run: gem build bitwarden-sdk-secrets.gemspec working-directory: languages/ruby/bitwarden_sdk_secrets - name: Push gem to Rubygems if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: rubygems/release-gem@48512b949a6517699b78f000b4f36e641d321ed3 # v1.0.0 + uses: rubygems/release-gem@035c7c1c1c14d277318867ced5037926d2395300 # v1.0.1 From c34fe6b7dd76cf4f0b45262eaa6b52429230b4df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 22 Feb 2024 16:21:04 +0100 Subject: [PATCH 300/378] [DEVOPS-1785] Fix ruby sdk directory in version bump workflow (#623) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/version-bump.yml:** Fix ruby sdk directory name in version bump workflow ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 8abe4b018..3c6485a09 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -154,7 +154,7 @@ jobs: ### ruby sdk - name: Bump ruby-sdk Version if: ${{ inputs.project == 'ruby-sdk' }} - run: sed -i "s/VERSION = '[0-9]\.[0-9]\.[0-9]'/VERSION = '${{ inputs.version_number }}'/" ./languages/ruby/bitwarden_sdk/lib/version.rb + run: sed -i "s/VERSION = '[0-9]\.[0-9]\.[0-9]'/VERSION = '${{ inputs.version_number }}'/" ./languages/ruby/bitwarden_sdk_secrets/lib/version.rb ############################ # VERSION BUMP SECTION END # From 74eecad418e58053fc85ef634b396b4084b07889 Mon Sep 17 00:00:00 2001 From: Bitwarden DevOps <106330231+bitwarden-devops-bot@users.noreply.github.com> Date: Thu, 22 Feb 2024 10:24:50 -0500 Subject: [PATCH 301/378] Bump version to 0.1.0 (#624) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [X] Other ## Objective Automated ruby-sdk version bump to 0.1.0 --- languages/ruby/bitwarden_sdk_secrets/lib/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/ruby/bitwarden_sdk_secrets/lib/version.rb b/languages/ruby/bitwarden_sdk_secrets/lib/version.rb index 199ec8ca6..82d5fc85b 100644 --- a/languages/ruby/bitwarden_sdk_secrets/lib/version.rb +++ b/languages/ruby/bitwarden_sdk_secrets/lib/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module BitwardenSDKSecrets - VERSION = '0.0.0' + VERSION = '0.1.0' end From 71c51426dd0b28d29a913ef6e7cea03dc2c59cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 22 Feb 2024 18:09:03 +0100 Subject: [PATCH 302/378] [DEVOPS-1785] Fix publish ruby sdk workflow permissions (#625) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/publish-ruby.yml:** Add `contents: read` permission and fix indentation ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-ruby.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 2be1eab85..6614113cd 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -12,9 +12,11 @@ on: options: - Release - Dry Run - permissions: - id-token: write - contents: write + +permissions: + contents: read + pages: write + id-token: write jobs: setup: From 7724d7d073b675eee14ae0924dc128a880071145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 22 Feb 2024 22:41:49 +0100 Subject: [PATCH 303/378] [DEVOPS-1785] Replace Ruby publish composite action with individual steps (#627) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Use individual steps instead of composite action for Ruby publish to rubygem.org. Change is needed because the path where the Ruby code lives cannot be specified in `rubygems/release-gem` action. ## Code changes - **.github/workflows/publish-ruby.yml** Use individual steps instead of composite action for Ruby publish to rubygem.org. Change is needed because the path where the Ruby code lives cannot be specified in `rubygems/release-gem` action. - **.github/workflows/build-rust-cross-platform.yml:** Remove `path` in `push` trigger to build always ## Before you submit - Please add **unit tests** where it makes sense to do so --- .../workflows/build-rust-cross-platform.yml | 2 -- .github/workflows/publish-ruby.yml | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 2eb1d12a8..67c41c6f9 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -8,8 +8,6 @@ on: - main - rc - hotfix-rc - paths: - - "crates/**" jobs: build_rust: diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 6614113cd..498e62812 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -107,12 +107,27 @@ jobs: for ((i=0; i<${#platforms[@]}; i++)); do cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk_secrets/lib/${platforms[$i]}/${files[$i]}" done - shell: bash - name: Build gem run: gem build bitwarden-sdk-secrets.gemspec working-directory: languages/ruby/bitwarden_sdk_secrets - - name: Push gem to Rubygems - if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: rubygems/release-gem@035c7c1c1c14d277318867ced5037926d2395300 # v1.0.1 + - name: Set remote URL + run: | + # Attribute commits to the last committer on HEAD + git config --global user.email "106330231+bitwarden-devops-bot@users.noreply.github.com" + git config --global user.name "bitwarden-devops-bot" + git remote set-url origin "https://x-access-token:${{ github.token }}@github.com/$GITHUB_REPOSITORY" + + - name: Configure trusted publishing credentials + uses: rubygems/configure-rubygems-credentials@bc6dd217f8a4f919d6835fcfefd470ef821f5c44 # v1.0.0 + + - name: Run release rake task + if: ${{ inputs.release_type == 'Release' }} + run: bundle exec rake release + working-directory: languages/ruby/bitwarden_sdk_secrets + + - name: Wait for release to propagate + if: ${{ inputs.release_type == 'Release' }} + run: gem exec rubygems-await pkg/*.gem + working-directory: languages/ruby/bitwarden_sdk_secrets From 27ec020f22ba3a776170793ac08a0f5961f6e1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Feb 2024 12:54:12 +0100 Subject: [PATCH 304/378] [DEVOPS-1785] Fix publish Ruby workflow (#628) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Fix error from ruby release pipeline: ``` Could not find gem 'rspec (~> 3.0)' in locally installed gems. ``` ## Code changes - **.github/workflows/publish-ruby.yml:** Replace `gem build` with `bundle install` ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-ruby.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 498e62812..931981667 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -15,7 +15,6 @@ on: permissions: contents: read - pages: write id-token: write jobs: @@ -108,8 +107,8 @@ jobs: cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk_secrets/lib/${platforms[$i]}/${files[$i]}" done - - name: Build gem - run: gem build bitwarden-sdk-secrets.gemspec + - name: bundle install + run: bundle install working-directory: languages/ruby/bitwarden_sdk_secrets - name: Set remote URL From 199851b8a4278eb3ee427bf2a9aa81d03d018453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Feb 2024 16:48:00 +0100 Subject: [PATCH 305/378] [DEVOPS-1333] Add code signing to the macOS bws CLI (#535) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/build-cli.yml:** Description of what was changed and why ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/secrets/devid-app-cert.p12.gpg | Bin 0 -> 3324 bytes .github/workflows/build-cli.yml | 268 +++++++++++++++++++++++-- crates/bws/entitlements.plist | 8 + 3 files changed, 261 insertions(+), 15 deletions(-) create mode 100644 .github/secrets/devid-app-cert.p12.gpg create mode 100644 crates/bws/entitlements.plist diff --git a/.github/secrets/devid-app-cert.p12.gpg b/.github/secrets/devid-app-cert.p12.gpg new file mode 100644 index 0000000000000000000000000000000000000000..8e2e2146e238314d23c9460e75989d6517783809 GIT binary patch literal 3324 zcmV@SCNaV%#Or%konszRFi;Wb~eE&{yc>i`T$Nn z#odyov^Creleum-z#UN(Sgivs!oZq}>6Fkb4IcHKl^)sXdTdv5XHWX5e$Na-<6gGE&F18gf?oEIH&iPtIwHng8^KAS*cHAGg@3y2f%z?Mssu4-oxF{4r z8A~N;!fnE_V@wEL==H_1>itYt_=j-iACf%}lsc-G1|im$S<;njht>%9)znwj1xLwW0bI z9F#i-DTB#lb^9tN94L9Q|3h-to6BD`OEqLD#n@k_%?1)jWKsC2=3qF@za4? z983KD<)16zpjfaSPvNrtTP`Bowf$?mF&idM0p1}e@>Cwm=jbq4YSNhUQ8k^R`#Juz zCQB@*>GEs%!Xsfmz)TRUK7?SW==sU_GK}=aFUYxHq=PVlqdN@}?R#CR4(uauXUE#K zz{OrFFf(C!PqmpDEPBD=?G@8cN}2Lz4s0wty8RKMrq` zM?5)$K^Not?{({{y#c97RZmKr>U>va3XL78YMzoKh=2YIdFspYVs#PqL(4V%t4vZj zEL^9-{Cwl!^%$x%!dD26*`?{_8AJ)4BY#39YM4d)R8bJnWG~pLqIJIa7G**LDKQ$R zOF<7VT6&%s#3IlzT_+A4X*tt~ztsTkD%06La@)e#DP>Q}TC^h7d0VK(FdzD*3v3(9 zAO{sR>d?fNk4^V}XaL7zDD!RGYjJ{W7b=_B>p)oM3DHT1RyZB20!um-vPXDYbP#D_ zO8$n3Hn!Jp5p{Rm5%j*&D``)jP}2s?D$`N=B1{(wBivnso%mM2S8_rk-tW-FN-(T3 zuA%B_;JcWvQy<*pwTwpgGBh*JEssO&P6SP{L64geRMquK$+Qw$Z3NKAdFx>SJgxls zM=69PzK0}u?r6grUDobA+a<|(9wtR9Ov)hFz#qG3Y(dp>@4j2sAp&H_GJEFja;9U( zwK{6rZs%c6S;L7hFjC;%z)TM@RCKvMyNS1OLlx?6!Ks?dNE`O0)dJ^`nXu5ye`p;d z-~=mDMc7OQKIuT*RPG-e@@Jij*c3P;Ia(Boe0Hr7dPOi7YH~<$p7aXBU&8UaOFaK2f zSwh&IJY6!E%co0)w<;2+GO`o=C7Yy(MGUY3pU5fS++|f%RlFIG>0-0h0N^e|Mb*Hs zAB{|+%wgTw|b5>>;f{z8DIY2K# zg`uC}x_t!hsPsu;L=M$*f?Rh^8@!ddAeZ`V3U>ZP1f79-3OBO*MfF2!O~(a-^7hD4`DlEX?fgs>fxamDH4ROArzH!OD;OE3@nJz5zN#& zIZwMBe%p3I>J59=L%SxQJiTV3z?0+$jY9k%_l#IKm6ap|wqWuDogn}Kru<*%kg%ZZ z!nP$CHgM%`2p(9>ebC`YTK%?l4+PZA*Ie+%+&S|Wk}lKUNDr(%-C~(*clwcc@ zxLv$p@9ZT_HF2!*XY}msk4^t0FxO z30qQWh)2PwdPUSoelhkGQs%9hy;tM&P#tI}3z7(6^^AjWP0-W943oc5AWQa5ME9|( z+MB=!2U3m=cB4XH+qX*3!`d9Ul|rW{QAX)A9wbe@^eE3Y)Q~$+MQTRg$z`* znUJg*12>l4TMoBhp^#Eqw7D=f28^(oELBp30U+~5F_WENLj!ej_9{YZ>Xf3@9>z2Y zd4YEzdN4tWgF^PJCMpSoQ!(AZZU_|!5}~FWVLIT;P8z&gyy*5f3ghx$)+G?=O+^AP z3gN>70EEQ>my4X>ji*M=@P?eo0CRw!h8+t^x`!RAWv$-)iNOFj(yhesT^brG z?=cYVmyHTgxK$>Z;s;;l!0^ekXdZjwWtR^_n`Y|iyhjGZ)%tX-`4jtDVa}lEl(h=?w+Dn&;q8@huau z$KeLyv>lr{ZZZeRS^E5<7G6qq>G6;<5+b)2y40;57iW40!N1#XIcd89+F74mZf&2u z?#2B|!6=~aJ3!DFu}7+2kXmZ`ud_#3wgvY*nl~G~r z@#A2kp8Gia*EA9jM6n*-P$4r)OMXlgkH(UbGKHAwV|4mvgUozB75s~&gc&xIhcilW z{M6pjuxe9pWPjuFk#@`&`fz&=!{sTBV4jo7&$?#D$X9{OT-#m7eu{KQM?-UO$rk(;GVOYI(ga+y%~?k$GUlNP15>T5~^0G zjrz(wEGhF2W5mkg7nu3L(Y3uu`;Y9e$}fdz?ghrAkS^^og!(<0k76q>t%9=U)21JU zf@PAeg4bQ5;t3fY+Fh@-%OYN)Lz5c>goJv=z|I+%y8!f1w%IuK@;#A-r1yc^Y1+tv z3~#4RDOOjvfDuAad)gJ}jrx@(w!f!GlxS-fc6xN=3wKDtx* zICcmv+a%M0ee+~RAb_qK)BNV8U&qos(DTxpwJ#MH)ZLn}f=huj!OiJG7FWU**X3r7 z3E!KKpP0RPU*BP(Cz537@Mx(~=Qy88yb``PCX{G}#< z0i6y0Q+E>>q zZr>4^I!Ilmp`}U`fEqguzf68YhNf6ab|fL!E0dKX7UveK>Qnf9YV{*YNDMAgQ>ona ze2`%f4q5mo{FC8yU1{EE_JkTe{F28G3cM1GqDFfCvm+T*%v(V}AhPo*>~ z=+;b>D95m^J>Urjwd}7< G(vHAR8DUNU literal 0 HcmV?d00001 diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index 4f1404b6e..f99645af5 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -30,7 +30,91 @@ jobs: VERSION=$(grep -o '^version = ".*"' crates/bws/Cargo.toml | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+") echo "package_version=$VERSION" >> $GITHUB_OUTPUT - build: + build-windows: + name: Building CLI for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} + runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} + needs: setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + strategy: + fail-fast: false + matrix: + settings: + - os: windows-2022 + target: x86_64-pc-windows-msvc + + - os: windows-2022 + target: aarch64-pc-windows-msvc + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + toolchain: stable + targets: ${{ matrix.settings.target }} + + - name: Cache cargo registry + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + with: + key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} + + - name: Build + env: + TARGET: ${{ matrix.settings.target }} + run: cargo build ${{ matrix.features }} -p bws --release --target=${{ matrix.settings.target }} + + - name: Login to Azure + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets-windows + 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: Install AST + run: dotnet tool install --global AzureSignTool --version 4.0.1 + + - name: Sign windows binary + env: + SIGNING_VAULT_URL: ${{ steps.retrieve-secrets-windows.outputs.code-signing-vault-url }} + SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets-windows.outputs.code-signing-client-id }} + SIGNING_TENANT_ID: ${{ steps.retrieve-secrets-windows.outputs.code-signing-tenant-id }} + SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets-windows.outputs.code-signing-client-secret }} + SIGNING_CERT_NAME: ${{ steps.retrieve-secrets-windows.outputs.code-signing-cert-name }} + run: | + azuresigntool sign -v \ + -kvu $SIGNING_VAULT_URL \ + -kvi $SIGNING_CLIENT_ID \ + -kvt $SIGNING_TENANT_ID \ + -kvs $SIGNING_CLIENT_SECRET \ + -kvc $SIGNING_CERT_NAME \ + -fd sha256 \ + -du https://bitwarden.com \ + -tr http://timestamp.digicert.com \ + ./target/${{ matrix.settings.target }}/release/bws.exe + + - name: Zip + shell: cmd + run: 7z a ./bws-${{ matrix.settings.target }}-%_PACKAGE_VERSION%.zip ./target/${{ matrix.settings.target }}/release/bws.exe + + - name: Upload artifact + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + with: + name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip + path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip + if-no-files-found: error + + build-macos: name: Building CLI for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} needs: @@ -47,12 +131,110 @@ jobs: - os: macos-12 target: aarch64-apple-darwin - - os: windows-2022 - target: x86_64-pc-windows-msvc + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - os: windows-2022 - target: aarch64-pc-windows-msvc + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + toolchain: stable + targets: ${{ matrix.settings.target }} + + - name: Cache cargo registry + uses: Swatinem/rust-cache@3cf7f8cc28d1b4e7d01e3783be10a97d55d483c8 # v2.7.1 + with: + key: ${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} + - name: Build + env: + TARGET: ${{ matrix.settings.target }} + run: cargo build ${{ matrix.features }} -p bws --release --target=${{ matrix.settings.target }} + + - name: Login to Azure + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets macos + id: retrieve-secrets-macos + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: "bitwarden-ci" + secrets: "macos-bws-notarization-apple-id, + macos-bws-notarization-team-id, + macos-bws-notarization-password, + macos-bws-certificate-name, + macos-bws-installer-certificate-name" + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_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 + + ls $HOME/secrets + + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Sign macos + env: + MACOS_CERTIFICATE_NAME: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-certificate-name }} + run: codesign --sign "$MACOS_CERTIFICATE_NAME" --verbose=3 --force --options=runtime --timestamp ./target/${{ matrix.settings.target }}/release/bws + + - name: Notarize app macos + env: + MACOS_NOTARIZATION_APPLE_ID: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-apple-id }} + MACOS_NOTARIZATION_TEAM_ID: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-team-id }} + MACOS_NOTARIZATION_PWD: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-password }} + MACOS_CERTIFICATE_NAME: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-certificate-name }} + run: | + echo "Create keychain profile" + xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD" + + echo "Creating notarization archive" + zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws + + codesign --sign "$MACOS_CERTIFICATE_NAME" --verbose=3 --force --options=runtime --timestamp ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip + + echo "Notarize app" + xcrun notarytool submit ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip --keychain-profile "notarytool-profile" --wait + + - name: Upload artifact + uses: actions/upload-artifact@c7d193f32edcb7bfad88892161225aeda64e9392 # v4.0.0 + with: + name: bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip + path: ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip + if-no-files-found: error + + build-linux: + name: Building CLI for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} + runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} + needs: + - setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + strategy: + fail-fast: false + matrix: + settings: - os: ubuntu-20.04 target: x86_64-unknown-linux-gnu @@ -89,13 +271,7 @@ jobs: TARGET: ${{ matrix.settings.target }} run: cross build ${{ matrix.features }} -p bws --release --target=${{ matrix.settings.target }} - - name: Zip Windows - shell: cmd - if: runner.os == 'Windows' - run: 7z a ./bws-${{ matrix.settings.target }}-%_PACKAGE_VERSION%.zip ./target/${{ matrix.settings.target }}/release/bws.exe - - - name: Zip Unix - if: runner.os != 'Windows' + - name: Zip linux run: zip -j ./bws-${{ matrix.settings.target }}-${{ env._PACKAGE_VERSION }}.zip ./target/${{ matrix.settings.target }}/release/bws - name: Upload artifact @@ -110,7 +286,7 @@ jobs: runs-on: macos-12 needs: - setup - - build + - build-macos env: _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} steps: @@ -138,8 +314,70 @@ jobs: lipo -create -output ./bws-macos-universal/bws ./bws-x86_64-apple-darwin/bws ./bws-aarch64-apple-darwin/bws - - name: Zip universal artifact - run: zip ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-macos-universal/bws + - name: Login to Azure + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets-macos + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: "bitwarden-ci" + secrets: "macos-bws-notarization-apple-id, + macos-bws-notarization-team-id, + macos-bws-notarization-password, + macos-bws-certificate-name, + macos-bws-installer-certificate-name" + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_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/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Sign binary + env: + MACOS_CERTIFICATE_NAME: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-certificate-name }} + run: codesign --sign "$MACOS_CERTIFICATE_NAME" --verbose=3 --force --options=runtime --timestamp ./bws-aarch64-apple-darwin/bws + + - name: Notarize app + env: + MACOS_NOTARIZATION_APPLE_ID: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-apple-id }} + MACOS_NOTARIZATION_TEAM_ID: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-team-id }} + MACOS_NOTARIZATION_PWD: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-notarization-password }} + MACOS_CERTIFICATE_NAME: ${{ steps.retrieve-secrets-macos.outputs.macos-bws-certificate-name }} + run: | + + echo "Create keychain profile" + xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD" + + echo "Creating notarization archive" + zip -j ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip ./bws-aarch64-apple-darwin/bws + + codesign --sign "$MACOS_CERTIFICATE_NAME" --verbose=3 --force --options=runtime --timestamp ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip + + echo "Notarize app" + xcrun notarytool submit ./bws-macos-universal-${{ env._PACKAGE_VERSION }}.zip --keychain-profile "notarytool-profile" --wait - name: Upload artifact uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 diff --git a/crates/bws/entitlements.plist b/crates/bws/entitlements.plist new file mode 100644 index 000000000..aeaa15049 --- /dev/null +++ b/crates/bws/entitlements.plist @@ -0,0 +1,8 @@ + + + + + com.apple.security.cs.allow-unsigned-executable-memory + + + \ No newline at end of file From 676069a8cc2bf3d5743e489b7e06b2c0e387f533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Feb 2024 16:59:35 +0100 Subject: [PATCH 306/378] [DEVOPS-1785] Change ruby publish workflow to use api key method (#629) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/publish-ruby.yml:** Use `gem push` with rubygem API key instead of automated release steps. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-ruby.yml | 39 ++++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/.github/workflows/publish-ruby.yml b/.github/workflows/publish-ruby.yml index 931981667..b97a7b730 100644 --- a/.github/workflows/publish-ruby.yml +++ b/.github/workflows/publish-ruby.yml @@ -107,26 +107,33 @@ jobs: cp "temp/${platforms[$i]}/${files[$i]}" "languages/ruby/bitwarden_sdk_secrets/lib/${platforms[$i]}/${files[$i]}" done + - 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: "rubygem-api-key" + - name: bundle install run: bundle install working-directory: languages/ruby/bitwarden_sdk_secrets - - name: Set remote URL - run: | - # Attribute commits to the last committer on HEAD - git config --global user.email "106330231+bitwarden-devops-bot@users.noreply.github.com" - git config --global user.name "bitwarden-devops-bot" - git remote set-url origin "https://x-access-token:${{ github.token }}@github.com/$GITHUB_REPOSITORY" - - - name: Configure trusted publishing credentials - uses: rubygems/configure-rubygems-credentials@bc6dd217f8a4f919d6835fcfefd470ef821f5c44 # v1.0.0 - - - name: Run release rake task - if: ${{ inputs.release_type == 'Release' }} - run: bundle exec rake release + - name: Build gem + run: gem build bitwarden-sdk-secrets.gemspec working-directory: languages/ruby/bitwarden_sdk_secrets - - name: Wait for release to propagate - if: ${{ inputs.release_type == 'Release' }} - run: gem exec rubygems-await pkg/*.gem + - name: Push gem to Rubygems + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem push *.gem + env: + GEM_HOST_API_KEY: ${{ steps.retrieve-secrets.outputs.rubygem-api-key }} working-directory: languages/ruby/bitwarden_sdk_secrets From 63b6a9e67eb688fb22e8e7c44ee4efe4d5cae05a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:11:01 +0100 Subject: [PATCH 307/378] [deps]: Update @types/node to v18.19.18 (#616) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.17` -> `18.19.18`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.17/18.19.18) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.17/18.19.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.17/18.19.18?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 036117a72..176ed5eca 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.17.tgz", - "integrity": "sha512-SzyGKgwPzuWp2SHhlpXKzCX0pIOfcI4V2eF37nNBJOhwlegQ83omtVQ1XxZpDE06V/d6AQvfQdPfnw0tRC//Ng==", + "version": "18.19.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.18.tgz", + "integrity": "sha512-80CP7B8y4PzZF0GWx15/gVWRrB5y/bIjNI84NK3cmQJu0WZwvmj2WMA5LcofQFVfLqqCSp545+U2LsrVzX36Zg==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From aad70143868ebef6694fbdc95766e290da70f612 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 27 Feb 2024 13:47:07 +0100 Subject: [PATCH 308/378] [PM-6437] Implement admin password reset logic (#631) Implement cryptographic logic for admin password reset. --- crates/bitwarden-uniffi/src/crypto.rs | 15 ++++- crates/bitwarden/src/mobile/client_crypto.rs | 16 +++-- crates/bitwarden/src/mobile/crypto.rs | 61 ++++++++++++++++++++ 3 files changed, 87 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 2d847b33d..0f877d52e 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use bitwarden::mobile::crypto::{ DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse, }; -use bitwarden_crypto::EncString; +use bitwarden_crypto::{AsymmetricEncString, EncString}; use crate::{error::Result, Client}; @@ -83,4 +83,17 @@ impl ClientCrypto { .derive_pin_user_key(encrypted_pin) .await?) } + + pub async fn enroll_admin_password_reset( + &self, + public_key: String, + ) -> Result { + Ok(self + .0 + .0 + .write() + .await + .crypto() + .enroll_admin_password_reset(public_key)?) + } } diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index f6ea3346b..6ef65975d 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -1,14 +1,14 @@ #[cfg(feature = "internal")] -use bitwarden_crypto::EncString; +use bitwarden_crypto::{AsymmetricEncString, EncString}; use crate::Client; #[cfg(feature = "internal")] use crate::{ error::Result, mobile::crypto::{ - derive_pin_key, derive_pin_user_key, get_user_encryption_key, initialize_org_crypto, - initialize_user_crypto, update_password, DerivePinKeyResponse, InitOrgCryptoRequest, - InitUserCryptoRequest, UpdatePasswordResponse, + derive_pin_key, derive_pin_user_key, enroll_admin_password_reset, get_user_encryption_key, + initialize_org_crypto, initialize_user_crypto, update_password, DerivePinKeyResponse, + InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse, }, }; @@ -49,6 +49,14 @@ impl<'a> ClientCrypto<'a> { pub async fn derive_pin_user_key(&mut self, encrypted_pin: EncString) -> Result { derive_pin_user_key(self.client, encrypted_pin) } + + #[cfg(feature = "internal")] + pub fn enroll_admin_password_reset( + &mut self, + public_key: String, + ) -> Result { + enroll_admin_password_reset(self.client, public_key) + } } impl<'a> Client { diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index a48b29b15..214643023 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -286,6 +286,24 @@ fn derive_pin_protected_user_key( Ok(derived_key.encrypt_user_key(user_key)?) } +#[cfg(feature = "internal")] +pub(super) fn enroll_admin_password_reset( + client: &mut Client, + public_key: String, +) -> Result { + use base64::{engine::general_purpose::STANDARD, Engine}; + use bitwarden_crypto::AsymmetricPublicCryptoKey; + + let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(public_key)?)?; + let enc = client.get_encryption_settings()?; + let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; + + Ok(AsymmetricEncString::encrypt_rsa2048_oaep_sha1( + &key.to_vec(), + &public_key, + )?) +} + #[cfg(test)] mod tests { use super::*; @@ -461,4 +479,47 @@ mod tests { .to_base64() ); } + + #[cfg(feature = "internal")] + #[test] + fn test_enroll_admin_password_reset() { + use std::{num::NonZeroU32, ops::Deref}; + + use base64::{engine::general_purpose::STANDARD, Engine}; + use bitwarden_crypto::AsymmetricCryptoKey; + + let mut client = Client::new(None); + client.set_login_method(LoginMethod::User(UserLoginMethod::Username { + client_id: "7b821276-e27c-400b-9853-606393c87f18".to_owned(), + email: "test@bitwarden.com".to_owned(), + kdf: Kdf::PBKDF2 { + iterations: NonZeroU32::new(600_000).unwrap(), + }, + })); + + let user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap(); + let private_key ="2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=".parse().unwrap(); + client + .initialize_user_crypto("asdfasdfasdf", user_key, private_key) + .unwrap(); + + let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsy7RFHcX3C8Q4/OMmhhbFReYWfB45W9PDTEA8tUZwZmtOiN2RErIS2M1c+K/4HoDJ/TjpbX1f2MZcr4nWvKFuqnZXyewFc+jmvKVewYi+NAu2++vqKq2kKcmMNhwoQDQdQIVy/Uqlp4Cpi2cIwO6ogq5nHNJGR3jm+CpyrafYlbz1bPvL3hbyoGDuG2tgADhyhXUdFuef2oF3wMvn1lAJAvJnPYpMiXUFmj1ejmbwtlxZDrHgUJvUcp7nYdwUKaFoi+sOttHn3u7eZPtNvxMjhSS/X/1xBIzP/mKNLdywH5LoRxniokUk+fV3PYUxJsiU3lV0Trc/tH46jqd8ZGjmwIDAQAB"; + + let encrypted = enroll_admin_password_reset(&mut client, public_key.to_owned()).unwrap(); + + let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ="; + let private_key = + AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key).unwrap()).unwrap(); + let decrypted: Vec = encrypted.decrypt_with_key(&private_key).unwrap(); + + let expected = client + .get_encryption_settings() + .unwrap() + .get_key(&None) + .unwrap() + .to_vec() + .deref() + .clone(); + assert_eq!(decrypted, expected); + } } From d1fe6b701324c540814fff0752209de3a7eefbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 27 Feb 2024 17:53:16 +0100 Subject: [PATCH 309/378] [DEVOPS-1333] Add code signing to the Windows bws CLI (#534) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Digitally sign Windows CLI .exe executable to prevent warning showing up on clients' computers while running `bws` commands. ## Code changes - **.github/workflows/build-cli.yml:** - split Windows and UNIX build jobs - add steps to windows build job to login to Azure, get secrets from KeyVault, install azuresigntool and use azuresigntool to sign windows CLI artifact. ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> --- .github/workflows/build-cli.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index f99645af5..e60928807 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -20,6 +20,7 @@ jobs: runs-on: ubuntu-22.04 outputs: package_version: ${{ steps.retrieve-version.outputs.package_version }} + sign: ${{ steps.sign.outputs.sign }} steps: - name: Checkout repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -30,6 +31,16 @@ jobs: VERSION=$(grep -o '^version = ".*"' crates/bws/Cargo.toml | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+") echo "package_version=$VERSION" >> $GITHUB_OUTPUT + - name: Sign if repo is owned by Bitwarden + id: sign + env: + REPO_OWNER: ${{ github.repository_owner }} + run: | + if [[ $REPO_OWNER == bitwarden ]]; then + echo "sign=true" >> $GITHUB_OUTPUT + fi + echo "sign=false" >> $GITHUB_OUTPUT + build-windows: name: Building CLI for - ${{ matrix.settings.os }} - ${{ matrix.settings.target }} runs-on: ${{ matrix.settings.os || 'ubuntu-latest' }} @@ -66,11 +77,13 @@ jobs: run: cargo build ${{ matrix.features }} -p bws --release --target=${{ matrix.settings.target }} - name: Login to Azure + if: ${{ needs.setup.outputs.sign == 'true' }} uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 with: creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - name: Retrieve secrets + if: ${{ needs.setup.outputs.sign == 'true' }} id: retrieve-secrets-windows uses: bitwarden/gh-actions/get-keyvault-secrets@main with: @@ -82,9 +95,11 @@ jobs: code-signing-cert-name" - name: Install AST + if: ${{ needs.setup.outputs.sign == 'true' }} run: dotnet tool install --global AzureSignTool --version 4.0.1 - name: Sign windows binary + if: ${{ needs.setup.outputs.sign == 'true' }} env: SIGNING_VAULT_URL: ${{ steps.retrieve-secrets-windows.outputs.code-signing-vault-url }} SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets-windows.outputs.code-signing-client-id }} From e9b77a488403e90c89cf3cdffc4452eb84c3ed7e Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Tue, 27 Feb 2024 12:39:28 -0500 Subject: [PATCH 310/378] Provide global coverage configuration (#634) Codecov says it merges global and local configs, but looks like it doesn't. Provides global status configuration so this doesn't fail checks. --- .github/codecov.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/codecov.yml b/.github/codecov.yml index 3228d009c..e91eb4393 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,3 +1,9 @@ +coverage: + status: + project: + default: + informational: true + ignore: - "crates/sdk-schemas" # Tool - "crates/uniffi-bindgen" # Tool From cdfb9fa529ffd8277d0e23c0562a140fac164d5c Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 27 Feb 2024 19:26:27 +0100 Subject: [PATCH 311/378] Make codecov patch informational (#636) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ``` ## Objective We should make the patch check informational too. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/codecov.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/codecov.yml b/.github/codecov.yml index e91eb4393..eb851984f 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,8 +1,7 @@ coverage: status: - project: - default: - informational: true + patch: + informational: true ignore: - "crates/sdk-schemas" # Tool From 4e456269ec2e2057ac70af8012a2abc367488dc9 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Tue, 27 Feb 2024 15:56:37 -0500 Subject: [PATCH 312/378] Export Clippy results as SARIF and upload (#633) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [X] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Takes Clippy results as SARIF and uploads to GHAS for easier viewing and management. ## Code changes - **.github/workflows/lint.yml:** New Cargo package usage and SARIF upload. ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Hinton --- .github/workflows/lint.yml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1c2279b3d..771b368f5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -35,6 +35,20 @@ jobs: - name: Cargo fmt run: cargo +nightly fmt --check + - name: Install clippy-sarif and sarif-fmt + run: cargo install clippy-sarif sarif-fmt --locked --git https://github.com/psastras/sarif-rs.git --rev 11c33a53f6ffeaed736856b86fb6b7b09fabdfd8 + + - name: Cargo clippy + run: cargo clippy --all-features --tests --message-format=json | + clippy-sarif | tee clippy_result.sarif | sarif-fmt + env: + RUSTFLAGS: "-D warnings" + + - name: Upload Clippy results to GitHub + uses: github/codeql-action/upload-sarif@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5 + with: + sarif_file: clippy_result.sarif + - name: Set up Node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: @@ -52,8 +66,3 @@ jobs: run: cargo doc --no-deps --features internal env: RUSTDOCFLAGS: "-D warnings" - - - name: Cargo clippy - run: cargo clippy --all-features --tests - env: - RUSTFLAGS: "-D warnings" From 932945de319c7950a1e4f27fb55d378b261eb8b6 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Thu, 29 Feb 2024 03:58:24 -0500 Subject: [PATCH 313/378] Undo global coverage setting application (#637) Reverts #634 and #636 as we found our mistake. --- .github/codecov.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/codecov.yml b/.github/codecov.yml index eb851984f..3228d009c 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,8 +1,3 @@ -coverage: - status: - patch: - informational: true - ignore: - "crates/sdk-schemas" # Tool - "crates/uniffi-bindgen" # Tool From c0fe4ac39c6a91b23575b6cf8d1db48e79897761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Thu, 29 Feb 2024 12:13:01 +0100 Subject: [PATCH 314/378] [DEVOPS-1750] Build and release pipeline for go SDK (#632) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **languages/go/.version:** Add file to hold current go SDK version - **.github/workflows/version-bump.yml** Add go SDK to version bump workflow - **.github/workflows/golang-release.yml** replace it with `.github/workflows/release-go.yaml` workflow. - **.github/workflows/build-go.yaml** Add build go as a separate workflow - **.github/workflows/release-go.yml** Update release go pipeline to our standards. Sync go SDK folder to external repo. Create release tag. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/build-go.yaml | 49 +++++++++ .github/workflows/golang-release.yml | 73 ------------- .github/workflows/release-go.yml | 151 +++++++++++++++++++++++++++ .github/workflows/version-bump.yml | 6 ++ languages/go/.version | 1 + 5 files changed, 207 insertions(+), 73 deletions(-) create mode 100644 .github/workflows/build-go.yaml delete mode 100644 .github/workflows/golang-release.yml create mode 100644 .github/workflows/release-go.yml create mode 100644 languages/go/.version diff --git a/.github/workflows/build-go.yaml b/.github/workflows/build-go.yaml new file mode 100644 index 000000000..433013aac --- /dev/null +++ b/.github/workflows/build-go.yaml @@ -0,0 +1,49 @@ +name: Build Go SDK + +on: + push: + branches: + - main + - rc + - hotfix-rc + + pull_request: + +env: + GO111MODULE: on + GO_VERSION: "^1.18" + +jobs: + build: + name: Build + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Go environment + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Cache dependencies + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - name: npm ci + run: npm ci + + - name: Generate schemas + run: npm run schemas + + - name: Build + working-directory: languages/go + run: go build -v ./... + + - name: Test + working-directory: languages/go + run: go test -v ./... diff --git a/.github/workflows/golang-release.yml b/.github/workflows/golang-release.yml deleted file mode 100644 index 10ec7675e..000000000 --- a/.github/workflows/golang-release.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Go Release - -on: - workflow_dispatch: - inputs: - version_number: - description: "New Version" - required: true - -env: - GO111MODULE: on - GO_VERSION: "^1.18" - -jobs: - build_rust: - uses: ./.github/workflows/build-rust-cross-platform.yml - - generate-schemas: - uses: ./.github/workflows/generate_schemas.yml - - build: - name: Build - needs: - - build_rust - - generate-schemas - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Setup Go environment - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Cache dependencies - uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 - with: - path: ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Build - run: go build -v ./... - - - name: Test - run: go test -v ./... - - release: - name: Release - needs: build - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Setup Go environment - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 - with: - go-version: ${{ env.GO_VERSION }} - - - name: Set release version - run: echo "VERSION=${{ github.event.inputs.version_number }}" >> $GITHUB_ENV - - - name: Install Goreleaser - run: go install github.com/goreleaser/goreleaser@v1.21.2 - - - name: Run Goreleaser - run: goreleaser release --rm-dist --skip-validate - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VERSION: ${{ env.VERSION }} diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml new file mode 100644 index 000000000..830e5f313 --- /dev/null +++ b/.github/workflows/release-go.yml @@ -0,0 +1,151 @@ +name: Release Go + +on: + workflow_dispatch: + inputs: + release_type: + description: "Release Options" + required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + +env: + GO111MODULE: on + GO_VERSION: "^1.18" + +jobs: + validate: + name: Setup + runs-on: ubuntu-22.04 + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Branch check + if: ${{ github.event.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: Get version + id: version + run: | + VERSION=$(cat languages/go/.version | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+") + echo "version=$VERSION" >> $GITHUB_OUTPUT + + repo-sync: + name: Push changed files to SDK Go repo + runs-on: ubuntu-22.04 + needs: validate + env: + _KEY_VAULT: "bitwarden-ci" + _BOT_EMAIL: 106330231+bitwarden-devops-bot@users.noreply.github.com + _BOT_NAME: bitwarden-devops-bot + _PKG_VERSION: ${{ needs.validate.outputs.version }} + steps: + - name: Checkout SDK repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + path: sdk + + - name: Checkout SDK-Go repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + repository: bitwarden/sm-sdk-go + path: sm-sdk-go + ref: main + + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Setup Git + working-directory: sm-sdk-go + run: | + git config --local user.email "${{ env._BOT_EMAIL }}" + git config --local user.name "${{ env._BOT_NAME }}" + + - name: Update files + run: | + # Copy files to local sm-sdk-go repo path + cp --verbose -rf sdk/languages/go sm-sdk-go + + - name: Push changes + working-directory: sm-sdk-go + run: | + git add . + git commit -m "Update Go SDK to ${{ github.sha }}" + + if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + echo "===================================" + echo "[!] Dry Run - Skipping push" + echo "===================================" + git ls-files -m + exit 0 + else + git push origin main + fi + + - name: Create release tag on SDK Go repo + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + working-directory: sm-sdk-go + run: | + # Check if tag exists, set output then exit 0 if true. + if git log v${{ env._PKG_VERSION }} >/dev/null 2>&1; then + echo "===================================" + echo "[!] Tag v${{ env._PKG_VERSION }} already exists" + echo "===================================" + exit 1 + fi + + git tag v${{ env._PKG_VERSION }} + git push origin v${{ env._PKG_VERSION }} + + github-release: + name: GitHub Release + runs-on: ubuntu-22.04 + needs: + - repo-sync + - validate + env: + _PKG_VERSION: ${{ needs.validate.outputs.version }} + steps: + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Create release + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 + with: + tag: v${{ env._PKG_VERSION }} + name: v${{ env._PKG_VERSION }} + body: "" + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + draft: true + repo: bitwarden/sm-sdk-go diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 3c6485a09..8298781fc 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -20,6 +20,7 @@ on: - napi - python-sdk - ruby-sdk + - go-sdk version_number: description: "New version (example: '2024.1.0')" required: true @@ -156,6 +157,11 @@ jobs: if: ${{ inputs.project == 'ruby-sdk' }} run: sed -i "s/VERSION = '[0-9]\.[0-9]\.[0-9]'/VERSION = '${{ inputs.version_number }}'/" ./languages/ruby/bitwarden_sdk_secrets/lib/version.rb + ### go sdk + - name: Bump go-sdk Version + if: ${{ inputs.project == 'go-sdk' }} + run: sed -i 's/[0-9]\.[0-9]\.[0-9]/${{ inputs.version_number }}/' ./languages/go/.version + ############################ # VERSION BUMP SECTION END # ############################ diff --git a/languages/go/.version b/languages/go/.version new file mode 100644 index 000000000..6c6aa7cb0 --- /dev/null +++ b/languages/go/.version @@ -0,0 +1 @@ +0.1.0 \ No newline at end of file From c3d809b6b3a0a9ebf9fe6bddeea10f54a3701062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 29 Feb 2024 17:31:56 +0100 Subject: [PATCH 315/378] Fix typo in `trust_device` (#640) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Function was accidentally called `t` when it should have been called `trust_device` --- crates/bitwarden-uniffi/src/auth/mod.rs | 2 +- languages/kotlin/doc.md | 68 +++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 34d0de93f..2a451ffdf 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -130,7 +130,7 @@ impl ClientAuth { } /// Trust the current device - pub async fn t(&self) -> Result { + pub async fn trust_device(&self) -> Result { Ok(self.0 .0.write().await.auth().trust_device()?) } } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index d69e134c4..c4b564a2e 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -46,6 +46,16 @@ Generator operations **Output**: Arc +### `exporters` + +Exporters + +**Arguments**: + +- self: Arc + +**Output**: Arc + ### `auth` Auth operations @@ -138,6 +148,23 @@ password, use the email OTP. **Output**: std::result::Result<,BitwardenError> +### `validate_password_user_key` + +Validate the user password without knowing the password hash + +Used for accounts that we know have master passwords but that have not logged in with a password. +Some example are login with device or TDE. + +This works by comparing the provided password against the encrypted user key. + +**Arguments**: + +- self: +- password: String +- encrypted_user_key: String + +**Output**: std::result::Result + ### `new_auth_request` Initialize a new auth request @@ -160,6 +187,16 @@ Approve an auth request **Output**: std::result::Result +### `trust_device` + +Trust the current device + +**Arguments**: + +- self: + +**Output**: std::result::Result + ## ClientAttachments ### `encrypt_buffer` @@ -1287,6 +1324,37 @@ implementations. + + deviceKey + object + + + + + + + + + + + + + + + + + + + + + + + + + +
KeyTypeDescription
device_keystringThe device's DeviceKey
protected_device_private_keyThe Device Private Key
device_protected_user_keyThe user's symmetric crypto key, encrypted with the Device Key.
+ + ## `InitUserCryptoRequest` From e16cea0957d997374584477e2e4a633de27f3f9c Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Thu, 29 Feb 2024 11:33:13 -0800 Subject: [PATCH 316/378] add get-by-ids to Go wrapper (#620) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ## Objective Allow secret fetching by a list of IDs, rather than requesting multiple secrets individually. Exposes the functionality from #150 in Go. ## Code changes - **languages/go/secrets.go:** Add `GetByIDS` func. - **languages/go/example/example.go:** Get secrets by ID. Added JSON output for QA/ease-of-use. --- languages/go/example/example.go | 25 +++++++++++++++++++++++++ languages/go/secrets.go | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/languages/go/example/example.go b/languages/go/example/example.go index deb353565..eb4d34612 100644 --- a/languages/go/example/example.go +++ b/languages/go/example/example.go @@ -1,7 +1,9 @@ package main import ( + "encoding/json" "fmt" + "log" "os" sdk "github.com/bitwarden/sdk/languages/go" @@ -87,5 +89,28 @@ func main() { panic(err) } + secretIdentifiers, err := bitwardenClient.Secrets.List(organizationID.String()) + if err != nil { + panic(err) + } + + // Get secrets with a list of IDs + secretIDs := make([]string, len(secretIdentifiers.Data)) + for i, identifier := range secretIdentifiers.Data { + secretIDs[i] = identifier.ID + } + + secrets, err := bitwardenClient.Secrets.GetByIDS(secretIDs) + if err != nil { + log.Fatalf("Error getting secrets: %v", err) + } + + jsonSecrets, err := json.MarshalIndent(secrets, "", " ") + if err != nil { + log.Fatalf("Error marshalling secrets to JSON: %v", err) + } + + fmt.Println(string(jsonSecrets)) + defer bitwardenClient.Close() } diff --git a/languages/go/secrets.go b/languages/go/secrets.go index e6863c459..2c56538f7 100644 --- a/languages/go/secrets.go +++ b/languages/go/secrets.go @@ -4,6 +4,7 @@ type SecretsInterface interface { Create(key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) List(organizationID string) (*SecretIdentifiersResponse, error) Get(secretID string) (*SecretResponse, error) + GetByIDS(secretIDs []string) (*SecretsResponse, error) Update(secretID string, key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) Delete(secretIDs []string) (*SecretsDeleteResponse, error) } @@ -76,6 +77,22 @@ func (s *Secrets) Get(id string) (*SecretResponse, error) { return &response, nil } +func (s *Secrets) GetByIDS(ids []string) (*SecretsResponse, error) { + command := Command{ + Secrets: &SecretsCommand{ + GetByIDS: &SecretsGetRequest{ + IDS: ids, + }, + }, + } + + var response SecretsResponse + if err := s.executeCommand(command, &response); err != nil { + return nil, err + } + return &response, nil +} + func (s *Secrets) Update(id string, key, value, note string, organizationID string, projectIDs []string) (*SecretResponse, error) { command := Command{ Secrets: &SecretsCommand{ From 5d131f519651a2f6cfb9d27378a7f112ada7e4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 1 Mar 2024 10:41:20 +0100 Subject: [PATCH 317/378] [DEVOPS-1750] Fix release Go SDK pipeline (#642) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/release-go.yml:** Use `bitwarden-devops-bot` PAT to checkout `sm-sdk-go` repo. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/release-go.yml | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 830e5f313..b9ff394be 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -1,4 +1,5 @@ -name: Release Go +name: Release Go SDK +run-name: Release Go SDK ${{ inputs.release_type }} on: workflow_dispatch: @@ -15,6 +16,7 @@ on: env: GO111MODULE: on GO_VERSION: "^1.18" + _KEY_VAULT: "bitwarden-ci" jobs: validate: @@ -47,7 +49,6 @@ jobs: runs-on: ubuntu-22.04 needs: validate env: - _KEY_VAULT: "bitwarden-ci" _BOT_EMAIL: 106330231+bitwarden-devops-bot@users.noreply.github.com _BOT_NAME: bitwarden-devops-bot _PKG_VERSION: ${{ needs.validate.outputs.version }} @@ -57,13 +58,6 @@ jobs: with: path: sdk - - name: Checkout SDK-Go repo - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 - with: - repository: bitwarden/sm-sdk-go - path: sm-sdk-go - ref: main - - name: Login to Azure - Prod Subscription uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 with: @@ -76,6 +70,14 @@ jobs: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" + - name: Checkout SDK-Go repo + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + with: + repository: bitwarden/sm-sdk-go + path: sm-sdk-go + ref: main + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + - name: Setup Git working-directory: sm-sdk-go run: | From 29089c576491c2424da178dc6a57f1a1f4596d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 1 Mar 2024 13:18:50 +0100 Subject: [PATCH 318/378] [PM-6262] Add basic feature flags support to enable cipher key encryption (#638) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Implement support for some basic feature flagging for the mobile clients, the only flag supported is `enableCipherKeyEncryption` --- crates/bitwarden-uniffi/src/platform/mod.rs | 6 ++ crates/bitwarden/src/client/client.rs | 24 +++++- crates/bitwarden/src/client/flags.rs | 43 +++++++++++ crates/bitwarden/src/client/mod.rs | 3 + .../src/mobile/vault/client_ciphers.rs | 15 +++- crates/bitwarden/src/vault/cipher/cipher.rs | 77 +++++++++++++++++++ languages/kotlin/doc.md | 11 +++ 7 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 crates/bitwarden/src/client/flags.rs diff --git a/crates/bitwarden-uniffi/src/platform/mod.rs b/crates/bitwarden-uniffi/src/platform/mod.rs index 7200b6678..33b14d345 100644 --- a/crates/bitwarden-uniffi/src/platform/mod.rs +++ b/crates/bitwarden-uniffi/src/platform/mod.rs @@ -31,4 +31,10 @@ impl ClientPlatform { .platform() .user_fingerprint(fingerprint_material)?) } + + /// Load feature flags into the client + pub async fn load_flags(&self, flags: std::collections::HashMap) -> Result<()> { + self.0 .0.write().await.load_flags(flags); + Ok(()) + } } diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 5b2c8b7e0..45f58444c 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -13,9 +13,12 @@ use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] -use crate::platform::{ - get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, - UserApiKeyResponse, +use crate::{ + client::flags::Flags, + platform::{ + get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, + UserApiKeyResponse, + }, }; use crate::{ client::{ @@ -77,6 +80,9 @@ pub struct Client { pub(crate) token_expires_on: Option, pub(crate) login_method: Option, + #[cfg(feature = "internal")] + flags: Flags, + /// Use Client::get_api_configurations() to access this. /// It should only be used directly in renew_token #[doc(hidden)] @@ -138,6 +144,8 @@ impl Client { refresh_token: None, token_expires_on: None, login_method: None, + #[cfg(feature = "internal")] + flags: Flags::default(), __api_configurations: ApiConfigurations { identity, api, @@ -148,6 +156,16 @@ impl Client { } } + #[cfg(feature = "internal")] + pub fn load_flags(&mut self, flags: std::collections::HashMap) { + self.flags = Flags::load_from_map(flags); + } + + #[cfg(feature = "mobile")] + pub(crate) fn get_flags(&self) -> &Flags { + &self.flags + } + pub(crate) async fn get_api_configurations(&mut self) -> &ApiConfigurations { // At the moment we ignore the error result from the token renewal, if it fails, // the token will end up expiring and the next operation is going to fail anyway. diff --git a/crates/bitwarden/src/client/flags.rs b/crates/bitwarden/src/client/flags.rs new file mode 100644 index 000000000..0fc17534b --- /dev/null +++ b/crates/bitwarden/src/client/flags.rs @@ -0,0 +1,43 @@ +#[derive(Debug, Default, Clone, serde::Deserialize)] +pub struct Flags { + #[serde(default, rename = "enableCipherKeyEncryption")] + pub enable_cipher_key_encryption: bool, +} + +impl Flags { + pub fn load_from_map(map: std::collections::HashMap) -> Self { + let map = map + .into_iter() + .map(|(k, v)| (k, serde_json::Value::Bool(v))) + .collect(); + serde_json::from_value(serde_json::Value::Object(map)).expect("Valid map") + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_load_empty_map() { + let map = std::collections::HashMap::new(); + let flags = Flags::load_from_map(map); + assert!(!flags.enable_cipher_key_encryption); + } + + #[test] + fn test_load_valid_map() { + let mut map = std::collections::HashMap::new(); + map.insert("enableCipherKeyEncryption".into(), true); + let flags = Flags::load_from_map(map); + assert!(flags.enable_cipher_key_encryption); + } + + #[test] + fn test_load_invalid_map() { + let mut map = std::collections::HashMap::new(); + map.insert("thisIsNotAFlag".into(), true); + let flags = Flags::load_from_map(map); + assert!(!flags.enable_cipher_key_encryption); + } +} diff --git a/crates/bitwarden/src/client/mod.rs b/crates/bitwarden/src/client/mod.rs index c3719fce2..f6d60e961 100644 --- a/crates/bitwarden/src/client/mod.rs +++ b/crates/bitwarden/src/client/mod.rs @@ -7,5 +7,8 @@ mod client; pub mod client_settings; pub(crate) mod encryption_settings; +#[cfg(feature = "internal")] +mod flags; + pub use access_token::AccessToken; pub use client::Client; diff --git a/crates/bitwarden/src/mobile/vault/client_ciphers.rs b/crates/bitwarden/src/mobile/vault/client_ciphers.rs index 4e34021ee..c35cf3080 100644 --- a/crates/bitwarden/src/mobile/vault/client_ciphers.rs +++ b/crates/bitwarden/src/mobile/vault/client_ciphers.rs @@ -1,8 +1,8 @@ -use bitwarden_crypto::{Decryptable, Encryptable}; +use bitwarden_crypto::{Decryptable, Encryptable, LocateKey}; use super::client_vault::ClientVault; use crate::{ - error::Result, + error::{Error, Result}, vault::{Cipher, CipherListView, CipherView}, Client, }; @@ -12,9 +12,18 @@ pub struct ClientCiphers<'a> { } impl<'a> ClientCiphers<'a> { - pub async fn encrypt(&self, cipher_view: CipherView) -> Result { + pub async fn encrypt(&self, mut cipher_view: CipherView) -> Result { let enc = self.client.get_encryption_settings()?; + // TODO: Once this flag is removed, the key generation logic should + // be moved directly into the KeyEncryptable implementation + if cipher_view.key.is_none() && self.client.get_flags().enable_cipher_key_encryption { + let key = cipher_view + .locate_key(enc, &None) + .ok_or(Error::VaultLocked)?; + cipher_view.generate_cipher_key(key)?; + } + let cipher = cipher_view.encrypt(enc, &None)?; Ok(cipher) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 9223462a1..24207251f 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -289,6 +289,18 @@ impl Cipher { } } +impl CipherView { + pub fn generate_cipher_key(&mut self, key: &SymmetricCryptoKey) -> Result<()> { + let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; + let key = ciphers_key.as_ref().unwrap_or(key); + + let new_key = SymmetricCryptoKey::generate(rand::thread_rng()); + + self.key = Some(new_key.to_vec().encrypt_with_key(key)?); + Ok(()) + } +} + impl KeyDecryptable for Cipher { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; @@ -401,3 +413,68 @@ impl From for CipherRepromptType } } } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_generate_cipher_key() { + let key = SymmetricCryptoKey::generate(rand::thread_rng()); + + fn generate_cipher() -> CipherView { + CipherView { + r#type: CipherType::Login, + login: Some(login::LoginView { + username: Some("test_username".to_string()), + password: Some("test_password".to_string()), + password_revision_date: None, + uris: None, + totp: None, + autofill_on_page_load: None, + }), + id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), + organization_id: None, + folder_id: None, + collection_ids: vec![], + key: None, + name: "My test login".to_string(), + notes: None, + identity: None, + card: None, + secure_note: None, + favorite: false, + reprompt: CipherRepromptType::None, + organization_use_totp: true, + edit: true, + view_password: true, + local_data: None, + attachments: None, + fields: None, + password_history: None, + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + } + } + + let original_cipher = generate_cipher(); + + // Check that the cipher gets encrypted correctly without it's own key + let cipher = generate_cipher(); + let no_key_cipher_enc = cipher.encrypt_with_key(&key).unwrap(); + let no_key_cipher_dec: CipherView = no_key_cipher_enc.decrypt_with_key(&key).unwrap(); + assert!(no_key_cipher_dec.key.is_none()); + assert_eq!(no_key_cipher_dec.name, original_cipher.name); + + let mut cipher = generate_cipher(); + cipher.generate_cipher_key(&key).unwrap(); + + // Check that the cipher gets encrypted correctly when it's assigned it's own key + let key_cipher_enc = cipher.encrypt_with_key(&key).unwrap(); + let key_cipher_dec: CipherView = key_cipher_enc.decrypt_with_key(&key).unwrap(); + assert!(key_cipher_dec.key.is_some()); + assert_eq!(key_cipher_dec.name, original_cipher.name); + } +} diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index c4b564a2e..5dce0dbb4 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -531,6 +531,17 @@ Fingerprint using logged in user's public key **Output**: std::result::Result +### `load_flags` + +Load feature flags into the client + +**Arguments**: + +- self: +- flags: std::collections::HashMap + +**Output**: std::result::Result<,BitwardenError> + ## ClientSends ### `encrypt` From 621cb48908ad11cf490eb84124424a22ac8a13fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 1 Mar 2024 14:31:04 +0100 Subject: [PATCH 319/378] [DEVOPS-1750] Fix release go pipeline (#643) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/release-go.yml:** Fix files copy and repo name in create release ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/release-go.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index b9ff394be..5106cd5ee 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -87,7 +87,7 @@ jobs: - name: Update files run: | # Copy files to local sm-sdk-go repo path - cp --verbose -rf sdk/languages/go sm-sdk-go + cp --verbose -rf sdk/languages/go/. sm-sdk-go - name: Push changes working-directory: sm-sdk-go @@ -150,4 +150,5 @@ jobs: body: "" token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} draft: true - repo: bitwarden/sm-sdk-go + repo: sm-sdk-go + owner: bitwarden From 300c1f054a1b359e0937ad8cf701bc4652bc493a Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 4 Mar 2024 16:09:32 +0100 Subject: [PATCH 320/378] Exclude unecessary files from published bws (#650) Prevent unnecessary files from being included in the crates distributed build. --- crates/bws/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 2a0a13f49..9dc6cb355 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -11,6 +11,7 @@ description = """ Bitwarden Secrets Manager CLI """ keywords = ["bitwarden", "secrets-manager", "cli"] +exclude = ["Dockerfile*", "entitlements.plist"] [dependencies] bat = { version = "0.24.0", features = [ From d18ac44226595a19ac8198b2b600f9e9dbf82d11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:17:48 +0100 Subject: [PATCH 321/378] Bump mio from 0.8.10 to 0.8.11 (#651) Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.10 to 0.8.11.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mio&package-manager=cargo&previous-version=0.8.10&new-version=0.8.11)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/bitwarden/sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7efce8973..5c9d0fb58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2003,9 +2003,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", From d2c68979b012565dce9c29c542b9859f2604e5ac Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 5 Mar 2024 15:52:11 +0100 Subject: [PATCH 322/378] Provide a stable test user (#514) Provide a stable test user for use in tests. --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/README.md b/README.md index bab08af9a..cdc52a7cb 100644 --- a/README.md +++ b/README.md @@ -86,5 +86,56 @@ This project uses customized templates which lives in the `support/openapi-templ These templates resolves some outstanding issues we've experienced with the rust generator. But we strive towards modifying the templates as little as possible to ease future upgrades. +## Tests + +Many of the SDK tests are based on encrypted data provided by the other Bitwarden clients. In order +to provide a consistent method of retrieving the data we provide a test account with user keys. + +**Disclaimer:** The server typically encrypts and protects certain fields. In order to allow +accounts to be used on other servers this protection was explicitly removed from these data dumps. + +### `test@bitwarden.com` + +- Email: `test@bitwarden.com` +- Password: `asdfasdfasdf` +- PBKDF2: `600_000` iterations + +```sql +INSERT INTO vault_dev.dbo.[User] ( + Id, Name, Email, EmailVerified, MasterPassword, + MasterPasswordHint, Culture, SecurityStamp, + TwoFactorProviders, TwoFactorRecoveryCode, + EquivalentDomains, ExcludedGlobalEquivalentDomains, + AccountRevisionDate, [Key], PublicKey, + PrivateKey, Premium, PremiumExpirationDate, + Storage, MaxStorageGb, Gateway, GatewayCustomerId, + GatewaySubscriptionId, LicenseKey, + CreationDate, RevisionDate, RenewalReminderDate, + Kdf, KdfIterations, ReferenceData, + ApiKey, ForcePasswordReset, UsesKeyConnector, + FailedLoginCount, LastFailedLoginDate, + AvatarColor, KdfMemory, KdfParallelism, + LastPasswordChangeDate, LastKdfChangeDate, + LastKeyRotationDate, LastEmailChangeDate +) +VALUES + ( + N 'b1fd4bf2-9643-4787-87f3-b0f00189c33b', + N 'Test', N 'test@bitwarden.com', + 0, N 'AQAAAAEAAYagAAAAEJ3ky9F/Zt5sy3/UAHVvBarMR+tBXYOM5IGgXy4/mx82uptgHgItauyCN+UZTvAqiA==', + null, N 'en-US', N 'F3KL7SCJKEXO4LJFVLGZITPEHM7SAVSZ', + null, null, null, null, N '2024-01-07 23:56:48.2600000', + N '2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=', + N 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Ww2chogqCpaAR7Uw448am4b7vDFXiM5kXjFlGfXBlrAdAqTTggEvTDlMNYqPlCo+mBM6iFmTTUY9rpZBvFskMnKvsvpJ47/fehAH2o2e3Ulv/5NFevaVCMCmpkBDtbMbO1A4a3btdRtCP8DsKWMefHauEpaoLxNTLWnOIZVfCMjsSgx2EvULHAZPTtbFwm4+UVKniM4ds4jvOsD85h4jn2aLs/jWJXFfxN8iVSqEqpC2TBvsPdyHb49xQoWWfF0Z6BiNqeNGKEU9Uos1pjL+kzhEzzSpH31PZT/ufJ/oo4+93wrUt57hb6f0jxiXhwd5yQ+9F6wVwpbfkq0IwhjOwIDAQAB', + N '2.yN7l00BOlUE0Sb0M//Q53w==|EwKG/BduQRQ33Izqc/ogoBROIoI5dmgrxSo82sgzgAMIBt3A2FZ9vPRMY+GWT85JiqytDitGR3TqwnFUBhKUpRRAq4x7rA6A1arHrFp5Tp1p21O3SfjtvB3quiOKbqWk6ZaU1Np9HwqwAecddFcB0YyBEiRX3VwF2pgpAdiPbSMuvo2qIgyob0CUoC/h4Bz1be7Qa7B0Xw9/fMKkB1LpOm925lzqosyMQM62YpMGkjMsbZz0uPopu32fxzDWSPr+kekNNyLt9InGhTpxLmq1go/pXR2uw5dfpXc5yuta7DB0EGBwnQ8Vl5HPdDooqOTD9I1jE0mRyuBpWTTI3FRnu3JUh3rIyGBJhUmHqGZvw2CKdqHCIrQeQkkEYqOeJRJVdBjhv5KGJifqT3BFRwX/YFJIChAQpebNQKXe/0kPivWokHWwXlDB7S7mBZzhaAPidZvnuIhalE2qmTypDwHy22FyqV58T8MGGMchcASDi/QXI6kcdpJzPXSeU9o+NC68QDlOIrMVxKFeE7w7PvVmAaxEo0YwmuAzzKy9QpdlK0aab/xEi8V4iXj4hGepqAvHkXIQd+r3FNeiLfllkb61p6WTjr5urcmDQMR94/wYoilpG5OlybHdbhsYHvIzYoLrC7fzl630gcO6t4nM24vdB6Ymg9BVpEgKRAxSbE62Tqacxqnz9AcmgItb48NiR/He3n3ydGjPYuKk/ihZMgEwAEZvSlNxYONSbYrIGDtOY+8Nbt6KiH3l06wjZW8tcmFeVlWv+tWotnTY9IqlAfvNVTjtsobqtQnvsiDjdEVtNy/s2ci5TH+NdZluca2OVEr91Wayxh70kpM6ib4UGbfdmGgCo74gtKvKSJU0rTHakQ5L9JlaSDD5FamBRyI0qfL43Ad9qOUZ8DaffDCyuaVyuqk7cz9HwmEmvWU3VQ+5t06n/5kRDXttcw8w+3qClEEdGo1KeENcnXCB32dQe3tDTFpuAIMLqwXs6FhpawfZ5kPYvLPczGWaqftIs/RXJ/EltGc0ugw2dmTLpoQhCqrcKEBDoYVk0LDZKsnzitOGdi9mOWse7Se8798ib1UsHFUjGzISEt6upestxOeupSTOh0v4+AjXbDzRUyogHww3V+Bqg71bkcMxtB+WM+pn1XNbVTyl9NR040nhP7KEf6e9ruXAtmrBC2ah5cFEpLIot77VFZ9ilLuitSz+7T8n1yAh1IEG6xxXxninAZIzi2qGbH69O5RSpOJuJTv17zTLJQIIc781JwQ2TTwTGnx5wZLbffhCasowJKd2EVcyMJyhz6ru0PvXWJ4hUdkARJs3Xu8dus9a86N8Xk6aAPzBDqzYb1vyFIfBxP0oO8xFHgd30Cgmz8UrSE3qeWRrF8ftrI6xQnFjHBGWD/JWSvd6YMcQED0aVuQkuNW9ST/DzQThPzRfPUoiL10yAmV7Ytu4fR3x2sF0Yfi87YhHFuCMpV/DsqxmUizyiJuD938eRcH8hzR/VO53Qo3UIsqOLcyXtTv6THjSlTopQ+JOLOnHm1w8dzYbLN44OG44rRsbihMUQp+wUZ6bsI8rrOnm9WErzkbQFbrfAINdoCiNa6cimYIjvvnMTaFWNymqY1vZxGztQiMiHiHYwTfwHTXrb9j0uPM=|09J28iXv9oWzYtzK2LBT6Yht4IT4MijEkk0fwFdrVQ4=', + 0, null, null, null, null, null, null, + null, N '2024-01-07 23:53:38.5900000', + N '2024-01-07 23:53:38.5900000', + null, 0, 600000, N '{"id":null}', N '7gp59kKHt9kMlks0BuNC4IjNXYkljR', + 0, 0, 0, null, null, null, null, null, + null, null, null + ); +``` + [secrets-manager]: https://bitwarden.com/products/secrets-manager/ [bws-help]: https://bitwarden.com/help/secrets-manager-cli/ From efeea62ecf3a68c7b1403803c1f5798d636d51c4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:51:01 -0500 Subject: [PATCH 323/378] [deps]: Update bitwarden/gh-actions digest to 4f37134 (#649) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release-go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 5106cd5ee..418c1e30f 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -65,7 +65,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -136,7 +136,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@62d1bf7c3e31c458cc7236b1e69a475d235cd78f + uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" From b115e26580cd937b14845b22263d628825241b38 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 13:51:18 -0500 Subject: [PATCH 324/378] [deps]: Update actions/checkout digest to 1e31de5 (#648) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release-go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 418c1e30f..a8bb82f88 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -54,7 +54,7 @@ jobs: _PKG_VERSION: ${{ needs.validate.outputs.version }} steps: - name: Checkout SDK repo - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4.0.0 with: path: sdk @@ -71,7 +71,7 @@ jobs: secrets: "github-pat-bitwarden-devops-bot-repo-scope" - name: Checkout SDK-Go repo - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4.0.0 with: repository: bitwarden/sm-sdk-go path: sm-sdk-go From 9d6fa34dc48e8aec50f5725c5d857bee9f3f6b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 11 Mar 2024 11:36:42 +0100 Subject: [PATCH 325/378] [PM-6100] Test for memory leaks of secrets (#641) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Added a small test framework to test for secret leaks in memory. This consists of a few parts: - Binary crate `memory-testing`, this compiles to a binary that uses `bitwarden_crypto` to create some keys in memory and then frees them. The execution of this program goes like this: - Starts, keys get defined in memory - Waits for input (This is where we create an initial core dump) - Program frees the keys - Waits for input (This is where we create a final core dump) - Program exits normally - A `capture_dumps.py` Python script, it's purpose is starting the program and orchestrating the core dumps and sending inputs to the program to continue. - A `Dockerfile` that will compile the program and run the `capture_dumps.py` script, this is needed because the dumps only work on a Linux environment. - A `test.py` script that analyzes the memory dumps for secrets in memory - A `run_tests.sh` script that builds and runs the docker container and the test script in one invocation I've tried other tools to run it natively on other operating systems like osxpmem on mac and they either don't work on ARM Macs or they require running as root and disabling System Integrity Protection. I've also added a small workflow to run these tests, as that runs on a linux environment, it's run directly without docker. The results are printed to a table now: ![image](https://github.com/bitwarden/sdk/assets/725423/699b25bb-b184-4d46-aec1-e785df53cc88) --- .github/codecov.yml | 1 + .github/workflows/memory-testing.yml | 43 ++++++ .gitignore | 1 - Cargo.lock | 18 +++ crates/memory-testing/.gitignore | 1 + crates/memory-testing/Cargo.toml | 13 ++ crates/memory-testing/Dockerfile | 26 ++++ crates/memory-testing/Dockerfile.dockerignore | 4 + crates/memory-testing/cases.json | 9 ++ crates/memory-testing/run_test.sh | 20 +++ .../memory-testing/src/bin/analyze-dumps.rs | 132 ++++++++++++++++++ .../memory-testing/src/bin/capture-dumps.rs | 70 ++++++++++ crates/memory-testing/src/lib.rs | 29 ++++ crates/memory-testing/src/main.rs | 44 ++++++ 14 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/memory-testing.yml create mode 100644 crates/memory-testing/.gitignore create mode 100644 crates/memory-testing/Cargo.toml create mode 100644 crates/memory-testing/Dockerfile create mode 100644 crates/memory-testing/Dockerfile.dockerignore create mode 100644 crates/memory-testing/cases.json create mode 100755 crates/memory-testing/run_test.sh create mode 100644 crates/memory-testing/src/bin/analyze-dumps.rs create mode 100644 crates/memory-testing/src/bin/capture-dumps.rs create mode 100644 crates/memory-testing/src/lib.rs create mode 100644 crates/memory-testing/src/main.rs diff --git a/.github/codecov.yml b/.github/codecov.yml index 3228d009c..eb34abf9c 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,3 +1,4 @@ ignore: - "crates/sdk-schemas" # Tool - "crates/uniffi-bindgen" # Tool + - "crates/memory-testing" # Testing diff --git a/.github/workflows/memory-testing.yml b/.github/workflows/memory-testing.yml new file mode 100644 index 000000000..af5ef6b7c --- /dev/null +++ b/.github/workflows/memory-testing.yml @@ -0,0 +1,43 @@ +--- +name: Test for memory leaks + +on: + pull_request: + paths: + - "crates/bitwarden-crypto/**" + - "crates/memory-testing/**" + push: + paths: + - "crates/bitwarden-crypto/**" + - "crates/memory-testing/**" + branches: + - "main" + - "rc" + - "hotfix-rc" + +jobs: + memory-test: + name: Testing + runs-on: ubuntu-22.04 + + steps: + - name: Check out repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Set up gdb + run: | + sudo apt update + sudo apt -y install gdb + + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + toolchain: stable + + - name: Cache cargo registry + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + with: + key: memtest-cargo + + - name: Test + run: ./crates/memory-testing/run_test.sh no-docker diff --git a/.gitignore b/.gitignore index 63c5875a3..b13651d19 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ x64/ x86/ build/ bld/ -[Bb]in/ [Oo]bj/ *.wasm diff --git a/Cargo.lock b/Cargo.lock index 5c9d0fb58..b9f383413 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1544,6 +1544,12 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hkdf" version = "0.12.4" @@ -1970,6 +1976,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory-testing" +version = "0.1.0" +dependencies = [ + "bitwarden-crypto", + "comfy-table", + "hex", + "serde", + "serde_json", + "zeroize", +] + [[package]] name = "mime" version = "0.3.17" diff --git a/crates/memory-testing/.gitignore b/crates/memory-testing/.gitignore new file mode 100644 index 000000000..53752db25 --- /dev/null +++ b/crates/memory-testing/.gitignore @@ -0,0 +1 @@ +output diff --git a/crates/memory-testing/Cargo.toml b/crates/memory-testing/Cargo.toml new file mode 100644 index 000000000..c1ecbbf54 --- /dev/null +++ b/crates/memory-testing/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "memory-testing" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +comfy-table = "7.1.0" +hex = "0.4.3" +serde = "1.0.196" +serde_json = "1.0.113" +zeroize = "1.7.0" diff --git a/crates/memory-testing/Dockerfile b/crates/memory-testing/Dockerfile new file mode 100644 index 000000000..fdcf5de00 --- /dev/null +++ b/crates/memory-testing/Dockerfile @@ -0,0 +1,26 @@ +############################################### +# Build stage # +############################################### +FROM rust:1.76 AS build + +# Copy required project files +COPY . /app + +# Build project +WORKDIR /app +RUN cargo build -p memory-testing + +############################################### +# App stage # +############################################### +FROM debian:bookworm-slim + +# This specifically needs to run as root to be able to capture core dumps +USER root + +RUN apt-get update && apt-get install -y --no-install-recommends gdb=13.1-3 && apt-get clean && rm -rf /var/lib/apt/lists/* + +# Copy built project from the build stage +COPY --from=build /app/target/debug/memory-testing /app/target/debug/capture-dumps /app/crates/memory-testing/cases.json ./ + +CMD [ "/capture-dumps", "./memory-testing", "/output" ] diff --git a/crates/memory-testing/Dockerfile.dockerignore b/crates/memory-testing/Dockerfile.dockerignore new file mode 100644 index 000000000..50f4b1230 --- /dev/null +++ b/crates/memory-testing/Dockerfile.dockerignore @@ -0,0 +1,4 @@ +* +!crates/* +!Cargo.toml +!Cargo.lock diff --git a/crates/memory-testing/cases.json b/crates/memory-testing/cases.json new file mode 100644 index 000000000..eb85e2aca --- /dev/null +++ b/crates/memory-testing/cases.json @@ -0,0 +1,9 @@ +{ + "symmetric_key": [ + { + "key": "FfhVVP8fmFIZY1WmRszPmRmVCxXNWVcJffPrbkywTPtBNkgfhYGT+D9sVGizYXrPffuj2yoyWqMwF9iF5aMQhQ==", + "decrypted_key_hex": "15f85554ff1f9852196355a646cccf9919950b15cd5957097df3eb6e4cb04cfb", + "decrypted_mac_hex": "4136481f858193f83f6c5468b3617acf7dfba3db2a325aa33017d885e5a31085" + } + ] +} diff --git a/crates/memory-testing/run_test.sh b/crates/memory-testing/run_test.sh new file mode 100755 index 000000000..627e5dacd --- /dev/null +++ b/crates/memory-testing/run_test.sh @@ -0,0 +1,20 @@ +# Move to the root of the repository +cd "$(dirname "$0")" +cd ../../ + +BASE_DIR="./crates/memory-testing" + +mkdir -p $BASE_DIR/output +rm $BASE_DIR/output/* + +cargo build -p memory-testing + +if [ "$1" = "no-docker" ]; then + # This specifically needs to run as root to be able to capture core dumps + sudo ./target/debug/capture-dumps ./target/debug/memory-testing $BASE_DIR +else + docker build -f crates/memory-testing/Dockerfile -t bitwarden/memory-testing . + docker run --rm -it -v $BASE_DIR:/output bitwarden/memory-testing +fi + +./target/debug/analyze-dumps $BASE_DIR diff --git a/crates/memory-testing/src/bin/analyze-dumps.rs b/crates/memory-testing/src/bin/analyze-dumps.rs new file mode 100644 index 000000000..fee72f2e5 --- /dev/null +++ b/crates/memory-testing/src/bin/analyze-dumps.rs @@ -0,0 +1,132 @@ +use std::{env, fmt::Display, io, path::Path, process}; + +use memory_testing::*; + +fn find_subarrays(needle: &[u8], haystack: &[u8]) -> Vec { + let needle_len = needle.len(); + let haystack_len = haystack.len(); + let mut subarrays = vec![]; + + if needle_len == 0 || haystack_len == 0 || needle_len > haystack_len { + return vec![]; + } + + for i in 0..=(haystack_len - needle_len) { + if &haystack[i..i + needle_len] == needle { + subarrays.push(i); + } + } + + subarrays +} + +const OK: &str = "✅"; +const FAIL: &str = "❌"; + +fn comma_sep(nums: &[usize]) -> String { + nums.iter() + .map(ToString::to_string) + .collect::>() + .join(", ") +} + +fn add_row( + table: &mut comfy_table::Table, + name: N, + initial_pos: &[usize], + final_pos: &[usize], + ok_cond: bool, +) -> bool { + table.add_row(vec![ + name.to_string(), + comma_sep(initial_pos), + comma_sep(final_pos), + if ok_cond { + OK.to_string() + } else { + FAIL.to_string() + }, + ]); + !ok_cond +} + +fn main() -> io::Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + println!("Usage: ./analyze-dumps "); + process::exit(1); + } + let base_dir: &Path = args[1].as_ref(); + + println!("Memory testing script started"); + + let initial_core = std::fs::read(base_dir.join("output/initial_dump.bin"))?; + let final_core = std::fs::read(base_dir.join("output/final_dump.bin"))?; + + let mut error = false; + let mut table = comfy_table::Table::new(); + table.set_header(vec!["Name", "Initial", "Final", "OK"]); + + let cases = memory_testing::load_cases(base_dir); + + let test_string: Vec = TEST_STRING.as_bytes().to_vec(); + let test_initial_pos = find_subarrays(&test_string, &initial_core); + let test_final_pos = find_subarrays(&test_string, &final_core); + + error |= add_row( + &mut table, + "Test String", + &test_initial_pos, + &test_final_pos, + !test_final_pos.is_empty(), + ); + + if test_initial_pos.is_empty() { + println!("ERROR: Test string not found in initial core dump, is the dump valid?"); + error = true; + } + + for (idx, case) in cases.symmetric_key.iter().enumerate() { + let key_part: Vec = hex::decode(&case.decrypted_key_hex).unwrap(); + let mac_part: Vec = hex::decode(&case.decrypted_mac_hex).unwrap(); + let key_in_b64: Vec = case.key.as_bytes().to_vec(); + + let key_initial_pos = find_subarrays(&key_part, &initial_core); + let mac_initial_pos = find_subarrays(&mac_part, &initial_core); + let b64_initial_pos = find_subarrays(&key_in_b64, &initial_core); + + let key_final_pos = find_subarrays(&key_part, &final_core); + let mac_final_pos = find_subarrays(&mac_part, &final_core); + let b64_final_pos = find_subarrays(&key_in_b64, &final_core); + + error |= add_row( + &mut table, + format!("Symm. Key, case {}", idx), + &key_initial_pos, + &key_final_pos, + key_final_pos.is_empty(), + ); + + error |= add_row( + &mut table, + format!("Symm. MAC, case {}", idx), + &mac_initial_pos, + &mac_final_pos, + mac_final_pos.is_empty(), + ); + + // TODO: At the moment we are not zeroizing the base64 key in from_str, so this test is + // ignored + add_row( + &mut table, + format!("Symm. Key in Base64, case {}", idx), + &b64_initial_pos, + &b64_final_pos, + b64_final_pos.is_empty(), + ); + } + + println!("{table}"); + + process::exit(if error { 1 } else { 0 }); +} diff --git a/crates/memory-testing/src/bin/capture-dumps.rs b/crates/memory-testing/src/bin/capture-dumps.rs new file mode 100644 index 000000000..f43905867 --- /dev/null +++ b/crates/memory-testing/src/bin/capture-dumps.rs @@ -0,0 +1,70 @@ +use std::{ + fs, + io::{self, prelude::*}, + path::Path, + process::{Command, Stdio}, + thread::sleep, + time::Duration, +}; + +fn dump_process_to_bytearray(pid: u32, output_dir: &Path, output_name: &Path) -> io::Result { + Command::new("gcore") + .args(["-a", &pid.to_string()]) + .output()?; + + let core_path = format!("core.{}", pid); + let output_path = output_dir.join(output_name); + let len = fs::copy(&core_path, output_path)?; + fs::remove_file(&core_path)?; + Ok(len) +} + +fn main() -> io::Result<()> { + let args: Vec = std::env::args().collect(); + if args.len() < 3 { + println!("Usage: ./capture_dumps "); + std::process::exit(1); + } + + let binary_path = &args[1]; + let base_dir: &Path = args[2].as_ref(); + + println!("Memory dump capture script started"); + + let mut proc = Command::new(binary_path) + .arg(base_dir) + .stdout(Stdio::inherit()) + .stdin(Stdio::piped()) + .spawn()?; + let id = proc.id(); + println!("Started memory testing process with PID: {}", id); + let stdin = proc.stdin.as_mut().expect("Valid stdin"); + + // Wait a bit for it to process + sleep(Duration::from_secs(3)); + + // Dump the process before the variables are freed + let initial_core = + dump_process_to_bytearray(id, &base_dir.join("output"), "initial_dump.bin".as_ref())?; + println!("Initial core dump file size: {}", initial_core); + + stdin.write_all(b".")?; + stdin.flush()?; + + // Wait a bit for it to process + sleep(Duration::from_secs(1)); + + // Dump the process after the variables are freed + let final_core = + dump_process_to_bytearray(id, &base_dir.join("output"), "final_dump.bin".as_ref())?; + println!("Final core dump file size: {}", final_core); + + stdin.write_all(b".")?; + stdin.flush()?; + + // Wait for the process to finish and print the output + let output = proc.wait()?; + println!("Return code: {}", output); + + std::process::exit(output.code().unwrap_or(1)); +} diff --git a/crates/memory-testing/src/lib.rs b/crates/memory-testing/src/lib.rs new file mode 100644 index 000000000..e633756d1 --- /dev/null +++ b/crates/memory-testing/src/lib.rs @@ -0,0 +1,29 @@ +use std::path::Path; + +use zeroize::Zeroize; + +pub const TEST_STRING: &str = "THIS IS USED TO CHECK THAT THE MEMORY IS DUMPED CORRECTLY"; + +pub fn load_cases(base_dir: &Path) -> Cases { + let mut json_str = std::fs::read_to_string(base_dir.join("cases.json")).unwrap(); + let cases: Cases = serde_json::from_str(&json_str).unwrap(); + + // Make sure that we don't leave extra copies of the data in memory + json_str.zeroize(); + cases +} + +// Note: We don't actively zeroize these structs here because we want the code in bitwarden_crypto +// to handle it for us +#[derive(serde::Deserialize)] +pub struct Cases { + pub symmetric_key: Vec, +} + +#[derive(serde::Deserialize)] +pub struct SymmetricKeyCases { + pub key: String, + + pub decrypted_key_hex: String, + pub decrypted_mac_hex: String, +} diff --git a/crates/memory-testing/src/main.rs b/crates/memory-testing/src/main.rs new file mode 100644 index 000000000..96e4ae175 --- /dev/null +++ b/crates/memory-testing/src/main.rs @@ -0,0 +1,44 @@ +use std::{env, io::Read, path::Path, process, str::FromStr}; + +use bitwarden_crypto::SymmetricCryptoKey; + +fn wait_for_dump() { + println!("Waiting for dump..."); + std::io::stdin().read_exact(&mut [1u8]).unwrap(); +} + +fn main() { + let args: Vec = env::args().collect(); + if args.len() < 2 { + println!("Usage: ./memory-testing "); + process::exit(1); + } + let base_dir: &Path = args[1].as_ref(); + + let test_string = String::from(memory_testing::TEST_STRING); + + let cases = memory_testing::load_cases(base_dir); + + let mut symmetric_keys = Vec::new(); + let mut symmetric_keys_as_vecs = Vec::new(); + + for case in &cases.symmetric_key { + let key = SymmetricCryptoKey::from_str(&case.key).unwrap(); + symmetric_keys_as_vecs.push(key.to_vec()); + symmetric_keys.push(key); + } + + // Make a memory dump before the variables are freed + wait_for_dump(); + + // Use all the variables so the compiler doesn't decide to remove them + println!("{test_string} {symmetric_keys:?} {symmetric_keys_as_vecs:?}"); + + drop(symmetric_keys); + drop(symmetric_keys_as_vecs); + + // After the variables are dropped, we want to make another dump + wait_for_dump(); + + println!("Done!") +} From a9c4bcb4ee031da966eb5d195136243ac5a7c55e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Mon, 11 Mar 2024 17:43:34 +0100 Subject: [PATCH 326/378] [DEVOPS-1750] Fix go release (#646) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/build-rust-cross-platform.yml:** Add ARM64 linux build - **.github/workflows/release-go.yml** Download precompiled C artifacts and place them in the repo ## Before you submit - Please add **unit tests** where it makes sense to do so --------- Co-authored-by: Vince Grassia <593223+vgrassia@users.noreply.github.com> --- .../workflows/build-rust-cross-platform.yml | 1 + .github/workflows/release-go.yml | 70 +++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 67c41c6f9..0db2d0cde 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -8,6 +8,7 @@ on: - main - rc - hotfix-rc + pull_request: jobs: build_rust: diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index a8bb82f88..cc17a4905 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Branch check - if: ${{ github.event.inputs.release_type != 'Dry Run' }} + if: ${{ inputs.release_type != 'Dry Run' }} run: | if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then echo "===================================" @@ -58,6 +58,15 @@ jobs: with: path: sdk + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: generate_schemas.yml + path: sdk/languages/go/bitwarden_sdk_secrets/lib + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: schemas.go + - name: Login to Azure - Prod Subscription uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 with: @@ -89,13 +98,19 @@ jobs: # Copy files to local sm-sdk-go repo path cp --verbose -rf sdk/languages/go/. sm-sdk-go + - name: Replace repo name + working-directory: sm-sdk-go + run: | + find . -name '*' -exec \ + gsed -i -e 's/github.com\/bitwarden\/sdk\/languages\/go/github.com\/bitwarden\/sm-sdk-go/g' {} \; + - name: Push changes working-directory: sm-sdk-go run: | git add . git commit -m "Update Go SDK to ${{ github.sha }}" - if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then + if [[ "${{ inputs.release_type }}" == "Dry Run" ]]; then echo "===================================" echo "[!] Dry Run - Skipping push" echo "===================================" @@ -106,7 +121,7 @@ jobs: fi - name: Create release tag on SDK Go repo - if: ${{ github.event.inputs.release_type != 'Dry Run' }} + if: ${{ inputs.release_type != 'Dry Run' }} working-directory: sm-sdk-go run: | # Check if tag exists, set output then exit 0 if true. @@ -141,8 +156,51 @@ jobs: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" + - name: Download x86_64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-apple-darwin + skip_unpack: true + + - name: Download aarch64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-aarch64-apple-darwin + skip_unpack: true + + - name: Download x86_64-unknown-linux-gnu artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-unknown-linux-gnu + skip_unpack: true + + - name: Download x86_64-pc-windows-msvc artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-pc-windows-msvc + skip_unpack: true + + - name: Rename build artifacts + run: | + mv libbitwarden_c_files-x86_64-apple-darwin.zip libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION.zip + mv libbitwarden_c_files-aarch64-apple-darwin.zip libbitwarden_c_files-aarch64-apple-darwin-$_PKG_VERSION.zip + mv libbitwarden_c_files-x86_64-unknown-linux-gnu.zip libbitwarden_c_files-x86_64-unknown-linux-gnu-$_PKG_VERSION.zip + mv libbitwarden_c_files-x86_64-pc-windows-msvc.zip libbitwarden_c_files-x86_64-pc-windows-msvc-$_PKG_VERSION.zip + - name: Create release - if: ${{ github.event.inputs.release_type != 'Dry Run' }} + if: ${{ inputs.release_type != 'Dry Run' }} uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 with: tag: v${{ env._PKG_VERSION }} @@ -152,3 +210,7 @@ jobs: draft: true repo: sm-sdk-go owner: bitwarden + artifacts: "libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION.zip, + libbitwarden_c_files-aarch64-apple-darwin-$_PKG_VERSION.zip, + libbitwarden_c_files-x86_64-unknown-linux-gnu-$_PKG_VERSION.zip, + libbitwarden_c_files-x86_64-pc-windows-msvc-$_PKG_VERSION.zip" From 0bf163659ce220fda6d8ff5267f0a2e240d9dbc6 Mon Sep 17 00:00:00 2001 From: Robyn MacCallum Date: Mon, 11 Mar 2024 19:43:29 -0400 Subject: [PATCH 327/378] Ruby updates (#654) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ``` ## Objective Fix ruby release date and add state to the ruby example ## Before you submit - Please add **unit tests** where it makes sense to do so --- languages/ruby/CHANGELOG.md | 3 ++- languages/ruby/examples/example.rb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/languages/ruby/CHANGELOG.md b/languages/ruby/CHANGELOG.md index 91c5ee3c2..0c842ecbb 100644 --- a/languages/ruby/CHANGELOG.md +++ b/languages/ruby/CHANGELOG.md @@ -1,5 +1,6 @@ ## [Unreleased] -## [0.1.0] - 2023-09-19 +## [0.1.0] - 2024-02-23 - Initial release + diff --git a/languages/ruby/examples/example.rb b/languages/ruby/examples/example.rb index 3c8e2045d..d1c7ce455 100644 --- a/languages/ruby/examples/example.rb +++ b/languages/ruby/examples/example.rb @@ -3,6 +3,7 @@ token = ENV['ACCESS_TOKEN'] organization_id = ENV['ORGANIZATION_ID'] +state_path = ENV['STATE_PATH'] # Configuring the URLS is optional, set them to nil to use the default values api_url = ENV['API_URL'] @@ -11,7 +12,7 @@ bitwarden_settings = BitwardenSDKSecrets::BitwardenSettings.new(api_url, identity_url) bw_client = BitwardenSDKSecrets::BitwardenClient.new(bitwarden_settings) -response = bw_client.access_token_login(token) +response = bw_client.access_token_login(token, state_path) puts response # CREATE project From ec54a8933b9dd0f56e0fa0b7ebb8b00b330e65a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 12 Mar 2024 11:13:01 +0100 Subject: [PATCH 328/378] [DEVOPS-1750] Fix Go release artifacts (#655) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Fix version reference in release artifacts in Go release workflow. ## Code changes - **.github/workflows/release-go.yml:** Fix version reference in release artifacts ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/release-go.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index cc17a4905..c7a198056 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -210,7 +210,7 @@ jobs: draft: true repo: sm-sdk-go owner: bitwarden - artifacts: "libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION.zip, - libbitwarden_c_files-aarch64-apple-darwin-$_PKG_VERSION.zip, - libbitwarden_c_files-x86_64-unknown-linux-gnu-$_PKG_VERSION.zip, - libbitwarden_c_files-x86_64-pc-windows-msvc-$_PKG_VERSION.zip" + artifacts: "libbitwarden_c_files-x86_64-apple-darwin-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-aarch64-apple-darwin-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-x86_64-unknown-linux-gnu-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-x86_64-pc-windows-msvc-${{ env._PKG_VERSION }}.zip" From 07a4ceb663aab1b057beb54c6856073a98d9da54 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 12 Mar 2024 16:19:25 +0100 Subject: [PATCH 329/378] Move access token to auth (#656) Move access token from client to auth. --- crates/bitwarden/CHANGELOG.md | 3 ++- .../src/{client => auth}/access_token.rs | 6 ++---- crates/bitwarden/src/auth/login/access_token.rs | 4 ++-- crates/bitwarden/src/auth/mod.rs | 2 ++ crates/bitwarden/src/client/client.rs | 16 ++++++++-------- crates/bitwarden/src/client/mod.rs | 2 -- crates/bitwarden/src/secrets_manager/state.rs | 2 +- crates/bws/src/main.rs | 4 ++-- 8 files changed, 19 insertions(+), 20 deletions(-) rename crates/bitwarden/src/{client => auth}/access_token.rs (97%) diff --git a/crates/bitwarden/CHANGELOG.md b/crates/bitwarden/CHANGELOG.md index ff47c19d8..ee4c6033b 100644 --- a/crates/bitwarden/CHANGELOG.md +++ b/crates/bitwarden/CHANGELOG.md @@ -9,7 +9,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed -- Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. +- Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. (#374) +- `client::AccessToken` is now `auth::AccessToken`. (#656) ## [0.4.0] - 2023-12-21 diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/auth/access_token.rs similarity index 97% rename from crates/bitwarden/src/client/access_token.rs rename to crates/bitwarden/src/auth/access_token.rs index d7cad2fca..667a78529 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/auth/access_token.rs @@ -65,12 +65,12 @@ impl FromStr for AccessToken { #[cfg(test)] mod tests { + use super::AccessToken; + #[test] fn can_decode_access_token() { use std::str::FromStr; - use crate::client::AccessToken; - let access_token = "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ=="; let token = AccessToken::from_str(access_token).unwrap(); @@ -86,8 +86,6 @@ mod tests { fn malformed_tokens() { use std::str::FromStr; - use crate::client::AccessToken; - // Encryption key without base64 padding, we generate it with padding but ignore it when // decoding let t = "0.ec2c1d46-6a4b-4751-a310-af9601317f2d.C2IgxjjLF7qSshsbwe8JGcbM075YXw:X8vbvA0bduihIDe/qrzIQQ"; diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index d540b31a8..46c3f2b50 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -11,9 +11,9 @@ use crate::{ auth::{ api::{request::AccessTokenRequest, response::IdentityTokenResponse}, login::{response::two_factor::TwoFactorProviders, PasswordLoginResponse}, - JWTToken, + AccessToken, JWTToken, }, - client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, + client::{LoginMethod, ServiceAccountLoginMethod}, error::{Error, Result}, secrets_manager::state::{self, ClientState}, Client, diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 021c97c0f..7918694e2 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -1,3 +1,4 @@ +mod access_token; pub(super) mod api; pub mod client_auth; mod jwt_token; @@ -5,6 +6,7 @@ pub mod login; #[cfg(feature = "internal")] pub mod password; pub mod renew; +pub use access_token::AccessToken; pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 45f58444c..883720529 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -9,9 +9,16 @@ use chrono::Utc; use reqwest::header::{self, HeaderValue}; use uuid::Uuid; -use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::{ + auth::AccessToken, + client::{ + client_settings::{ClientSettings, DeviceType}, + encryption_settings::EncryptionSettings, + }, + error::{Error, Result}, +}; #[cfg(feature = "internal")] use crate::{ client::flags::Flags, @@ -20,13 +27,6 @@ use crate::{ UserApiKeyResponse, }, }; -use crate::{ - client::{ - client_settings::{ClientSettings, DeviceType}, - encryption_settings::EncryptionSettings, - }, - error::{Error, Result}, -}; #[derive(Debug)] pub(crate) struct ApiConfigurations { diff --git a/crates/bitwarden/src/client/mod.rs b/crates/bitwarden/src/client/mod.rs index f6d60e961..0c703570f 100644 --- a/crates/bitwarden/src/client/mod.rs +++ b/crates/bitwarden/src/client/mod.rs @@ -1,7 +1,6 @@ //! Bitwarden SDK Client pub(crate) use client::*; -pub(crate) mod access_token; #[allow(clippy::module_inception)] mod client; pub mod client_settings; @@ -10,5 +9,4 @@ pub(crate) mod encryption_settings; #[cfg(feature = "internal")] mod flags; -pub use access_token::AccessToken; pub use client::Client; diff --git a/crates/bitwarden/src/secrets_manager/state.rs b/crates/bitwarden/src/secrets_manager/state.rs index 4efa4403b..b2b6f6a8e 100644 --- a/crates/bitwarden/src/secrets_manager/state.rs +++ b/crates/bitwarden/src/secrets_manager/state.rs @@ -4,7 +4,7 @@ use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable}; use serde::{Deserialize, Serialize}; use crate::{ - client::AccessToken, + auth::AccessToken, error::{Error, Result}, }; diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index cb130b52c..6ed78f7b7 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -1,8 +1,8 @@ use std::{path::PathBuf, process, str::FromStr}; use bitwarden::{ - auth::login::AccessTokenLoginRequest, - client::{client_settings::ClientSettings, AccessToken}, + auth::{login::AccessTokenLoginRequest, AccessToken}, + client::client_settings::ClientSettings, secrets_manager::{ projects::{ ProjectCreateRequest, ProjectGetRequest, ProjectPutRequest, ProjectsDeleteRequest, From aaa6466c60f50d52781baa0be1fc301e23b125e3 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 14 Mar 2024 12:31:52 +0100 Subject: [PATCH 330/378] [PM-6761] Add fido credentials to data model (#657) Add `Fido2Credentials` to the `Login` struct to support storing passkeys. Currently we don't decrypt passkeys but rather pass them along encrypted to ensure we can re-encrypt the login without data loss. --- crates/bitwarden/src/tool/exporters/mod.rs | 1 + crates/bitwarden/src/vault/cipher/cipher.rs | 1 + crates/bitwarden/src/vault/cipher/login.rs | 56 +++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 9e9e99ed5..45bdfd3fd 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -240,6 +240,7 @@ mod tests { uris: None, totp: None, autofill_on_page_load: None, + fido2_credentials: None, }), id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), organization_id: None, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 24207251f..47b58694d 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -433,6 +433,7 @@ mod tests { uris: None, totp: None, autofill_on_page_load: None, + fido2_credentials: None, }), id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), organization_id: None, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 5e2156a83..5d00c41e1 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -38,6 +38,25 @@ pub struct LoginUriView { pub r#match: Option, } +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct Fido2Credential { + pub credential_id: EncString, + pub key_type: EncString, + pub key_algorithm: EncString, + pub key_curve: EncString, + pub key_value: EncString, + pub rp_id: EncString, + pub user_handle: Option, + pub user_name: Option, + pub counter: EncString, + pub rp_name: Option, + pub user_display_name: Option, + pub discoverable: EncString, + pub creation_date: DateTime, +} + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -49,6 +68,8 @@ pub struct Login { pub uris: Option>, pub totp: Option, pub autofill_on_page_load: Option, + + pub fido2_credentials: Option>, } #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -62,6 +83,9 @@ pub struct LoginView { pub uris: Option>, pub totp: Option, pub autofill_on_page_load: Option, + + // TODO: Remove this once the SDK supports state + pub fido2_credentials: Option>, } impl KeyEncryptable for LoginUriView { @@ -82,6 +106,7 @@ impl KeyEncryptable for LoginView { uris: self.uris.encrypt_with_key(key)?, totp: self.totp.encrypt_with_key(key)?, autofill_on_page_load: self.autofill_on_page_load, + fido2_credentials: self.fido2_credentials, }) } } @@ -104,6 +129,7 @@ impl KeyDecryptable for Login { uris: self.uris.decrypt_with_key(key).ok().flatten(), totp: self.totp.decrypt_with_key(key).ok().flatten(), autofill_on_page_load: self.autofill_on_page_load, + fido2_credentials: self.fido2_credentials.clone(), }) } } @@ -125,6 +151,10 @@ impl TryFrom for Login { .transpose()?, totp: EncString::try_from_optional(login.totp)?, autofill_on_page_load: login.autofill_on_page_load, + fido2_credentials: login + .fido2_credentials + .map(|v| v.into_iter().map(|c| c.try_into()).collect()) + .transpose()?, }) } } @@ -152,3 +182,29 @@ impl From for UriMatchType { } } } + +impl TryFrom for Fido2Credential { + type Error = Error; + + fn try_from(value: bitwarden_api_api::models::CipherFido2CredentialModel) -> Result { + Ok(Self { + credential_id: value.credential_id.ok_or(Error::MissingFields)?.parse()?, + key_type: value.key_type.ok_or(Error::MissingFields)?.parse()?, + key_algorithm: value.key_algorithm.ok_or(Error::MissingFields)?.parse()?, + key_curve: value.key_curve.ok_or(Error::MissingFields)?.parse()?, + key_value: value.key_value.ok_or(Error::MissingFields)?.parse()?, + rp_id: value.rp_id.ok_or(Error::MissingFields)?.parse()?, + user_handle: EncString::try_from_optional(value.user_handle) + .ok() + .flatten(), + user_name: EncString::try_from_optional(value.user_name).ok().flatten(), + counter: value.counter.ok_or(Error::MissingFields)?.parse()?, + rp_name: EncString::try_from_optional(value.rp_name).ok().flatten(), + user_display_name: EncString::try_from_optional(value.user_display_name) + .ok() + .flatten(), + discoverable: value.discoverable.ok_or(Error::MissingFields)?.parse()?, + creation_date: value.creation_date.parse().unwrap(), + }) + } +} From dd440baa7797dcf90175ac6bf0e7ad26f15cf6fb Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 14 Mar 2024 12:55:22 +0100 Subject: [PATCH 331/378] Mark exporters and generators as internal dependencies (#660) We accidentally exposed exporters and generators without feature flagging them. This PR properly puts them under the internal feature flag. --- crates/bitwarden-crypto/Cargo.toml | 2 +- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 11 +++++++---- crates/bitwarden/src/error.rs | 6 ++++++ crates/bitwarden/src/lib.rs | 1 + 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 54a9f760e..c1104faba 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -15,7 +15,7 @@ rust-version = "1.71" [features] default = [] -mobile = ["uniffi"] +mobile = ["dep:uniffi"] # Mobile-specific features [dependencies] aes = { version = ">=0.8.2, <0.9", features = ["zeroize"] } diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index 8f06de664..8ee2806a0 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.71" [features] -mobile = ["uniffi"] # Mobile-specific features +mobile = ["dep:uniffi"] # Mobile-specific features [dependencies] bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 9950a788a..37dbe28c3 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -16,10 +16,13 @@ rust-version = "1.71" default = ["secrets"] secrets = [] # Secrets manager API -internal = [] # Internal testing methods +internal = [ + "dep:bitwarden-exporters", + "dep:bitwarden-generators", +] # Internal testing methods mobile = [ - "uniffi", "internal", + "dep:uniffi", "bitwarden-crypto/mobile", "bitwarden-generators/mobile", ] # Mobile-specific features @@ -31,8 +34,8 @@ base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } -bitwarden-exporters = { path = "../bitwarden-exporters", version = "0.1.0" } -bitwarden-generators = { path = "../bitwarden-generators", version = "0.1.0" } +bitwarden-exporters = { path = "../bitwarden-exporters", version = "0.1.0", optional = true } +bitwarden-generators = { path = "../bitwarden-generators", version = "0.1.0", optional = true } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index ed5d27c3e..bd040e51b 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -4,7 +4,9 @@ use std::{borrow::Cow, fmt::Debug}; use bitwarden_api_api::apis::Error as ApiError; use bitwarden_api_identity::apis::Error as IdentityError; +#[cfg(feature = "internal")] use bitwarden_exporters::ExportError; +#[cfg(feature = "internal")] use bitwarden_generators::{PassphraseError, PasswordError, UsernameError}; use reqwest::StatusCode; use thiserror::Error; @@ -52,13 +54,17 @@ pub enum Error { InvalidStateFile, // Generators + #[cfg(feature = "internal")] #[error(transparent)] UsernameError(#[from] UsernameError), + #[cfg(feature = "internal")] #[error(transparent)] PassphraseError(#[from] PassphraseError), + #[cfg(feature = "internal")] #[error(transparent)] PasswordError(#[from] PasswordError), + #[cfg(feature = "internal")] #[error(transparent)] ExportError(#[from] ExportError), diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index 28eb521de..17774b002 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -75,6 +75,7 @@ pub use client::Client; #[doc = include_str!("../README.md")] mod readme {} +#[cfg(feature = "internal")] pub mod generators { pub use bitwarden_generators::{ PassphraseGeneratorRequest, PasswordGeneratorRequest, UsernameGeneratorRequest, From d2742c838233a765dc37e2427193a2ffbbe06043 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 15 Mar 2024 17:32:56 +0100 Subject: [PATCH 332/378] Extract shared metadata to workspace and link (#661) - Extract shared metadata into the workspace `Cargo.toml` and link packages to use it. This ensures we have a single point of truth and will simplify updating. - Added `publish = false` to all packages that are not published on `crates.io` to prevent accidental publication. - Remove duplicated license files --- Cargo.toml | 21 +- crates/bitwarden-api-api/Cargo.toml | 14 +- crates/bitwarden-api-api/LICENSE | 295 ----------------------- crates/bitwarden-api-identity/Cargo.toml | 14 +- crates/bitwarden-api-identity/LICENSE | 295 ----------------------- crates/bitwarden-c/Cargo.toml | 10 +- crates/bitwarden-c/LICENSE | 295 ----------------------- crates/bitwarden-cli/Cargo.toml | 10 +- crates/bitwarden-crypto/Cargo.toml | 15 +- crates/bitwarden-exporters/Cargo.toml | 17 +- crates/bitwarden-generators/Cargo.toml | 17 +- crates/bitwarden-json/Cargo.toml | 18 +- crates/bitwarden-json/LICENSE | 295 ----------------------- crates/bitwarden-napi/Cargo.toml | 20 +- crates/bitwarden-napi/LICENSE | 295 ----------------------- crates/bitwarden-py/Cargo.toml | 11 +- crates/bitwarden-py/LICENSE | 295 ----------------------- crates/bitwarden-uniffi/Cargo.toml | 20 +- crates/bitwarden-wasm/Cargo.toml | 11 +- crates/bitwarden-wasm/LICENSE | 295 ----------------------- crates/bitwarden/Cargo.toml | 23 +- crates/bitwarden/LICENSE | 295 ----------------------- crates/bw/Cargo.toml | 18 +- crates/bw/LICENSE | 295 ----------------------- crates/bws/Cargo.toml | 15 +- crates/bws/LICENSE | 295 ----------------------- crates/memory-testing/Cargo.toml | 11 +- crates/sdk-schemas/Cargo.toml | 11 +- crates/uniffi-bindgen/Cargo.toml | 11 +- 29 files changed, 184 insertions(+), 3053 deletions(-) delete mode 100644 crates/bitwarden-api-api/LICENSE delete mode 100644 crates/bitwarden-api-identity/LICENSE delete mode 100644 crates/bitwarden-c/LICENSE delete mode 100644 crates/bitwarden-json/LICENSE delete mode 100644 crates/bitwarden-napi/LICENSE delete mode 100644 crates/bitwarden-py/LICENSE delete mode 100644 crates/bitwarden-wasm/LICENSE delete mode 100644 crates/bitwarden/LICENSE delete mode 100644 crates/bw/LICENSE delete mode 100644 crates/bws/LICENSE diff --git a/Cargo.toml b/Cargo.toml index 125aac2a8..64920d58c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,27 @@ [workspace] resolver = "2" - members = ["crates/*"] +# Global settings for all crates should be defined here +[workspace.package] +authors = ["Bitwarden Inc"] +edition = "2021" +# Note: Changing rust-version should be considered a breaking change +rust-version = "1.71" +homepage = "https://bitwarden.com" +repository = "https://github.com/bitwarden/sdk" +license-file = "LICENSE" +keywords = ["bitwarden"] + +# Define dependencies that are expected to be consistent across all crates +[workspace.dependencies] +bitwarden = { path = "crates/bitwarden", version = "0.4.0" } +bitwarden-api-api = { path = "crates/bitwarden-api-api", version = "0.2.3" } +bitwarden-api-identity = { path = "crates/bitwarden-api-identity", version = "=0.2.3" } +bitwarden-crypto = { path = "crates/bitwarden-crypto", version = "=0.1.0" } +bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=0.1.0" } +bitwarden-generators = { path = "crates/bitwarden-generators", version = "=0.1.0" } + # Compile all dependencies with some optimizations when building this crate on debug # This slows down clean builds by about 50%, but the resulting binaries can be orders of magnitude faster # As clean builds won't occur very often, this won't slow down the development process diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index 5b8b0c773..427b4bd97 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -1,16 +1,18 @@ [package] name = "bitwarden-api-api" version = "0.2.3" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Api bindings for the Bitwarden API. """ -keywords = ["bitwarden"] categories = ["api-bindings"] -edition = "2018" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [dependencies] serde = ">=1.0.163, <2" diff --git a/crates/bitwarden-api-api/LICENSE b/crates/bitwarden-api-api/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-api-api/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 4f4b46732..7f09cfdb8 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -1,16 +1,18 @@ [package] name = "bitwarden-api-identity" version = "0.2.3" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Api bindings for the Bitwarden Identity API. """ -keywords = ["bitwarden"] categories = ["api-bindings"] -edition = "2018" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [dependencies] serde = ">=1.0.163, <2" diff --git a/crates/bitwarden-api-identity/LICENSE b/crates/bitwarden-api-identity/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-api-identity/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-c/Cargo.toml b/crates/bitwarden-c/Cargo.toml index 211a482e9..e3f966ee1 100644 --- a/crates/bitwarden-c/Cargo.toml +++ b/crates/bitwarden-c/Cargo.toml @@ -1,8 +1,14 @@ [package] name = "bitwarden-c" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true [lib] crate-type = ["lib", "staticlib", "cdylib"] diff --git a/crates/bitwarden-c/LICENSE b/crates/bitwarden-c/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-c/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index 0c32ce556..de5a4f9fc 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -1,8 +1,14 @@ [package] name = "bitwarden-cli" version = "0.1.0" -edition = "2021" -rust-version = "1.71" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [dependencies] clap = { version = "4.5.1", features = ["derive"] } diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index c1104faba..ce0424c63 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "bitwarden-crypto" version = "0.1.0" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Internal crate for the bitwarden crate. Do not use. """ -keywords = ["bitwarden"] -edition = "2021" -rust-version = "1.71" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [features] default = [] diff --git a/crates/bitwarden-exporters/Cargo.toml b/crates/bitwarden-exporters/Cargo.toml index 40316437f..0607369d0 100644 --- a/crates/bitwarden-exporters/Cargo.toml +++ b/crates/bitwarden-exporters/Cargo.toml @@ -1,21 +1,22 @@ [package] name = "bitwarden-exporters" version = "0.1.0" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Internal crate for the bitwarden crate. Do not use. """ -keywords = ["bitwarden"] -edition = "2021" -rust-version = "1.57" exclude = ["/resources"] +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true + [dependencies] base64 = ">=0.21.2, <0.22" -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-crypto = { workspace = true } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index 8ee2806a0..e43d4530f 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -1,22 +1,23 @@ [package] name = "bitwarden-generators" version = "0.1.0" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Internal crate for the bitwarden crate. Do not use. """ -keywords = ["bitwarden"] -edition = "2021" -rust-version = "1.71" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [features] mobile = ["dep:uniffi"] # Mobile-specific features [dependencies] -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-crypto = { workspace = true } rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = [ "json", diff --git a/crates/bitwarden-json/Cargo.toml b/crates/bitwarden-json/Cargo.toml index 5949ce8cf..16116567b 100644 --- a/crates/bitwarden-json/Cargo.toml +++ b/crates/bitwarden-json/Cargo.toml @@ -1,17 +1,19 @@ [package] name = "bitwarden-json" version = "0.3.0" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ JSON bindings for the Bitwarden Secret Manager SDK """ -keywords = ["bitwarden", "secrets manager"] +keywords = ["bitwarden", "secrets-manager"] categories = ["api-bindings"] -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true [features] internal = ["bitwarden/internal"] # Internal testing methods @@ -24,4 +26,4 @@ schemars = ">=0.8.12, <0.9" serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" -bitwarden = { path = "../bitwarden" } +bitwarden = { workspace = true } diff --git a/crates/bitwarden-json/LICENSE b/crates/bitwarden-json/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-json/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 296f5f45f..016401fe7 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -1,16 +1,18 @@ [package] name = "bitwarden-napi" version = "0.3.1" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ N-API bindings for the Bitwarden Secrets Manager SDK """ -keywords = ["bitwarden", "secrets manager"] -edition = "2021" -rust-version = "1.71" +keywords = ["bitwarden", "secrets-manager"] +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true [lib] crate-type = ["cdylib", "rlib"] @@ -21,7 +23,9 @@ log = "0.4.20" napi = { version = "2", features = ["async"] } napi-derive = "2" -bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = ["secrets"] } +bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = [ + "secrets", +] } [build-dependencies] napi-build = "2.1.0" diff --git a/crates/bitwarden-napi/LICENSE b/crates/bitwarden-napi/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-napi/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index f954b0a20..f66a0c11f 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -1,8 +1,15 @@ [package] name = "bitwarden-py" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [lib] name = "bitwarden_py" diff --git a/crates/bitwarden-py/LICENSE b/crates/bitwarden-py/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-py/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index eb316ceca..94572b991 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -1,8 +1,14 @@ [package] name = "bitwarden-uniffi" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true [features] docs = ["dep:schemars"] # Docs @@ -21,13 +27,9 @@ env_logger = "0.11.1" schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.26.1" -bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0", features = [ - "mobile", -] } -bitwarden-generators = { path = "../bitwarden-generators", version = "=0.1.0", features = [ - "mobile", -] } +bitwarden = { workspace = true, features = ["mobile", "internal"] } +bitwarden-crypto = { workspace = true, features = ["mobile"] } +bitwarden-generators = { workspace = true, features = ["mobile"] } [build-dependencies] uniffi = { version = "=0.26.1", features = ["build"] } diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 547ea25ff..a688f12b6 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -1,8 +1,15 @@ [package] name = "bitwarden-wasm" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [lib] crate-type = ["cdylib"] diff --git a/crates/bitwarden-wasm/LICENSE b/crates/bitwarden-wasm/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden-wasm/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 37dbe28c3..59e7dd8e5 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "bitwarden" version = "0.4.0" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Bitwarden Secrets Manager SDK """ keywords = ["bitwarden", "secrets-manager"] -edition = "2021" -rust-version = "1.71" + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true [features] default = ["secrets"] @@ -31,11 +32,11 @@ wasm-bindgen = ["chrono/wasmbind"] [dependencies] base64 = ">=0.21.2, <0.22" -bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } -bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } -bitwarden-exporters = { path = "../bitwarden-exporters", version = "0.1.0", optional = true } -bitwarden-generators = { path = "../bitwarden-generators", version = "0.1.0", optional = true } +bitwarden-api-api = { workspace = true } +bitwarden-api-identity = { workspace = true } +bitwarden-crypto = { workspace = true } +bitwarden-exporters = { workspace = true, optional = true } +bitwarden-generators = { workspace = true, optional = true } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", diff --git a/crates/bitwarden/LICENSE b/crates/bitwarden/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bitwarden/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index 3d2762ac3..c54c35e28 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -1,17 +1,18 @@ [package] name = "bw" version = "0.0.2" -edition = "2021" -rust-version = "1.71" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Bitwarden Password Manager CLI """ keywords = ["bitwarden", "password-manager", "cli"] +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true + [dependencies] clap = { version = "4.5.1", features = ["derive", "env"] } color-eyre = "0.6" @@ -20,10 +21,7 @@ inquire = "0.6.2" log = "0.4.20" tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } -bitwarden = { path = "../bitwarden", version = "0.4.0", features = [ - "internal", - "mobile", -] } +bitwarden = { workspace = true, features = ["internal", "mobile"] } bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } [dev-dependencies] diff --git a/crates/bw/LICENSE b/crates/bw/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bw/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 9dc6cb355..f85744656 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -1,18 +1,19 @@ [package] name = "bws" version = "0.4.0" -edition = "2021" -rust-version = "1.71" -authors = ["Bitwarden Inc"] -license-file = "LICENSE" -repository = "https://github.com/bitwarden/sdk" -homepage = "https://bitwarden.com" description = """ Bitwarden Secrets Manager CLI """ keywords = ["bitwarden", "secrets-manager", "cli"] exclude = ["Dockerfile*", "entitlements.plist"] +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true + [dependencies] bat = { version = "0.24.0", features = [ "regex-onig", @@ -41,7 +42,7 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.10" uuid = { version = "^1.7.0", features = ["serde"] } -bitwarden = { path = "../bitwarden", version = "0.4.0", features = ["secrets"] } +bitwarden = { workspace = true, features = ["secrets"] } [dev-dependencies] tempfile = "3.10.0" diff --git a/crates/bws/LICENSE b/crates/bws/LICENSE deleted file mode 100644 index e9d496ff7..000000000 --- a/crates/bws/LICENSE +++ /dev/null @@ -1,295 +0,0 @@ -BITWARDEN SOFTWARE DEVELOPMENT KIT LICENSE AGREEMENT -Version 1, 17 March 2023 - -1. Introduction - -1.1 The Bitwarden Software Development Kit (referred to in the License Agreement -as the "SDK" and available for download at the following URL -https://github.com/bitwarden/sdk) is licensed to you subject to the terms of -this License Agreement. The License Agreement forms a legally binding contract -between you and the Company in relation to your use of the SDK. - -1.2 "Bitwarden" means the Bitwarden software made available by the Company, -available for download at the following URL, as updated from time to time. - -1.3 A "Compatible Application" means any software program or service that (i) -connects to and interoperates with a current version of the Bitwarden server -products distributed by the Company; and (ii) complies with the Company’s -acceptable use policy available at the following URL: -https://bitwarden.com/terms/#acceptable_use. - -1.4 "Company" means Bitwarden Inc., organized under the laws of the State of -Delaware. - -2. Accepting this License Agreement - -2.1 In order to access or use the SDK, you must first agree to the License -Agreement. You may not access or use the SDK if you do not accept the License -Agreement. - -2.2 By clicking to accept and/or accessing or using the SDK, you hereby agree to -the terms of the License Agreement. - -2.3 You may not access or use the SDK and may not accept the License Agreement -if you are a person barred from receiving the SDK under the laws of the United -States or other countries, including the country in which you are resident or -from which you access or use the SDK. - -2.4 If you are agreeing to be bound by the License Agreement on behalf of your -employer or any other entity, you represent and warrant that you have full legal -authority to bind your employer or such other entity to the License Agreement. -If you do not have the requisite authority, you may not accept the License -Agreement or you may not access or use the SDK on behalf of your employer or -other entity. - -3. SDK License from Bitwarden - -3.1 Subject to the terms of this License Agreement, Bitwarden grants you a -limited, worldwide, royalty-free, non-assignable, non-exclusive, and -non-sublicensable license to use the SDK solely (a) to develop, test, and -demonstrate a Compatible Application; (b) to develop, test, and run a Compatible -Application for personal use by your family; or (c) to to develop, test, and run -a Compatible Application for the internal business operations of your -organization in connection with a paid license for a Bitwarden server product, -provided that in no case above may the Compatible Application be offered, -licensed, or sold to a third party. - -3.2 You agree that Bitwarden or third parties own all legal right, title and -interest in and to the SDK, including any Intellectual Property Rights that -subsist in the SDK. "Intellectual Property Rights" means any and all rights -under patent law, copyright law, trade secret law, trademark law, and any and -all other proprietary rights. Bitwarden reserves all rights not expressly -granted to you. - -3.3 You may not use this SDK to develop applications for use with software other -than Bitwarden (including non-compatible implementations of Bitwarden) or to -develop another SDK. - -3.4 You may not use the SDK for any purpose not expressly permitted by the -License Agreement. Except for contributions to Bitwarden pursuant to the -Contribution License Agreement available at this URL: -https://cla-assistant.io/bitwarden/clients, or to the extent required by -applicable third party licenses, you may not copy modify, adapt, redistribute, -decompile, reverse engineer, disassemble, or create derivative works of the SDK -or any part of the SDK. - -3.5 Use, reproduction, and distribution of a component of the SDK licensed under -an open source software license are governed solely by the terms of that open -source software license and not the License Agreement. - -3.6 You agree that the form and nature of the SDK that the Company provides may -change without prior notice to you and that future versions of the SDK may be -incompatible with applications developed on previous versions of the SDK. You -agree that the Company may stop (permanently or temporarily) providing the SDK -or any features within the SDK to you or to users generally at the Company’s -sole discretion, without prior notice to you. - -3.7 Nothing in the License Agreement gives you a right to use any of the -Company’s trade names, trademarks, service marks, logos, domain names, or other -distinctive brand features. - -3.8 You agree that you will not remove, obscure, or alter any proprietary rights -notices (including copyright and trademark notices) that may be affixed to or -contained within the SDK. - -4. Use of the SDK by You - -4.1 The Company agrees that it obtains no right, title, or interest from you (or -your licensors) under the License Agreement in or to any software applications -that you develop using the SDK, including any Intellectual Property Rights that -subsist in those applications. - -4.2 You agree to use the SDK and write applications only for purposes that are -permitted by (a) the License Agreement and (b) any applicable law, regulation or -generally accepted practices or guidelines in the relevant jurisdictions -(including any laws regarding the export of data or software to and from the -United States or other relevant countries). - -4.3 You agree that if you use the SDK to develop applications for other users, -you will protect the privacy and legal rights of those users. If the users -provide you with user names, passwords, or other login information or personal -information, you must make the users aware that the information will be -available to your application, and you must provide legally adequate privacy -notice and protection for those users. If your application stores personal or -sensitive information provided by users, it must do so securely. If the user -provides your application with Bitwarden Account information, your application -may only use that information to access the user's Bitwarden Account when, and -for the limited purposes for which, the user has given you permission to do so. - -4.4 You agree that you will not engage in any activity with the SDK, including -the development or distribution of an application, that interferes with, -disrupts, damages, or accesses in an unauthorized manner the servers, networks, -or other properties or services of any third party including, but not limited -to, the Company, or any mobile communications carrier or public cloud service. - -4.5 If you use the SDK to retrieve a user's data from Bitwarden, you acknowledge -and agree that you shall retrieve data only with the user's explicit consent and -only when, and for the limited purposes for which, the user has given you -permission to do so. - -4.6 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any data, content, or resources -that you create, transmit or display through Bitwarden and/or applications for -Bitwarden, and for the consequences of your actions (including any loss or -damage which Bitwarden may suffer) by doing so. - -4.7 You agree that you are solely responsible for, and that the Company has no -responsibility to you or to any third party for, any breach of your obligations -under the License Agreement, any applicable third party contract or Terms of -Service, or any applicable law or regulation, and for the consequences -(including any loss or damage which the Company or any third party may suffer) -of any such breach. - -5. Third Party Applications - -5.1 If you use the SDK to integrate or run applications developed by a third -party or that access data, content or resources provided by a third party, you -agree that the Company is not responsible for those applications, data, content, -or resources. You understand that all data, content or resources which you may -access through such third party applications are the sole responsibility of the -person from which they originated and that the Company is not liable for any -loss or damage that you may experience as a result of the use or access of any -of those third party applications, data, content, or resources. - -5.2 You should be aware that the data, content, and resources presented to you -through such a third party application may be protected by intellectual property -rights which are owned by the providers (or by other persons or companies on -their behalf). You acknowledge that your use of such third party applications, -data, content, or resources may be subject to separate terms between you and the -relevant third party. In that case, the License Agreement does not affect your -legal relationship with these third parties. - -6. Use of Bitwarden Server - -You acknowledge and agree that the Bitwarden server products to which any -Compatible Application must connect is protected by intellectual property rights -which are owned by the Company and your use of the Bitwarden server products is -subject to additional terms not set forth in this License Agreement. - -7. Terminating this License Agreement - -7.1 The License Agreement will continue to apply until terminated by either you -or the Company as set out below. - -7.2 If you want to terminate the License Agreement, you may do so by ceasing -your use of the SDK and any relevant developer credentials. - -7.3 The Company may at any time, terminate the License Agreement with you if: - -(a) you have breached any provision of the License Agreement; or - -(b) the Company is required to do so by law; or - -(c) a third party with whom the Company offered certain parts of the SDK to you -has terminated its relationship with the Company or ceased to offer certain -parts of the SDK to either the Company or to you; or - -(d) the Company decides to no longer provide the SDK or certain parts of the SDK -to users in the country in which you are resident or from which you use the -service, or the provision of the SDK or certain SDK services to you by the -Company is, in the Company’'s sole discretion, no longer commercially viable or -technically practicable. - -7.4 When the License Agreement comes to an end, all of the legal rights, -obligations and liabilities that you and the Company have benefited from, been -subject to (or which have accrued over time whilst the License Agreement has -been in force) or which are expressed to continue indefinitely, shall be -unaffected by this cessation, and the provisions of paragraph 12.8 shall -continue to apply to such rights, obligations and liabilities indefinitely. - -8. NO SUPPORT - -The Company is not obligated under this License Agreement to provide you any -support services for the SDK. Any support provided is at the Company’s sole -discretion and provided on an "as is" basis and without warranty of any kind. - -9. DISCLAIMER OF WARRANTIES - -9.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE -RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF -ANY KIND FROM Bitwarden. - -9.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED -THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY -RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF -DATA THAT RESULTS FROM SUCH USE. - -9.3 THE COMPANY FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY -KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED -WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE -AND NON-INFRINGEMENT. - -10. LIMITATION OF LIABILITY - -YOU EXPRESSLY UNDERSTAND AND AGREE THAT THE COMPANY, ITS SUBSIDIARIES AND -AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF -LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, -STATUTORY, OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS -OF DATA, WHETHER OR NOT THE COMPANY OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF -OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING. - -11. Indemnification - -To the maximum extent permitted by law, you agree to defend, indemnify and hold -harmless the Company, its affiliates and their respective directors, officers, -employees and agents from and against any and all claims, actions, suits or -proceedings, as well as any and all losses, liabilities, damages, costs and -expenses (including reasonable attorneys fees) arising out of or accruing from -(a) your use of the SDK, (b) any application you develop on the SDK that -infringes any copyright, trademark, trade secret, trade dress, patent or other -intellectual property right of any person or defames any person or violates -their rights of publicity or privacy, and (c) any non-compliance by you with the -License Agreement. - -12. General Legal Terms - -12.1 The Company may make changes to the License Agreement as it distributes new -versions of the SDK. When these changes are made, the Company will make a new -version of the License Agreement available on the website where the SDK is made -available. - -12.2 The License Agreement constitutes the whole legal agreement between you and -the Company and governs your use of the SDK (excluding any services or software -which the Company may provide to you under a separate written agreement), and -completely replaces any prior agreements between you and the Company in relation -to the SDK. - -12.3 You agree that if the Company does not exercise or enforce any legal right -or remedy which is contained in the License Agreement (or which the Company has -the benefit of under any applicable law), this will not be taken to be a formal -waiver of the Company's rights and that those rights or remedies will still be -available to the Company. - -12.4 If any court of law, having the jurisdiction to decide on this matter, -rules that any provision of the License Agreement is invalid, then that -provision will be removed from the License Agreement without affecting the rest -of the License Agreement. The remaining provisions of the License Agreement will -continue to be valid and enforceable. - -12.5 You acknowledge and agree that each member of the group of companies of -which the Company is the parent shall be third party beneficiaries to the -License Agreement and that such other companies shall be entitled to directly -enforce, and rely upon, any provision of the License Agreement that confers a -benefit on them or rights in favor of them. Other than this, no other person or -company shall be third party beneficiaries to the License Agreement. - -12.6 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND -REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND -REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON -DESTINATIONS, END USERS, AND END USE. - -12.7 The rights granted in the License Agreement may not be assigned or -transferred by either you or the Company without the prior written approval of -the other party, provided that the Company may assign this License Agreement -upon notice to you in connection with an acquisition, merger, sale of assets, or -similar corporate change in control for the Company or the Intellectual Property -Rights in the SDK. - -12.8 The License Agreement, and any dispute relating to or arising out of this -License Agreement, shall be governed by the laws of the State of California -without regard to its conflict of laws provisions. You and the Company agree to -submit to the exclusive jurisdiction of the courts located within the county of -Los Angeles, California to resolve any dispute or legal matter arising from the -License Agreement. Notwithstanding this, you agree that the Company shall be -allowed to apply for injunctive remedies, or any equivalent type of urgent legal -relief, in any forum or jurisdiction. diff --git a/crates/memory-testing/Cargo.toml b/crates/memory-testing/Cargo.toml index c1ecbbf54..120fcaad1 100644 --- a/crates/memory-testing/Cargo.toml +++ b/crates/memory-testing/Cargo.toml @@ -1,11 +1,18 @@ [package] name = "memory-testing" version = "0.1.0" -edition = "2021" publish = false +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true + [dependencies] -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-crypto = { workspace = true } comfy-table = "7.1.0" hex = "0.4.3" serde = "1.0.196" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index dda54e86a..6b5ba3c6c 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -1,8 +1,15 @@ [package] name = "sdk-schemas" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [features] internal = [ diff --git a/crates/uniffi-bindgen/Cargo.toml b/crates/uniffi-bindgen/Cargo.toml index 9809eeb72..5ef3977bc 100644 --- a/crates/uniffi-bindgen/Cargo.toml +++ b/crates/uniffi-bindgen/Cargo.toml @@ -1,8 +1,15 @@ [package] name = "uniffi-bindgen" version = "0.1.0" -edition = "2021" -rust-version = "1.71" +publish = false + +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +homepage.workspace = true +repository.workspace = true +license-file.workspace = true +keywords.workspace = true [[bin]] # This can be whatever name makes sense for your project, but the rest of this tutorial assumes uniffi-bindgen. From e3ad0e48959c9e8a0b0a59d79a25c771924daa8c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:05:53 -0400 Subject: [PATCH 333/378] [deps]: Update bitwarden/gh-actions digest to 116cb2f (#664) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release-go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index c7a198056..5625570c9 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -74,7 +74,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + uses: bitwarden/gh-actions/get-keyvault-secrets@116cb2f33ef6e9250c4525b2205ef3a2e761e796 with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -151,7 +151,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + uses: bitwarden/gh-actions/get-keyvault-secrets@116cb2f33ef6e9250c4525b2205ef3a2e761e796 with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" From e51db84b828530f9414a9110f60f67e7e324ec73 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Mon, 18 Mar 2024 14:34:56 +0000 Subject: [PATCH 334/378] Update bitwarden actions to main (#669) --- .github/workflows/release-go.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 5625570c9..a434dce4e 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -74,7 +74,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@116cb2f33ef6e9250c4525b2205ef3a2e761e796 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -151,7 +151,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@116cb2f33ef6e9250c4525b2205ef3a2e761e796 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" From 8522822583a85cf5c8cc4183bc8a209725cf18c6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 16:43:53 +0100 Subject: [PATCH 335/378] [deps]: Update Rust crate chrono to 0.4.35 (#667) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [chrono](https://togithub.com/chronotope/chrono) | dependencies | patch | `0.4.34` -> `0.4.35` | --- ### Release Notes
chronotope/chrono (chrono) ### [`v0.4.35`](https://togithub.com/chronotope/chrono/releases/tag/v0.4.35) [Compare Source](https://togithub.com/chronotope/chrono/compare/v0.4.34...v0.4.35) Most of our efforts have shifted to improving the API for a 0.5 release, for which cleanups and refactorings are landing on the 0.4.x branch. The most significant changes in this release are two sets of deprecations. - We deprecated all timestamp-related methods on `NaiveDateTime`. The reason is that a timestamp is defined to be in UTC. The `NaiveDateTime` type doesn't know the offset from UTC, so it was technically wrong to have these methods. The alternative is to use the similar methods on the `DateTime` type, or from the `TimeZone` trait. Converting from `NaiveDateTime` to `DateTime` is simple with `.and_utc()`, and in the other direction with `.naive_utc()`. - The panicking constructors of `TimeDelta` (the new name of the `Duration` type) are deprecated. This was the last part of chrono that defaulted to panicking on error, dating from before rust 1.0. - A nice change is that `NaiveDate` now includes a niche. So now `Option`, `Option` and `Option>` are the same size as their base types. - `format::Numeric` and `format::Fixed` are marked as `non_exhaustive`. This will allow us to improve our formatting and parsing support, and we have reason to believe this breaking change will have little to no impact on users. ### Additions - Add `DateTime::{from_timestamp_micros, from_timestamp_nanos}` ([#​1234](https://togithub.com/chronotope/chrono/issues/1234)) - Add getters to `Parsed` ([#​1465](https://togithub.com/chronotope/chrono/issues/1465)) ### Deprecations - Deprecate timestamp methods on `NaiveDateTime` ([#​1473](https://togithub.com/chronotope/chrono/issues/1473)) - Deprecate panicking constructors of `TimeDelta` ([#​1450](https://togithub.com/chronotope/chrono/issues/1450)) ### Changes/fixes - Use `NonZeroI32` inside `NaiveDate` ([#​1207](https://togithub.com/chronotope/chrono/issues/1207)) - Mark `format::Numeric` and `format::Fixed` as `non_exhaustive` ([#​1430](https://togithub.com/chronotope/chrono/issues/1430)) - `Parsed` fixes to error values ([#​1439](https://togithub.com/chronotope/chrono/issues/1439)) - Use `overflowing_naive_local` in `DateTime::checked_add*` ([#​1333](https://togithub.com/chronotope/chrono/issues/1333)) - Do complete range checks in `Parsed::set_*` ([#​1465](https://togithub.com/chronotope/chrono/issues/1465)) ### Documentation - Rustfmt doctests ([#​1452](https://togithub.com/chronotope/chrono/issues/1452)) - Improve docs for crate features ([#​1455](https://togithub.com/chronotope/chrono/issues/1455), thanks [@​edmorley](https://togithub.com/edmorley)) - Add more documentation and examples to `Parsed` ([#​1439](https://togithub.com/chronotope/chrono/issues/1439)) ### Internal - Refactor `internals` module ([#​1428](https://togithub.com/chronotope/chrono/issues/1428), [#​1429](https://togithub.com/chronotope/chrono/issues/1429), [#​1431](https://togithub.com/chronotope/chrono/issues/1431), [#​1432](https://togithub.com/chronotope/chrono/issues/1432), [#​1433](https://togithub.com/chronotope/chrono/issues/1433), [#​1438](https://togithub.com/chronotope/chrono/issues/1438)) - CI: test cross-compiling to `x86_64-unknown-illumos` instead of Solaris ([#​1437](https://togithub.com/chronotope/chrono/issues/1437)) - CI: lint Windows target, fix clippy warning ([#​1441](https://togithub.com/chronotope/chrono/issues/1441)) - CI: only run `cargo hack check` on Linux ([#​1442](https://togithub.com/chronotope/chrono/issues/1442)) - Update windows-bindgen to 0.54 ([#​1462](https://togithub.com/chronotope/chrono/issues/1462), [#​1483](https://togithub.com/chronotope/chrono/issues/1483)) - Simplify error value of `parse_internal` ([#​1459](https://togithub.com/chronotope/chrono/issues/1459)) - Simplify `SerdeError` ([#​1458](https://togithub.com/chronotope/chrono/issues/1458)) - Simplify `NaiveDate::from_isoywd` a bit ([#​1464](https://togithub.com/chronotope/chrono/issues/1464)) Thanks to all contributors on behalf of the chrono team, [@​djc](https://togithub.com/djc) and [@​pitdicker](https://togithub.com/pitdicker)!
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/bws/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9f383413..a27fe8821 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,9 +704,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index f85744656..ccf143c47 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -18,7 +18,7 @@ license-file.workspace = true bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } -chrono = { version = "0.4.34", features = [ +chrono = { version = "0.4.35", features = [ "clock", "std", ], default-features = false } From 240c4345aeb6caafc93dcb998487c718a31d6ea0 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Mon, 18 Mar 2024 12:46:42 -0400 Subject: [PATCH 336/378] Scanning (#630) ## Objective Introduces a new GitHub Actions workflow named `Scan` in the `.github/workflows/scan.yml` file. The workflow is triggered on manual dispatch, push to the `main`, `rc`, and `hotfix-rc` branches, and when a pull request is opened or synchronized. The workflow includes two jobs: `sast` and `quality`. The `sast` job runs a Static Application Security Testing (SAST) scan using Checkmarx and uploads the results to GitHub. The `quality` job runs a quality scan using SonarCloud. * [`.github/workflows/scan.yml`](diffhunk://#diff-246cd0c2f7db532638dd80a92ac011f49b3d26038983a4c0169ea8f8a5c39280R1-R71): Added a new GitHub Actions workflow named `Scan`. This workflow is triggered on manual dispatch, push to the `main`, `rc`, and `hotfix-rc` branches, and when a pull request is opened or synchronized. The workflow includes two jobs: `sast` and `quality`. The `sast` job runs a Static Application Security Testing (SAST) scan using Checkmarx and uploads the results to GitHub. The `quality` job runs a quality scan using SonarCloud. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/scan.yml | 71 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/scan.yml diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml new file mode 100644 index 000000000..45763089c --- /dev/null +++ b/.github/workflows/scan.yml @@ -0,0 +1,71 @@ +name: Scan + +on: + workflow_dispatch: + push: + branches: + - "main" + - "rc" + - "hotfix-rc" + pull_request_target: + types: [opened, synchronize] + +permissions: read-all + +jobs: + check-run: + name: Check PR run + uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main + + sast: + name: SAST scan + runs-on: ubuntu-22.04 + needs: check-run + permissions: + security-events: write + + steps: + - name: Check out repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: Scan with Checkmarx + uses: checkmarx/ast-github-action@749fec53e0db0f6404a97e2e0807c3e80e3583a7 #2.0.23 + env: + INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" + with: + project_name: ${{ github.repository }} + cx_tenant: ${{ secrets.CHECKMARX_TENANT }} + base_uri: https://ast.checkmarx.net/ + cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }} + cx_client_secret: ${{ secrets.CHECKMARX_SECRET }} + additional_params: --report-format sarif --output-path . ${{ env.INCREMENTAL }} + + - name: Upload Checkmarx results to GitHub + uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 + with: + sarif_file: cx_result.sarif + + quality: + name: Quality scan + runs-on: ubuntu-22.04 + needs: check-run + + steps: + - name: Check out repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: Scan with SonarCloud + uses: sonarsource/sonarcloud-github-action@49e6cd3b187936a73b8280d59ffd9da69df63ec9 # v2.1.1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + args: > + -Dsonar.organization=${{ github.repository_owner }} + -Dsonar.projectKey=${{ github.repository_owner }}_${{ github.event.repository.name }} + -Dsonar.exclusions=languages/** From b6d36ead37bbcfc8daaa8a35d7292cdccfd9db58 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:04:37 -0700 Subject: [PATCH 337/378] Update CHANGELOG.md (#658) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [x] Other ## Objective Update changelog to mention the `bws` Docker image --------- Co-authored-by: Oscar Hinton --- crates/bws/CHANGELOG.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/bws/CHANGELOG.md b/crates/bws/CHANGELOG.md index 2bb431485..642266c70 100644 --- a/crates/bws/CHANGELOG.md +++ b/crates/bws/CHANGELOG.md @@ -7,10 +7,20 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -### Changed +### Added -- Switched TLS backend to `rustls`, removing the dependency on `OpenSSL`. - Add a `BWS_CONFIG_FILE` environment variable to specify the location of the config file (#571) +- The `bws` CLI is now available as a Docker image (`docker run -it bitwarden/bws --help`) (#305) +- The `bws` CLI releases are now code signed on Windows and Mac (#534, #535) + +### Fixed + +- Re-add output options to the help menu after they were accidentally removed (#477) + +### Changed + +- Switched TLS backend to `rusttls`, removing the dependency on `OpenSSL` (#374) +- Updated MSRV for `bws` to `1.71.0` (#589) ## [0.4.0] - 2023-12-21 From a5185511a77ae5c644b84fdfbbf379799a941baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 19 Mar 2024 16:07:23 +0100 Subject: [PATCH 338/378] [DEVOPS-1786] Update release pipeline for PHP SDK (#659) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Update release pipeline for PHP SDK. ## Code changes - **file.ext:** Description of what was changed and why ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-php.yml | 267 +++++++++++++++++++++++++---- .github/workflows/version-bump.yml | 7 + languages/php/composer.json | 3 +- 3 files changed, 239 insertions(+), 38 deletions(-) diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index 00b34c23f..aefeae60a 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -1,20 +1,50 @@ name: Publish PHP SDK +run-name: Publish PHP SDK ${{ inputs.release_type }} on: - push: - branches: - - main + workflow_dispatch: + inputs: + release_type: + description: "Release Options" + required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + +env: + _KEY_VAULT: "bitwarden-ci" jobs: - build_rust: - uses: ./.github/workflows/build-rust-cross-platform.yml + validate: + name: Setup + runs-on: ubuntu-22.04 + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - setup_php: + - 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: Get version + id: version + run: | + VERSION=$(cat languages/php/composer.json | grep -Eo '"version": "[0-9]+\.[0-9]+\.[0-9]+"' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') + echo "version=$VERSION" >> $GITHUB_OUTPUT + + setup-php: name: Setup PHP runs-on: ubuntu-22.04 - needs: - - build_rust - steps: - name: Checkout Repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -32,44 +62,207 @@ jobs: composer validate working-directory: languages/php/ - - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + repo-sync: + name: Push changed files to SDK PHP repo + runs-on: ubuntu-22.04 + needs: + - validate + - setup-php + env: + _BOT_EMAIL: 106330231+bitwarden-devops-bot@users.noreply.github.com + _BOT_NAME: bitwarden-devops-bot + _PKG_VERSION: ${{ needs.validate.outputs.version }} + steps: + - name: Checkout SDK repo + uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4.0.0 with: - name: libbitwarden_c_files-x86_64-apple-darwin - path: temp/macos-x64 + path: sdk - - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 with: - name: libbitwarden_c_files-aarch64-apple-darwin - path: temp/macos-arm64 + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} - - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c with: - name: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: temp/linux-x64 + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" - - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + - name: Checkout SDK-PHP repo + uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4.0.0 with: - name: libbitwarden_c_files-x86_64-pc-windows-msvc - path: temp/windows-x64 + repository: bitwarden/sm-sdk-php + path: sm-sdk-php + ref: main + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} - - name: Copy lib files + - name: Setup Git + working-directory: sm-sdk-php run: | - mkdir -p languages/php/src/lib/macos-arm64 - mkdir -p languages/php/src/lib/linux-x64 - mkdir -p languages/php/src/lib/macos-x64 - mkdir -p languages/php/src/lib/windows-x64 + git config --local user.email "${{ env._BOT_EMAIL }}" + git config --local user.name "${{ env._BOT_NAME }}" - platforms=("macos-arm64" "linux-x64" "macos-x64" "windows-x64") - files=("libbitwarden_c.dylib" "libbitwarden_c.so" "libbitwarden_c.dylib" "bitwarden_c.dll") + - name: Update files + run: | + # Copy files to local sm-sdk-php repo path + cp --verbose -rf sdk/languages/php/. sm-sdk-php + + - name: Replace repo name + working-directory: sm-sdk-php + run: | + find . -name '*' -exec \ + sed -i -e 's/github.com\/bitwarden\/sdk\/languages\/php/github.com\/bitwarden\/sm-sdk-php/g' {} \; - for ((i=0; i<${#platforms[@]}; i++)); do - cp "temp/${platforms[$i]}/${files[$i]}" "languages/php/src/lib/${platforms[$i]}/${files[$i]}" - done + find . -name '*' -exec \ + sed -i -e 's/github.com\/bitwarden\/sdk/github.com\/bitwarden\/sm-sdk-php/g' {} \; + + - name: Push changes + working-directory: sm-sdk-php + run: | + git add . + git commit -m "Update Go SDK to ${{ github.sha }}" + + if [[ "${{ inputs.release_type }}" == "Dry Run" ]]; then + echo "===================================" + echo "[!] Dry Run - Skipping push" + echo "===================================" + git ls-files -m + exit 0 + else + git push origin main + fi + + - name: Create release tag on SDK Go repo + if: ${{ inputs.release_type != 'Dry Run' }} + working-directory: sm-sdk-php + run: | + # Check if tag exists, set output then exit 0 if true. + if git log v${{ env._PKG_VERSION }} >/dev/null 2>&1; then + echo "===================================" + echo "[!] Tag v${{ env._PKG_VERSION }} already exists" + echo "===================================" + exit 1 + fi + + git tag v${{ env._PKG_VERSION }} + git push origin v${{ env._PKG_VERSION }} + + github-release: + name: GitHub Release + runs-on: ubuntu-22.04 + needs: + - setup-php + - repo-sync + - validate + env: + _PKG_VERSION: ${{ needs.validate.outputs.version }} + steps: + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Download x86_64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-apple-darwin + skip_unpack: true + + - name: Download aarch64-apple-darwin artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-aarch64-apple-darwin + skip_unpack: true + + - name: Download x86_64-unknown-linux-gnu artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-unknown-linux-gnu + skip_unpack: true + + - name: Download x86_64-pc-windows-msvc artifact + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-pc-windows-msvc + skip_unpack: true + + - name: Rename build artifacts + run: | + mv libbitwarden_c_files-x86_64-apple-darwin.zip libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION.zip + mv libbitwarden_c_files-aarch64-apple-darwin.zip libbitwarden_c_files-aarch64-apple-darwin-$_PKG_VERSION.zip + mv libbitwarden_c_files-x86_64-unknown-linux-gnu.zip libbitwarden_c_files-x86_64-unknown-linux-gnu-$_PKG_VERSION.zip + mv libbitwarden_c_files-x86_64-pc-windows-msvc.zip libbitwarden_c_files-x86_64-pc-windows-msvc-$_PKG_VERSION.zip + + - name: Create release + if: ${{ inputs.release_type != 'Dry Run' }} + uses: ncipollo/release-action@6c75be85e571768fa31b40abf38de58ba0397db5 # v1.13.0 + with: + tag: v${{ env._PKG_VERSION }} + name: v${{ env._PKG_VERSION }} + body: "" + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + draft: true + repo: sm-sdk-php + owner: bitwarden + artifacts: "libbitwarden_c_files-x86_64-apple-darwin-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-aarch64-apple-darwin-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-x86_64-unknown-linux-gnu-${{ env._PKG_VERSION }}.zip, + libbitwarden_c_files-x86_64-pc-windows-msvc-${{ env._PKG_VERSION }}.zip" + + packagist-publish: + name: Publish to Packagist + runs-on: ubuntu-22.04 + needs: + - validate + - setup-php + - repo-sync + - github-release + steps: + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "github-pat-bitwarden-devops-bot-repo-scope, + packagist-key" + + - name: Checkout SDK-PHP repo + uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4.0.0 + with: + repository: bitwarden/sm-sdk-php + path: sm-sdk-php + ref: main + token: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} - name: Publish version - run: curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username=malirobot&apiToken=${{secrets.PACKAGIST_KEY}}' -d'{"repository":{"url":"https://packagist.org/packages/bitwarden/sdk"}}' - working-directory: languages/php/ + if: ${{ inputs.release_type != 'Dry Run' }} + env: + PACKAGIST_KEY: ${{ steps.retrieve-secrets.outputs.packagist-key }} + run: curl -XPOST -H'content-type:application/json' 'https://packagist.org/api/update-package?username=bitwarden&apiToken=${{ env.PACKAGIST_KEY }}' -d'{"repository":{"url":"https://packagist.org/packages/bitwarden/sdk-secrets"}}' + working-directory: sm-sdk-php diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 8298781fc..b4f41b5ef 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -21,6 +21,7 @@ on: - python-sdk - ruby-sdk - go-sdk + - php-sdk version_number: description: "New version (example: '2024.1.0')" required: true @@ -162,6 +163,12 @@ jobs: if: ${{ inputs.project == 'go-sdk' }} run: sed -i 's/[0-9]\.[0-9]\.[0-9]/${{ inputs.version_number }}/' ./languages/go/.version + ### php sdk + - name: Bump php-sdk Version + if: ${{ inputs.project == 'php-sdk' }} + run: | + sed -i 's/"version": "[0-9]\.[0-9]\.[0-9]"/"version": "${{ inputs.version_number }}"/' ./languages/php/composer.json + ############################ # VERSION BUMP SECTION END # ############################ diff --git a/languages/php/composer.json b/languages/php/composer.json index 18b333eac..85447e72a 100644 --- a/languages/php/composer.json +++ b/languages/php/composer.json @@ -1,9 +1,10 @@ { - "name": "bitwarden/sdk", + "name": "bitwarden/sdk-secrets", "description": "PHP bindings for interacting with the Bitwarden Secrets Manager. This is a beta release and might be missing some functionality.", "type": "library", "keywords": ["bitwarden","sdk","password-manager"], "homepage": "https://github.com/bitwarden/sdk", + "version": "0.1.0", "require": { "php": "^8.0", "swaggest/json-schema": "^0.12.42", From 812be7930e6f8e3b2ecac9a965b1420d4dc78243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 19 Mar 2024 16:32:41 +0100 Subject: [PATCH 339/378] [DEVOPS-1749] update release pipeline for C# (#668) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/publish-dotnet.yml:** Inline publish dotnet workflow with Bitwarden publish workflows standards. - **.github/workflows/version-bump.yml** Add `dotnet-sdk` to version bump workflow. - **languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj** Add version and change name of the nuget. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-dotnet.yml | 104 ++++++++++++++---- .github/workflows/version-bump.yml | 6 + .../csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj | 5 +- 3 files changed, 90 insertions(+), 25 deletions(-) diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 2f9304903..66d9dc712 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -1,34 +1,65 @@ -name: Deploy NuGet Package +name: Publish .NET NuGet +run-name: Publish .NET NuGet Package ${{ inputs.release_type }} on: workflow_dispatch: inputs: - version_number: - description: "New Version" + release_type: + description: "Release Options" required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + +env: + _KEY_VAULT: "bitwarden-ci" jobs: - generate_schemas: - uses: ./.github/workflows/generate_schemas.yml + validate: + name: Setup + runs-on: ubuntu-22.04 + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - 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: Install xmllint + run: sudo apt-get install -y libxml2-utils - build_rust: - uses: ./.github/workflows/build-rust-cross-platform.yml + - name: Get version + id: version + run: | + VERSION=$(xmllint --xpath 'string(/Project/PropertyGroup/Version)' languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj) + echo "version=$VERSION" >> $GITHUB_OUTPUT deploy: name: Deploy runs-on: ubuntu-22.04 - needs: - - generate_schemas - - build_rust - + needs: validate steps: - name: Checkout Repository uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Download C# schemas artifact - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: bitwarden/gh-actions/download-artifacts@main with: - name: schemas.cs + workflow: generate_schemas.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: schemas.cs path: languages/csharp/Bitwarden.Sdk - name: Set up .NET Core @@ -37,34 +68,61 @@ jobs: global-json-file: languages/csharp/global.json - name: Download x86_64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: bitwarden/gh-actions/download-artifacts@main with: - name: libbitwarden_c_files-x86_64-apple-darwin + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-x64 - name: Download aarch64-apple-darwin files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: bitwarden/gh-actions/download-artifacts@main with: - name: libbitwarden_c_files-aarch64-apple-darwin + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-aarch64-apple-darwin path: languages/csharp/Bitwarden.Sdk/macos-arm64 - name: Download x86_64-unknown-linux-gnu files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: bitwarden/gh-actions/download-artifacts@main with: - name: libbitwarden_c_files-x86_64-unknown-linux-gnu + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-unknown-linux-gnu path: languages/csharp/Bitwarden.Sdk/linux-x64 - name: Download x86_64-pc-windows-msvc files - uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2 + uses: bitwarden/gh-actions/download-artifacts@main with: - name: libbitwarden_c_files-x86_64-pc-windows-msvc + workflow: build-rust-cross-platform.yml + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 - name: Pack NuGet Package env: - VERSION: ${{ github.event.inputs.version_number }} + VERSION: ${{ needs.validate.outputs.version }} run: dotnet pack --configuration Release -p:PackageID=Bitwarden.Sdk -p:Version=${VERSION} --output ./nuget-output /nologo /v:n working-directory: languages/csharp/Bitwarden.Sdk + - name: Login to Azure - Prod Subscription + uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 + with: + creds: ${{ secrets.AZURE_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: bitwarden/gh-actions/get-keyvault-secrets@main + with: + keyvault: ${{ env._KEY_VAULT }} + secrets: "nuget-api-key" + - name: Publish NuGet Package - run: dotnet nuget push ./languages/csharp/Bitwarden.Sdk/nuget-output/*.nupkg -k ${{ secrets.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json + if: ${{ inputs.release_type != 'Dry Run' }} + env: + NUGET_API_KEY: ${{ steps.retrieve-secrets.outputs.nuget-api-key }} + run: dotnet nuget push ./languages/csharp/Bitwarden.Sdk/nuget-output/*.nupkg -k ${{ env.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index b4f41b5ef..704bee01d 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -21,6 +21,7 @@ on: - python-sdk - ruby-sdk - go-sdk + - dotnet-sdk - php-sdk version_number: description: "New version (example: '2024.1.0')" @@ -163,6 +164,11 @@ jobs: if: ${{ inputs.project == 'go-sdk' }} run: sed -i 's/[0-9]\.[0-9]\.[0-9]/${{ inputs.version_number }}/' ./languages/go/.version + ### dotnet sdk + - name: Bump dotnet-sdk Version + if: ${{ inputs.project == 'dotnet-sdk' }} + run: sed -i 's/[0-9]\.[0-9]\.[0-9]<\/Version>/${{ inputs.version_number }}<\/Version>/' languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj + ### php sdk - name: Bump php-sdk Version if: ${{ inputs.project == 'php-sdk' }} diff --git a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj index 3717aefdf..35770eedf 100644 --- a/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj +++ b/languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj @@ -16,11 +16,12 @@ Git https://bitwarden.com/products/secrets-manager/ - Bitwarden.Sdk + Bitwarden.Secrets.Sdk bitwarden.png - Bitwarden;Sdk;.NET + Bitwarden;Secrets Manager;Sdk;.NET README.md LICENSE.txt + 0.1.0 From 73028a72a9fcced8a0cc4914cbe210011c53d7f6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:09:52 +0100 Subject: [PATCH 340/378] [deps]: Update Rust crate anyhow to 1.0.81 (#666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [anyhow](https://togithub.com/dtolnay/anyhow) | dependencies | patch | `1.0.79` -> `1.0.81` | --- ### Release Notes
dtolnay/anyhow (anyhow) ### [`v1.0.81`](https://togithub.com/dtolnay/anyhow/releases/tag/1.0.81) [Compare Source](https://togithub.com/dtolnay/anyhow/compare/1.0.80...1.0.81) - Make backtrace support available when using -Dwarnings ([#​354](https://togithub.com/dtolnay/anyhow/issues/354))
--- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/sdk-schemas/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a27fe8821..f520ace8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,9 +112,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arc-swap" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index 6b5ba3c6c..c4cc9139b 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -19,7 +19,7 @@ internal = [ ] [dependencies] -anyhow = "1.0.79" +anyhow = "1.0.81" itertools = "0.12.1" schemars = { version = "0.8.16", features = ["preserve_order"] } serde_json = "1.0.113" From 97d9e8cfbcc728313dee7e5730e8f2f919c421ee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 17:11:33 +0100 Subject: [PATCH 341/378] [deps]: Update @types/node to v18.19.26 (#665) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.18` -> `18.19.26`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.18/18.19.26) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.26?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.26?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.18/18.19.26?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.18/18.19.26?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index 176ed5eca..dc788c8ce 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.18.tgz", - "integrity": "sha512-80CP7B8y4PzZF0GWx15/gVWRrB5y/bIjNI84NK3cmQJu0WZwvmj2WMA5LcofQFVfLqqCSp545+U2LsrVzX36Zg==", + "version": "18.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", + "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 99796abd916f063da381cb189026beebb7551cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Wed, 20 Mar 2024 14:50:17 +0100 Subject: [PATCH 342/378] [DEVOPS-1786] Fix release pipeline for PHP SDK (#670) ## Type of change ``` - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/publish-php.yml:** Add `composer update` in PHP setup to fix publish error. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/publish-php.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index aefeae60a..782ffee1d 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -58,6 +58,7 @@ jobs: - name: Composer check run: | + composer update composer install composer validate working-directory: languages/php/ From c66892bd079eca98f15443c289f21c9731cd0f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 21 Mar 2024 13:08:19 +0100 Subject: [PATCH 343/378] Update request and rust-platform-verifier (#673) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Previously rust-platform-verifier was pinned to an old version to keep it's rustls version the same as reqwest. The latest update to reqwest now contains a new rustls version which unblocks this update. --- Cargo.lock | 656 +++++++++++------------ crates/bitwarden-api-api/Cargo.toml | 2 +- crates/bitwarden-api-identity/Cargo.toml | 2 +- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden/Cargo.toml | 4 +- 5 files changed, 328 insertions(+), 338 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f520ace8a..dfa714cc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -118,9 +118,9 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" [[package]] name = "argon2" @@ -158,7 +158,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -212,13 +212,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -256,9 +256,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2db21524cad41c5591204d22d75e1970a2d1f71060214ca931dc7d5afe2c14e5" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" dependencies = [ "serde", ] @@ -323,9 +323,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitwarden" @@ -561,9 +561,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "serde", @@ -571,9 +571,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bw" @@ -612,15 +612,15 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.10", + "toml 0.8.12", "uuid", ] [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" @@ -683,12 +683,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cesu8" @@ -714,7 +711,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -730,9 +727,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.1" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" dependencies = [ "clap_builder", "clap_derive", @@ -740,9 +737,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -761,14 +758,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -791,9 +788,9 @@ dependencies = [ [[package]] name = "color-eyre" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5" dependencies = [ "backtrace", "color-spantrace", @@ -992,7 +989,7 @@ version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "crossterm_winapi", "libc", "parking_lot", @@ -1041,12 +1038,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -1188,9 +1185,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" @@ -1225,9 +1222,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ "anstream", "anstyle", @@ -1389,7 +1386,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -1484,36 +1481,17 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.11", - "indexmap 2.2.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" +checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 1.0.0", - "indexmap 2.2.3", + "http", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -1538,11 +1516,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1579,37 +1563,15 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.11", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.0" @@ -1617,19 +1579,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.0.0", + "http", ] [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", - "http 1.0.0", - "http-body 1.0.0", + "futures-core", + "http", + "http-body", "pin-project-lite", ] @@ -1653,60 +1615,40 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.2", - "http 1.0.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec", "tokio", "want", ] [[package]] name = "hyper-rustls" -version = "0.24.2" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ "futures-util", - "http 0.2.11", - "hyper 0.14.28", + "http", + "hyper", + "hyper-util", "rustls", + "rustls-pki-types", "tokio", "tokio-rustls", + "tower-service", ] [[package]] @@ -1716,13 +1658,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", + "futures-channel", "futures-util", - "http 1.0.0", - "http-body 1.0.0", - "hyper 1.1.0", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1783,9 +1729,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.3" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1881,9 +1827,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1905,12 +1851,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.4", ] [[package]] @@ -1925,7 +1871,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] @@ -1957,9 +1903,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" @@ -2033,11 +1979,11 @@ dependencies = [ [[package]] name = "napi" -version = "2.15.2" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd92040344a83763379b122f4e714932ccaa700439e647f1e90481dd1999cb" +checksum = "54a63d0570e4c3e0daf7a8d380563610e159f538e20448d6c911337246f40e84" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "ctor", "napi-derive", "napi-sys", @@ -2053,23 +1999,23 @@ checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43" [[package]] name = "napi-derive" -version = "2.15.2" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef56a31cf81a1d183aa991c85128e6f27c312b72227e506b1854068c2ac7d53" +checksum = "05bb7c37e3c1dda9312fdbe4a9fc7507fca72288ba154ec093e2d49114e727ce" dependencies = [ "cfg-if", "convert_case", "napi-derive-backend", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] name = "napi-derive-backend" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b8f403a37007cad225039fc0323b961bb40d697eea744140920ebb689ff1d" +checksum = "f785a8b8d7b83e925f5aa6d2ae3c159d17fe137ac368dc185bef410e7acdaeb4" dependencies = [ "convert_case", "once_cell", @@ -2077,7 +2023,7 @@ dependencies = [ "quote", "regex", "semver", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -2331,6 +2277,26 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.53", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2383,13 +2349,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64", - "indexmap 2.2.3", + "indexmap 2.2.5", "line-wrap", "quick-xml", "serde", "time", ] +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + [[package]] name = "powerfmt" version = "0.2.0" @@ -2404,24 +2376,25 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0" +checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" dependencies = [ "cfg-if", "indoc", "libc", "memoffset", "parking_lot", + "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", @@ -2455,9 +2428,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be" +checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" dependencies = [ "once_cell", "target-lexicon", @@ -2465,9 +2438,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1" +checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" dependencies = [ "libc", "pyo3-build-config", @@ -2486,26 +2459,27 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3" +checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] name = "pyo3-macros-backend" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f" +checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", + "pyo3-build-config", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -2564,9 +2538,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -2616,9 +2590,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -2633,20 +2607,20 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.24" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "58b48d98d932f4ee75e541614d32a7f44c889b72bd9c2e04d95edd135989df88" dependencies = [ "base64", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2 0.3.24", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", + "http", + "http-body", + "http-body-util", + "hyper", "hyper-rustls", + "hyper-util", "ipnet", "js-sys", "log", @@ -2656,12 +2630,12 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-rustls", "tower-service", @@ -2725,11 +2699,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2738,24 +2712,27 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 2.1.1", + "rustls-pki-types", "schannel", "security-framework", ] @@ -2769,11 +2746,27 @@ dependencies = [ "base64", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" + [[package]] name = "rustls-platform-verifier" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92c57b5de012da34087f2fe711fa29770f9a7abdde660b01bac3c9dbdee91b84" +checksum = "2c35b9a497e588f1fb2e1d18a0d46a6d057710f34c3da7084b27353b319453cc" dependencies = [ "core-foundation", "core-foundation-sys", @@ -2798,11 +2791,12 @@ checksum = "84e217e7fdc8466b5b35d30f8c0a30febd29173df4a3a0c2115d306b9c4117ad" [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] @@ -2898,17 +2892,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", -] - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", + "syn 2.0.53", ] [[package]] @@ -2959,22 +2943,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -2990,9 +2974,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -3018,7 +3002,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -3044,11 +3028,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ - "indexmap 2.2.3", + "indexmap 2.2.5", "itoa", "ryu", "serde", @@ -3143,9 +3127,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smawk" @@ -3155,12 +3139,12 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3221,11 +3205,11 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -3256,9 +3240,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.49" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -3291,38 +3275,17 @@ dependencies = [ "walkdir", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "target-lexicon" -version = "0.12.13" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", @@ -3343,29 +3306,29 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -3442,16 +3405,17 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ "rustls", + "rustls-pki-types", "tokio", ] @@ -3480,9 +3444,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -3501,17 +3465,39 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.6" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.3", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3524,6 +3510,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-core", ] @@ -3600,9 +3587,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -3655,7 +3642,7 @@ dependencies = [ "fs-err", "glob", "goblin", - "heck", + "heck 0.4.1", "once_cell", "paste", "serde", @@ -3684,7 +3671,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72775b3afa6adb30e0c92b3107858d2fcb0ff1a417ac242db1f648b0e2dd0ef2" dependencies = [ "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] @@ -3717,7 +3704,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.49", + "syn 2.0.53", "toml 0.5.11", "uniffi_build", "uniffi_meta", @@ -3769,9 +3756,9 @@ checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "untrusted" @@ -3798,9 +3785,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "serde", @@ -3820,9 +3807,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -3845,9 +3832,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "serde", @@ -3857,24 +3844,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -3884,9 +3871,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3894,28 +3881,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-bindgen-test" -version = "0.3.41" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61" +checksum = "d9bf62a58e0780af3e852044583deee40983e5886da43a271dd772379987667b" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3927,20 +3914,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.41" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89" +checksum = "b7f89739351a2e03cb94beb799d47fb2cac01759b40ec441f7de39b00cbf7ef0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] name = "web-sys" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -3948,9 +3935,12 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "weedle2" @@ -3998,7 +3988,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -4016,7 +4006,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -4036,17 +4026,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -4057,9 +4047,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -4069,9 +4059,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -4081,9 +4071,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -4093,9 +4083,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -4105,9 +4095,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -4117,9 +4107,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -4129,15 +4119,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.6.1" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] @@ -4163,9 +4153,9 @@ dependencies = [ "base64", "deadpool", "futures", - "http 1.0.0", + "http", "http-body-util", - "hyper 1.1.0", + "hyper", "hyper-util", "log", "once_cell", @@ -4193,7 +4183,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.53", ] [[package]] diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index 427b4bd97..538d590ec 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -22,7 +22,7 @@ serde_repr = ">=0.1.12, <0.2" url = ">=2.3.1, <3" uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] -version = ">=0.11.18, <0.12" +version = ">=0.12, <0.13" features = ["json", "multipart"] default-features = false diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 7f09cfdb8..067d90648 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -22,7 +22,7 @@ serde_repr = ">=0.1.12, <0.2" url = ">=2.3.1, <3" uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] -version = ">=0.11.18, <0.12" +version = ">=0.12, <0.13" features = ["json", "multipart"] default-features = false diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index e43d4530f..1780c37c8 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -19,7 +19,7 @@ mobile = ["dep:uniffi"] # Mobile-specific features [dependencies] bitwarden-crypto = { workspace = true } rand = ">=0.8.5, <0.9" -reqwest = { version = ">=0.11, <0.12", features = [ +reqwest = { version = ">=0.12, <0.13", features = [ "json", ], default-features = false } schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 59e7dd8e5..4c9596b81 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -47,7 +47,7 @@ getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } hmac = ">=0.12.1, <0.13" log = ">=0.4.18, <0.5" rand = ">=0.8.5, <0.9" -reqwest = { version = ">=0.11, <0.12", features = [ +reqwest = { version = ">=0.12, <0.13", features = [ "json", ], default-features = false } schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } @@ -70,7 +70,7 @@ zxcvbn = ">= 2.2.2, <3.0" reqwest = { version = "*", features = [ "rustls-tls-manual-roots", ], default-features = false } -rustls-platform-verifier = "0.1.0" +rustls-platform-verifier = "0.2.0" [target.'cfg(target_os = "android")'.dependencies] # On android, the use of rustls-platform-verifier is more complicated and going through some changes at the moment, so we fall back to using webpki-roots From 67e743f595e73df9807b6f17f557e327ac0fbc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 21 Mar 2024 19:07:41 +0100 Subject: [PATCH 344/378] [PM-6760] Add support for URI checksums (#662) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Validate the URI checksums of ciphers. This is done in a similar way to the `enable_cipher_key_encryption` flag check --- crates/bitwarden/src/vault/cipher/cipher.rs | 32 +++++++- crates/bitwarden/src/vault/cipher/login.rs | 83 +++++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 47b58694d..f0138beb9 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -139,10 +139,15 @@ pub struct CipherListView { } impl KeyEncryptable for CipherView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(mut self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); + // For compatibility reasons, we only create checksums for ciphers that have a key + if ciphers_key.is_some() { + self.generate_checksums(); + } + Ok(Cipher { id: self.id, organization_id: self.organization_id, @@ -177,7 +182,7 @@ impl KeyDecryptable for Cipher { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); - Ok(CipherView { + let mut cipher = CipherView { id: self.id, organization_id: self.organization_id, folder_id: self.folder_id, @@ -202,7 +207,14 @@ impl KeyDecryptable for Cipher { creation_date: self.creation_date, deleted_date: self.deleted_date, revision_date: self.revision_date, - }) + }; + + // For compatibility we only remove URLs with invalid checksums if the cipher has a key + if ciphers_key.is_some() { + cipher.remove_invalid_checksums(); + } + + Ok(cipher) } } @@ -299,6 +311,20 @@ impl CipherView { self.key = Some(new_key.to_vec().encrypt_with_key(key)?); Ok(()) } + + pub fn generate_checksums(&mut self) { + if let Some(uris) = self.login.as_mut().and_then(|l| l.uris.as_mut()) { + for uri in uris { + uri.generate_checksum(); + } + } + } + + pub fn remove_invalid_checksums(&mut self) { + if let Some(uris) = self.login.as_mut().and_then(|l| l.uris.as_mut()) { + uris.retain(|u| u.is_checksum_valid()); + } + } } impl KeyDecryptable for Cipher { diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 5d00c41e1..26fd59001 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,3 +1,4 @@ +use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_api_api::models::{CipherLoginModel, CipherLoginUriModel}; use bitwarden_crypto::{ CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, @@ -28,6 +29,7 @@ pub enum UriMatchType { pub struct LoginUri { pub uri: Option, pub r#match: Option, + pub uri_checksum: Option, } #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -36,6 +38,35 @@ pub struct LoginUri { pub struct LoginUriView { pub uri: Option, pub r#match: Option, + pub uri_checksum: Option, +} + +impl LoginUriView { + pub(crate) fn is_checksum_valid(&self) -> bool { + let Some(uri) = &self.uri else { + return false; + }; + let Some(cs) = &self.uri_checksum else { + return false; + }; + let Ok(cs) = STANDARD.decode(cs) else { + return false; + }; + + use sha2::Digest; + let uri_hash = sha2::Sha256::new().chain_update(uri.as_bytes()).finalize(); + + uri_hash.as_slice() == cs + } + + pub(crate) fn generate_checksum(&mut self) { + if let Some(uri) = &self.uri { + use sha2::Digest; + let uri_hash = sha2::Sha256::new().chain_update(uri.as_bytes()).finalize(); + let uri_hash = STANDARD.encode(uri_hash.as_slice()); + self.uri_checksum = Some(uri_hash); + } + } } #[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] @@ -93,6 +124,7 @@ impl KeyEncryptable for LoginUriView { Ok(LoginUri { uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, + uri_checksum: self.uri_checksum.encrypt_with_key(key)?, }) } } @@ -116,6 +148,7 @@ impl KeyDecryptable for LoginUri { Ok(LoginUriView { uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, + uri_checksum: self.uri_checksum.decrypt_with_key(key)?, }) } } @@ -166,6 +199,7 @@ impl TryFrom for LoginUri { Ok(Self { uri: EncString::try_from_optional(uri.uri)?, r#match: uri.r#match.map(|m| m.into()), + uri_checksum: EncString::try_from_optional(uri.uri_checksum)?, }) } } @@ -208,3 +242,52 @@ impl TryFrom for Fido2Cre }) } } + +#[cfg(test)] +mod tests { + #[test] + fn test_valid_checksum() { + let uri = super::LoginUriView { + uri: Some("https://example.com".to_string()), + r#match: Some(super::UriMatchType::Domain), + uri_checksum: Some("EAaArVRs5qV39C9S3zO0z9ynVoWeZkuNfeMpsVDQnOk=".to_string()), + }; + assert!(uri.is_checksum_valid()); + } + + #[test] + fn test_invalid_checksum() { + let uri = super::LoginUriView { + uri: Some("https://example.com".to_string()), + r#match: Some(super::UriMatchType::Domain), + uri_checksum: Some("UtSgIv8LYfEdOu7yqjF7qXWhmouYGYC8RSr7/ryZg5Q=".to_string()), + }; + assert!(!uri.is_checksum_valid()); + } + + #[test] + fn test_missing_checksum() { + let uri = super::LoginUriView { + uri: Some("https://example.com".to_string()), + r#match: Some(super::UriMatchType::Domain), + uri_checksum: None, + }; + assert!(!uri.is_checksum_valid()); + } + + #[test] + fn test_generate_checksum() { + let mut uri = super::LoginUriView { + uri: Some("https://test.com".to_string()), + r#match: Some(super::UriMatchType::Domain), + uri_checksum: None, + }; + + uri.generate_checksum(); + + assert_eq!( + uri.uri_checksum.unwrap().as_str(), + "OWk2vQvwYD1nhLZdA+ltrpBWbDa2JmHyjUEWxRZSS8w=" + ); + } +} From cb2e1f3c90e6a0c6d065332d4510bc3f1856799b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Mon, 25 Mar 2024 15:07:32 +0100 Subject: [PATCH 345/378] [DEVOPS-1750] Change structure of sm-sdk-go repo (#677) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/release-go.yml:** Move `schemas.go` artifact to the `sm-sdk-go` repo root and repack zip artifacts to include only needed (`libbitwarden_c.*`) files. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/release-go.yml | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index a434dce4e..8ea03e928 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -58,15 +58,6 @@ jobs: with: path: sdk - - name: Download artifacts - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: generate_schemas.yml - path: sdk/languages/go/bitwarden_sdk_secrets/lib - workflow_conclusion: success - branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: schemas.go - - name: Login to Azure - Prod Subscription uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 with: @@ -98,6 +89,15 @@ jobs: # Copy files to local sm-sdk-go repo path cp --verbose -rf sdk/languages/go/. sm-sdk-go + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: generate_schemas.yml + path: sm-sdk-go + workflow_conclusion: success + branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + artifacts: schemas.go + - name: Replace repo name working-directory: sm-sdk-go run: | @@ -194,10 +194,16 @@ jobs: - name: Rename build artifacts run: | - mv libbitwarden_c_files-x86_64-apple-darwin.zip libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION.zip - mv libbitwarden_c_files-aarch64-apple-darwin.zip libbitwarden_c_files-aarch64-apple-darwin-$_PKG_VERSION.zip - mv libbitwarden_c_files-x86_64-unknown-linux-gnu.zip libbitwarden_c_files-x86_64-unknown-linux-gnu-$_PKG_VERSION.zip - mv libbitwarden_c_files-x86_64-pc-windows-msvc.zip libbitwarden_c_files-x86_64-pc-windows-msvc-$_PKG_VERSION.zip + artifacts=("x86_64-apple-darwin" "aarch64-apple-darwin" "x86_64-unknown-linux-gnu" "x86_64-pc-windows-msvc") # aarch64-unknown-linux-gnu) + for value in "${artifacts[@]}" + do + unzip libbitwarden_c_files-$value.zip -d libbitwarden_c_files-$value + cd libbitwarden_c_files-$value + zip -Rj ../libbitwarden_c_files-$value-$_PKG_VERSION.zip 'libbitwarden_c.*' + cd .. + done + + ls ./libbitwarden_c_files-x86_64-apple-darwin-$_PKG_VERSION -lRa - name: Create release if: ${{ inputs.release_type != 'Dry Run' }} From 596ce17fe9b75f4435250b531485069d1e1348f2 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Mon, 25 Mar 2024 11:31:55 -0400 Subject: [PATCH 346/378] Nightly Toolchain Note (#675) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add a note about the required nightly toolchain. Without this people will receive an error when attempting to run the `build-api.sh` script. For posterity, the nightly toolchain is required for certain features deemed unsafe. You can find more info here: https://github.com/bitwarden/sdk/pull/512 ## Code changes - **README.md:** Add nightly install instructions ## Before you submit - Please add **unit tests** where it makes sense to do so --- README.md | 3 +++ support/build-api.sh | 1 + 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index cdc52a7cb..a1ef88b7d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,9 @@ This project uses customized templates which lives in the `support/openapi-templ These templates resolves some outstanding issues we've experienced with the rust generator. But we strive towards modifying the templates as little as possible to ease future upgrades. +Note: If you don't have the nightly toolchain installed, the `build-api.sh` script will install it +for you. + ## Tests Many of the SDK tests are based on encrypted data provided by the other Bitwarden clients. In order diff --git a/support/build-api.sh b/support/build-api.sh index a668b5564..ea295a523 100755 --- a/support/build-api.sh +++ b/support/build-api.sh @@ -22,5 +22,6 @@ npx openapi-generator-cli generate \ -t ./support/openapi-template \ --additional-properties=packageVersion=1.0.0 +rustup toolchain install nightly cargo +nightly fmt npm run prettier From 27cf0540a437fad0e44fca99df754dc4d553a6e8 Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Wed, 27 Mar 2024 12:35:02 -0400 Subject: [PATCH 347/378] Adjust scan permissions (#683) ## Objective Adjusts the permissions for the scanning workflow per our standard template. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/scan.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 45763089c..4bed1380f 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -10,8 +10,6 @@ on: pull_request_target: types: [opened, synchronize] -permissions: read-all - jobs: check-run: name: Check PR run @@ -22,6 +20,8 @@ jobs: runs-on: ubuntu-22.04 needs: check-run permissions: + contents: read + pull-requests: write security-events: write steps: @@ -43,7 +43,7 @@ jobs: additional_params: --report-format sarif --output-path . ${{ env.INCREMENTAL }} - name: Upload Checkmarx results to GitHub - uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 with: sarif_file: cx_result.sarif @@ -51,6 +51,9 @@ jobs: name: Quality scan runs-on: ubuntu-22.04 needs: check-run + permissions: + contents: read + pull-requests: write steps: - name: Check out repo From 51a514063be4044d1f4b648ae33b9c491c6d625b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 28 Mar 2024 12:39:47 +0100 Subject: [PATCH 348/378] [PM-7067] Remove unnecessary unwraps (#682) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective This PR replaces the unwraps found in the audit by proper error handling, I've also had a quick look through the rest of the code base and replaced a bunch of others as well. --- crates/bitwarden-crypto/src/keys/master_key.rs | 7 +++++-- crates/bitwarden-crypto/src/rsa.rs | 7 +++++-- crates/bitwarden/src/auth/login/api_key.rs | 10 +++++++--- crates/bitwarden/src/auth/login/auth_request.rs | 12 ++++++------ crates/bitwarden/src/auth/login/password.rs | 10 +++++++--- .../bitwarden/src/mobile/vault/client_attachments.rs | 4 ++-- crates/bitwarden/src/mobile/vault/client_sends.rs | 4 ++-- crates/bitwarden/src/vault/cipher/login.rs | 2 +- crates/bw/src/auth/login.rs | 8 ++------ 9 files changed, 37 insertions(+), 27 deletions(-) diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index aff403c59..8e6d2575b 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -5,7 +5,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use super::utils::{derive_kdf_key, stretch_kdf_key}; -use crate::{util, EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey}; +use crate::{util, CryptoError, EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey}; #[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -68,7 +68,10 @@ impl MasterKey { EncString::encrypt_aes256_hmac( user_key.to_vec().as_slice(), - stretched_key.mac_key.as_ref().unwrap(), + stretched_key + .mac_key + .as_ref() + .ok_or(CryptoError::InvalidMac)?, &stretched_key.key, ) } diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index 231e77aaa..98f1282cc 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -36,8 +36,11 @@ pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_pkcs8_der() .map_err(|_| RsaError::CreatePrivateKey)?; - let protected = - EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.as_ref().unwrap(), &key.key)?; + let protected = EncString::encrypt_aes256_hmac( + pkcs.as_bytes(), + key.mac_key.as_ref().ok_or(CryptoError::InvalidMac)?, + &key.key, + )?; Ok(RsaKeyPair { public: b64, diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index e161ececd..72d05897a 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -9,7 +9,7 @@ use crate::{ JWTToken, }, client::{LoginMethod, UserLoginMethod}, - error::Result, + error::{Error, Result}, Client, }; @@ -44,8 +44,12 @@ pub(crate) async fn login_api_key( kdf, })); - let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); - let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); + let user_key: EncString = r.key.as_deref().ok_or(Error::MissingFields)?.parse()?; + let private_key: EncString = r + .private_key + .as_deref() + .ok_or(Error::MissingFields)? + .parse()?; client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs index 1d85c75d6..ee2aef254 100644 --- a/crates/bitwarden/src/auth/login/auth_request.rs +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -13,7 +13,7 @@ use crate::{ auth_request::new_auth_request, }, client::{LoginMethod, UserLoginMethod}, - error::Result, + error::{Error, Result}, mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, Client, }; @@ -50,7 +50,7 @@ pub(crate) async fn send_new_auth_request( fingerprint: auth.fingerprint, email, device_identifier, - auth_request_id: res.id.unwrap(), + auth_request_id: res.id.ok_or(Error::MissingFields)?, access_code: auth.access_code, private_key: auth.private_key, }) @@ -103,11 +103,11 @@ pub(crate) async fn complete_auth_request( let method = match res.master_password_hash { Some(_) => AuthRequestMethod::MasterKey { - protected_master_key: res.key.unwrap().parse().unwrap(), - auth_request_key: r.key.unwrap().parse().unwrap(), + protected_master_key: res.key.ok_or(Error::MissingFields)?.parse()?, + auth_request_key: r.key.ok_or(Error::MissingFields)?.parse()?, }, None => AuthRequestMethod::UserKey { - protected_user_key: res.key.unwrap().parse().unwrap(), + protected_user_key: res.key.ok_or(Error::MissingFields)?.parse()?, }, }; @@ -116,7 +116,7 @@ pub(crate) async fn complete_auth_request( .initialize_user_crypto(InitUserCryptoRequest { kdf_params: kdf, email: auth_req.email, - private_key: r.private_key.unwrap(), + private_key: r.private_key.ok_or(Error::MissingFields)?, method: InitUserCryptoMethod::AuthRequest { request_private_key: auth_req.private_key, method, diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 02552b70e..9fa62a566 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -24,7 +24,7 @@ pub(crate) async fn login_password( ) -> Result { use bitwarden_crypto::{EncString, HashPurpose}; - use crate::{auth::determine_password_hash, client::UserLoginMethod}; + use crate::{auth::determine_password_hash, client::UserLoginMethod, error::Error}; info!("password logging in"); debug!("{:#?}, {:#?}", client, input); @@ -49,8 +49,12 @@ pub(crate) async fn login_password( kdf: input.kdf.to_owned(), })); - let user_key: EncString = r.key.as_deref().unwrap().parse().unwrap(); - let private_key: EncString = r.private_key.as_deref().unwrap().parse().unwrap(); + let user_key: EncString = r.key.as_deref().ok_or(Error::MissingFields)?.parse()?; + let private_key: EncString = r + .private_key + .as_deref() + .ok_or(Error::MissingFields)? + .parse()?; client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/mobile/vault/client_attachments.rs b/crates/bitwarden/src/mobile/vault/client_attachments.rs index c436f10fd..e40721b04 100644 --- a/crates/bitwarden/src/mobile/vault/client_attachments.rs +++ b/crates/bitwarden/src/mobile/vault/client_attachments.rs @@ -40,7 +40,7 @@ impl<'a> ClientAttachments<'a> { decrypted_file_path: &Path, encrypted_file_path: &Path, ) -> Result { - let data = std::fs::read(decrypted_file_path).unwrap(); + let data = std::fs::read(decrypted_file_path)?; let AttachmentEncryptResult { attachment, contents, @@ -73,7 +73,7 @@ impl<'a> ClientAttachments<'a> { encrypted_file_path: &Path, decrypted_file_path: &Path, ) -> Result<()> { - let data = std::fs::read(encrypted_file_path).unwrap(); + let data = std::fs::read(encrypted_file_path)?; let decrypted = self.decrypt_buffer(cipher, attachment, &data).await?; std::fs::write(decrypted_file_path, decrypted)?; Ok(()) diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index 45d9a7825..e03432313 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -36,7 +36,7 @@ impl<'a> ClientSends<'a> { encrypted_file_path: &Path, decrypted_file_path: &Path, ) -> Result<()> { - let data = std::fs::read(encrypted_file_path).unwrap(); + let data = std::fs::read(encrypted_file_path)?; let decrypted = self.decrypt_buffer(send, &data).await?; std::fs::write(decrypted_file_path, decrypted)?; Ok(()) @@ -65,7 +65,7 @@ impl<'a> ClientSends<'a> { decrypted_file_path: &Path, encrypted_file_path: &Path, ) -> Result<()> { - let data = std::fs::read(decrypted_file_path).unwrap(); + let data = std::fs::read(decrypted_file_path)?; let encrypted = self.encrypt_buffer(send, &data).await?; std::fs::write(encrypted_file_path, encrypted)?; Ok(()) diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 26fd59001..e5731dbee 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -238,7 +238,7 @@ impl TryFrom for Fido2Cre .ok() .flatten(), discoverable: value.discoverable.ok_or(Error::MissingFields)?.parse()?, - creation_date: value.creation_date.parse().unwrap(), + creation_date: value.creation_date.parse()?, }) } } diff --git a/crates/bw/src/auth/login.rs b/crates/bw/src/auth/login.rs index e0195f5aa..91e740a3a 100644 --- a/crates/bw/src/auth/login.rs +++ b/crates/bw/src/auth/login.rs @@ -123,17 +123,13 @@ pub(crate) async fn login_device( let email = text_prompt_when_none("Email", email)?; let device_identifier = text_prompt_when_none("Device Identifier", device_identifier)?; - let auth = client - .auth() - .login_device(email, device_identifier) - .await - .unwrap(); + let auth = client.auth().login_device(email, device_identifier).await?; println!("Fingerprint: {}", auth.fingerprint); Text::new("Press enter once approved").prompt()?; - client.auth().login_device_complete(auth).await.unwrap(); + client.auth().login_device_complete(auth).await?; Ok(()) } From 0ae0226d4c56c36f82f4056071dec791fcc73d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Thu, 28 Mar 2024 15:34:25 +0100 Subject: [PATCH 349/378] [PM-7051] Implement make_register_tde_keys (#685) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Add support in the SDK to create the keys necessary for the just in time user for TDE --- crates/bitwarden-uniffi/src/auth/mod.rs | 16 ++++++++ crates/bitwarden/src/auth/client_auth.rs | 9 +++++ crates/bitwarden/src/auth/mod.rs | 4 ++ crates/bitwarden/src/auth/tde.rs | 51 ++++++++++++++++++++++++ crates/bitwarden/src/client/client.rs | 2 +- 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 crates/bitwarden/src/auth/tde.rs diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 2a451ffdf..62b709045 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use bitwarden::auth::{ password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, + RegisterTdeKeyResponse, }; use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf, TrustDeviceResponse}; @@ -78,6 +79,21 @@ impl ClientAuth { .make_register_keys(email, password, kdf)?) } + /// Generate keys needed for TDE process + pub async fn make_register_tde_keys( + &self, + org_public_key: String, + remember_device: bool, + ) -> Result { + Ok(self + .0 + .0 + .write() + .await + .auth() + .make_register_tde_keys(org_public_key, remember_device)?) + } + /// Validate the user password /// /// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 5f2002133..5029d389b 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -20,6 +20,7 @@ use crate::{ MasterPasswordPolicyOptions, }, register::{make_register_keys, register}, + tde::{make_register_tde_keys, RegisterTdeKeyResponse}, AuthRequestResponse, RegisterKeyResponse, RegisterRequest, }, client::Kdf, @@ -73,6 +74,14 @@ impl<'a> ClientAuth<'a> { make_register_keys(email, password, kdf) } + pub fn make_register_tde_keys( + &mut self, + org_public_key: String, + remember_device: bool, + ) -> Result { + make_register_tde_keys(self.client, org_public_key, remember_device) + } + pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 7918694e2..b1fe2dbda 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -20,6 +20,10 @@ mod auth_request; pub use auth_request::AuthRequestResponse; #[cfg(feature = "mobile")] pub(crate) use auth_request::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; +#[cfg(feature = "internal")] +mod tde; +#[cfg(feature = "internal")] +pub use tde::RegisterTdeKeyResponse; #[cfg(feature = "internal")] use crate::{client::Kdf, error::Result}; diff --git a/crates/bitwarden/src/auth/tde.rs b/crates/bitwarden/src/auth/tde.rs new file mode 100644 index 000000000..1a3de3026 --- /dev/null +++ b/crates/bitwarden/src/auth/tde.rs @@ -0,0 +1,51 @@ +use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::{ + AsymmetricEncString, AsymmetricPublicCryptoKey, DeviceKey, EncString, SymmetricCryptoKey, + TrustDeviceResponse, UserKey, +}; + +use crate::{error::Result, Client}; + +/// This function generates a new user key and key pair, initializes the client's crypto with the +/// generated user key, and encrypts the user key with the organization public key for admin +/// password reset. If remember_device is true, it also generates a device key. +pub(super) fn make_register_tde_keys( + client: &mut Client, + org_public_key: String, + remember_device: bool, +) -> Result { + let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(org_public_key)?)?; + + let mut rng = rand::thread_rng(); + + let user_key = UserKey::new(SymmetricCryptoKey::generate(&mut rng)); + let key_pair = user_key.make_key_pair()?; + + let admin_reset = + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(&user_key.0.to_vec(), &public_key)?; + + let device_key = if remember_device { + Some(DeviceKey::trust_device(&user_key.0)?) + } else { + None + }; + + client.initialize_user_crypto_decrypted_key(user_key.0, key_pair.private.clone())?; + + Ok(RegisterTdeKeyResponse { + private_key: key_pair.private, + public_key: key_pair.public, + + admin_reset, + device_key, + }) +} + +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct RegisterTdeKeyResponse { + pub private_key: EncString, + pub public_key: String, + + pub admin_reset: AsymmetricEncString, + pub device_key: Option, +} diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 883720529..68442d5d3 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -265,7 +265,7 @@ impl Client { Ok(self.encryption_settings.as_ref().unwrap()) } - #[cfg(feature = "mobile")] + #[cfg(feature = "internal")] pub(crate) fn initialize_user_crypto_decrypted_key( &mut self, user_key: SymmetricCryptoKey, From 9cd9a152af3ad00e910916fa68fe103953683161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 29 Mar 2024 12:56:02 +0100 Subject: [PATCH 350/378] Update dotnet build pipeline (#671) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/build-dotnet.yml:** Trigger build on `rc` and `hotfix-rc` branches, get dotnet project version from `.csproj` while building. - **.github/workflows/publish-dotnet.yml** Use build artifact during publish ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/build-dotnet.yml | 31 +++++++++++--- .github/workflows/publish-dotnet.yml | 60 +++------------------------- 2 files changed, 31 insertions(+), 60 deletions(-) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 58bbd5dfa..b08b37160 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -4,6 +4,10 @@ on: push: branches: - main + - rc + - hotfix-rc + pull_request: + workflow_dispatch: jobs: generate_schemas: @@ -12,12 +16,31 @@ jobs: build_rust: uses: ./.github/workflows/build-rust-cross-platform.yml + version: + name: Get version + runs-on: ubuntu-22.04 + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Install xmllint + run: sudo apt-get install -y libxml2-utils + + - name: Get version + id: version + run: | + VERSION=$(xmllint --xpath 'string(/Project/PropertyGroup/Version)' languages/csharp/Bitwarden.Sdk/Bitwarden.Sdk.csproj) + echo "version=$VERSION" >> $GITHUB_OUTPUT + build_dotnet: name: Build .NET runs-on: ubuntu-22.04 needs: - generate_schemas - build_rust + - version steps: - name: Checkout Repository @@ -58,21 +81,19 @@ jobs: name: libbitwarden_c_files-x86_64-pc-windows-msvc path: languages/csharp/Bitwarden.Sdk/windows-x64 - - name: Build .NET 6 Project + - name: Build .NET Project working-directory: languages/csharp/Bitwarden.Sdk run: | dotnet restore dotnet build --configuration Release - name: Pack NuGet Package - env: - VERSION: 0.0.1 - run: dotnet pack --configuration Release -p:PackageID=Bitwarden.Sdk -p:Version=${VERSION} --output ./nuget-output /nologo /v:n + run: dotnet pack --configuration Release --output ./nuget-output /nologo /v:n working-directory: languages/csharp/Bitwarden.Sdk - name: Upload NuGet package uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: - name: Bitwarden.Sdk.0.0.1.nupkg + name: Bitwarden.Sdk.${{ needs.version.outputs.version }}.nupkg path: | ./languages/csharp/Bitwarden.Sdk/nuget-output/*.nupkg diff --git a/.github/workflows/publish-dotnet.yml b/.github/workflows/publish-dotnet.yml index 66d9dc712..73f930c1a 100644 --- a/.github/workflows/publish-dotnet.yml +++ b/.github/workflows/publish-dotnet.yml @@ -50,64 +50,14 @@ jobs: runs-on: ubuntu-22.04 needs: validate steps: - - name: Checkout Repository - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Download C# schemas artifact - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: generate_schemas.yml - workflow_conclusion: success - branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: schemas.cs - path: languages/csharp/Bitwarden.Sdk - - - name: Set up .NET Core - uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0 - with: - global-json-file: languages/csharp/global.json - - - name: Download x86_64-apple-darwin files - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: build-rust-cross-platform.yml - workflow_conclusion: success - branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: libbitwarden_c_files-x86_64-apple-darwin - path: languages/csharp/Bitwarden.Sdk/macos-x64 - - - name: Download aarch64-apple-darwin files + - name: Download NuGet package uses: bitwarden/gh-actions/download-artifacts@main with: - workflow: build-rust-cross-platform.yml + workflow: build-dotnet.yml workflow_conclusion: success branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: libbitwarden_c_files-aarch64-apple-darwin - path: languages/csharp/Bitwarden.Sdk/macos-arm64 - - - name: Download x86_64-unknown-linux-gnu files - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: build-rust-cross-platform.yml - workflow_conclusion: success - branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: libbitwarden_c_files-x86_64-unknown-linux-gnu - path: languages/csharp/Bitwarden.Sdk/linux-x64 - - - name: Download x86_64-pc-windows-msvc files - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: build-rust-cross-platform.yml - workflow_conclusion: success - branch: ${{ inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} - artifacts: libbitwarden_c_files-x86_64-pc-windows-msvc - path: languages/csharp/Bitwarden.Sdk/windows-x64 - - - name: Pack NuGet Package - env: - VERSION: ${{ needs.validate.outputs.version }} - run: dotnet pack --configuration Release -p:PackageID=Bitwarden.Sdk -p:Version=${VERSION} --output ./nuget-output /nologo /v:n - working-directory: languages/csharp/Bitwarden.Sdk + artifacts: Bitwarden.Sdk.${{ needs.validate.outputs.version }}.nupkg + path: ./nuget-output - name: Login to Azure - Prod Subscription uses: Azure/login@92a5484dfaf04ca78a94597f4f19fea633851fa2 # v1.4.7 @@ -125,4 +75,4 @@ jobs: if: ${{ inputs.release_type != 'Dry Run' }} env: NUGET_API_KEY: ${{ steps.retrieve-secrets.outputs.nuget-api-key }} - run: dotnet nuget push ./languages/csharp/Bitwarden.Sdk/nuget-output/*.nupkg -k ${{ env.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json + run: dotnet nuget push ./nuget-output/*.nupkg -k ${{ env.NUGET_API_KEY }} -s https://api.nuget.org/v3/index.json From 538b9f20d157a0bc124effa0cd612d08c453ef8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 1 Apr 2024 16:03:50 +0200 Subject: [PATCH 351/378] Add sensitive types to SymmetricCryptoKey (#672) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective This is a small subset of #536, which only contains the minimum code to protect the import/export functions on SymmetricCryptoKey. It also enables the from_base64 test on SymmetricCryptoKey as that passes now. After this PR is merged I'll be expanding the use of Sensitive to other parts of the codebase while adding some extra memory testing checks to validate that it works for them. --- .../src/enc_string/symmetric.rs | 16 +- .../bitwarden-crypto/src/keys/device_key.rs | 34 ++- .../bitwarden-crypto/src/keys/master_key.rs | 2 +- crates/bitwarden-crypto/src/keys/mod.rs | 2 +- .../src/keys/shareable_key.rs | 4 +- .../src/keys/symmetric_crypto_key.rs | 53 +++-- crates/bitwarden-crypto/src/lib.rs | 2 + .../src/sensitive/decrypted.rs | 16 ++ crates/bitwarden-crypto/src/sensitive/mod.rs | 5 + .../src/sensitive/sensitive.rs | 220 ++++++++++++++++++ crates/bitwarden-crypto/src/uniffi_support.rs | 25 +- crates/bitwarden-uniffi/src/crypto.rs | 4 +- crates/bitwarden-uniffi/src/uniffi_support.rs | 3 +- crates/bitwarden/src/auth/access_token.rs | 2 +- crates/bitwarden/src/auth/auth_request.rs | 14 +- .../bitwarden/src/auth/login/access_token.rs | 12 +- crates/bitwarden/src/auth/tde.rs | 2 +- crates/bitwarden/src/mobile/client_crypto.rs | 4 +- crates/bitwarden/src/mobile/crypto.rs | 25 +- crates/bitwarden/src/secrets_manager/state.rs | 6 +- crates/bitwarden/src/uniffi_support.rs | 7 +- .../bitwarden/src/vault/cipher/attachment.rs | 11 +- crates/bitwarden/src/vault/cipher/cipher.rs | 2 +- crates/bitwarden/src/vault/send.rs | 2 +- .../memory-testing/src/bin/analyze-dumps.rs | 4 +- crates/memory-testing/src/main.rs | 9 +- 26 files changed, 381 insertions(+), 105 deletions(-) create mode 100644 crates/bitwarden-crypto/src/sensitive/decrypted.rs create mode 100644 crates/bitwarden-crypto/src/sensitive/mod.rs create mode 100644 crates/bitwarden-crypto/src/sensitive/sensitive.rs diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index d5489fc96..0217a4b93 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -290,14 +290,16 @@ mod tests { use schemars::schema_for; use super::EncString; - use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use crate::{ + derive_symmetric_key, KeyDecryptable, KeyEncryptable, SensitiveString, SymmetricCryptoKey, + }; #[test] fn test_enc_string_roundtrip() { let key = derive_symmetric_key("test"); - let test_string = "encrypted_test_string".to_string(); - let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); + let test_string = "encrypted_test_string"; + let cipher = test_string.to_owned().encrypt_with_key(&key).unwrap(); let decrypted_str: String = cipher.decrypt_with_key(&key).unwrap(); assert_eq!(decrypted_str, test_string); @@ -390,8 +392,8 @@ mod tests { #[test] fn test_decrypt_cbc256() { - let key = "hvBMMb1t79YssFZkpetYsM3deyVuQv4r88Uj9gvYe08="; - let key: SymmetricCryptoKey = key.parse().unwrap(); + let key = SensitiveString::test("hvBMMb1t79YssFZkpetYsM3deyVuQv4r88Uj9gvYe08="); + let key = SymmetricCryptoKey::try_from(key).unwrap(); let enc_str = "0.NQfjHLr6za7VQVAbrpL81w==|wfrjmyJ0bfwkQlySrhw8dA=="; let enc_string: EncString = enc_str.parse().unwrap(); @@ -403,8 +405,8 @@ mod tests { #[test] fn test_decrypt_cbc128_hmac() { - let key = "Gt1aZ8kTTgkF80bLtb7LiMZBcxEA2FA5mbvV4x7K208="; - let key: SymmetricCryptoKey = key.parse().unwrap(); + let key = SensitiveString::test("Gt1aZ8kTTgkF80bLtb7LiMZBcxEA2FA5mbvV4x7K208="); + let key = SymmetricCryptoKey::try_from(key).unwrap(); let enc_str = "1.CU/oG4VZuxbHoZSDZjCLQw==|kb1HGwAk+fQ275ORfLf5Ew==|8UaEYHyqRZcG37JWhYBOBdEatEXd1u1/wN7OuImolcM="; let enc_string: EncString = enc_str.parse().unwrap(); diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs index 876ae7b75..d33e0dc32 100644 --- a/crates/bitwarden-crypto/src/keys/device_key.rs +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -1,8 +1,6 @@ -use std::str::FromStr; - use crate::{ - error::Result, AsymmetricCryptoKey, AsymmetricEncString, CryptoError, EncString, - KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, + error::Result, AsymmetricCryptoKey, AsymmetricEncString, CryptoError, DecryptedVec, EncString, + KeyDecryptable, KeyEncryptable, SensitiveString, SymmetricCryptoKey, }; /// Device Key @@ -16,7 +14,7 @@ pub struct DeviceKey(SymmetricCryptoKey); #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct TrustDeviceResponse { /// Base64 encoded device key - pub device_key: String, + pub device_key: SensitiveString, /// UserKey encrypted with DevicePublicKey pub protected_user_key: AsymmetricEncString, /// DevicePrivateKey encrypted with [DeviceKey] @@ -40,7 +38,7 @@ impl DeviceKey { let data = user_key.to_vec(); let protected_user_key = - AsymmetricEncString::encrypt_rsa2048_oaep_sha1(&data, &device_private_key)?; + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(data.expose(), &device_private_key)?; let protected_device_public_key = device_private_key .to_public_der()? @@ -65,25 +63,25 @@ impl DeviceKey { protected_user_key: AsymmetricEncString, ) -> Result { let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; - let device_private_key = AsymmetricCryptoKey::from_der(device_private_key.as_slice())?; + let device_private_key = AsymmetricCryptoKey::from_der(&device_private_key)?; - let mut dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; - let user_key: SymmetricCryptoKey = dec.as_mut_slice().try_into()?; + let dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; + let dec = DecryptedVec::new(Box::new(dec)); + let user_key = SymmetricCryptoKey::try_from(dec)?; Ok(user_key) } - fn to_base64(&self) -> String { + fn to_base64(&self) -> SensitiveString { self.0.to_base64() } } -impl FromStr for DeviceKey { - type Err = CryptoError; +impl TryFrom for DeviceKey { + type Error = CryptoError; - fn from_str(s: &str) -> Result { - let key = s.parse::()?; - Ok(DeviceKey(key)) + fn try_from(value: SensitiveString) -> Result { + SymmetricCryptoKey::try_from(value).map(DeviceKey) } } @@ -98,10 +96,8 @@ mod tests { let result = DeviceKey::trust_device(&key).unwrap(); - let decrypted = result - .device_key - .parse::() - .unwrap() + let device_key = DeviceKey::try_from(result.device_key).unwrap(); + let decrypted = device_key .decrypt_user_key( result.protected_device_private_key, result.protected_user_key, diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 8e6d2575b..b6921fc6b 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -67,7 +67,7 @@ impl MasterKey { let stretched_key = stretch_kdf_key(&self.0)?; EncString::encrypt_aes256_hmac( - user_key.to_vec().as_slice(), + user_key.to_vec().expose(), stretched_key .mac_key .as_ref() diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 5bfd32b8b..435f1011b 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -1,5 +1,5 @@ mod key_encryptable; -pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; +pub use key_encryptable::{CryptoKey, KeyDecryptable, KeyEncryptable}; mod master_key; pub use master_key::{HashPurpose, Kdf, MasterKey}; mod shareable_key; diff --git a/crates/bitwarden-crypto/src/keys/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs index fbb2d2e44..2b9ec837f 100644 --- a/crates/bitwarden-crypto/src/keys/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -37,9 +37,9 @@ mod tests { #[test] fn test_derive_shareable_key() { let key = derive_shareable_key(*b"&/$%F1a895g67HlX", "test_key", None); - assert_eq!(key.to_base64(), "4PV6+PcmF2w7YHRatvyMcVQtI7zvCyssv/wFWmzjiH6Iv9altjmDkuBD1aagLVaLezbthbSe+ktR+U6qswxNnQ=="); + assert_eq!(key.to_base64().expose(), "4PV6+PcmF2w7YHRatvyMcVQtI7zvCyssv/wFWmzjiH6Iv9altjmDkuBD1aagLVaLezbthbSe+ktR+U6qswxNnQ=="); let key = derive_shareable_key(*b"67t9b5g67$%Dh89n", "test_key", Some("test")); - assert_eq!(key.to_base64(), "F9jVQmrACGx9VUPjuzfMYDjr726JtL300Y3Yg+VYUnVQtQ1s8oImJ5xtp1KALC9h2nav04++1LDW4iFD+infng=="); + assert_eq!(key.to_base64().expose(), "F9jVQmrACGx9VUPjuzfMYDjr726JtL300Y3Yg+VYUnVQtQ1s8oImJ5xtp1KALC9h2nav04++1LDW4iFD+infng=="); } } diff --git a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 0c165bb40..23d09cbca 100644 --- a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -1,13 +1,13 @@ -use std::{pin::Pin, str::FromStr}; +use std::pin::Pin; use aes::cipher::typenum::U32; -use base64::{engine::general_purpose::STANDARD, Engine}; +use base64::engine::general_purpose::STANDARD; use generic_array::GenericArray; use rand::Rng; -use zeroize::{Zeroize, Zeroizing}; +use zeroize::Zeroize; use super::key_encryptable::CryptoKey; -use crate::CryptoError; +use crate::{CryptoError, SensitiveString, SensitiveVec}; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { @@ -59,31 +59,35 @@ impl SymmetricCryptoKey { self.key.len() + self.mac_key.as_ref().map_or(0, |mac| mac.len()) } - pub fn to_base64(&self) -> String { - let mut buf = self.to_vec(); - - let result = STANDARD.encode(&buf); - buf.zeroize(); - result + pub fn to_base64(&self) -> SensitiveString { + self.to_vec().encode_base64(STANDARD) } - pub fn to_vec(&self) -> Zeroizing> { - let mut buf = Vec::with_capacity(self.total_len()); + pub fn to_vec(&self) -> SensitiveVec { + let mut buf = SensitiveVec::new(Box::new(Vec::with_capacity(self.total_len()))); - buf.extend_from_slice(&self.key); + buf.expose_mut().extend_from_slice(&self.key); if let Some(mac) = &self.mac_key { - buf.extend_from_slice(mac); + buf.expose_mut().extend_from_slice(mac); } - Zeroizing::new(buf) + buf } } -impl FromStr for SymmetricCryptoKey { - type Err = CryptoError; +impl TryFrom for SymmetricCryptoKey { + type Error = CryptoError; - fn from_str(s: &str) -> Result { - let mut bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; - SymmetricCryptoKey::try_from(bytes.as_mut_slice()) + fn try_from(value: SensitiveString) -> Result { + SymmetricCryptoKey::try_from(value.decode_base64(STANDARD)?) + } +} + +impl TryFrom for SymmetricCryptoKey { + type Error = CryptoError; + + fn try_from(mut value: SensitiveVec) -> Result { + let val = value.expose_mut(); + SymmetricCryptoKey::try_from(val.as_mut_slice()) } } @@ -138,19 +142,18 @@ pub fn derive_symmetric_key(name: &str) -> SymmetricCryptoKey { #[cfg(test)] mod tests { - use std::str::FromStr; - use super::{derive_symmetric_key, SymmetricCryptoKey}; + use crate::SensitiveString; #[test] fn test_symmetric_crypto_key() { let key = derive_symmetric_key("test"); - let key2 = SymmetricCryptoKey::from_str(&key.to_base64()).unwrap(); + let key2 = SymmetricCryptoKey::try_from(key.to_base64()).unwrap(); assert_eq!(key.key, key2.key); assert_eq!(key.mac_key, key2.mac_key); - let key = "UY4B5N4DA4UisCNClgZtRr6VLy9ZF5BXXC7cDZRqourKi4ghEMgISbCsubvgCkHf5DZctQjVot11/vVvN9NNHQ=="; - let key2 = SymmetricCryptoKey::from_str(key).unwrap(); + let key = SensitiveString::test("UY4B5N4DA4UisCNClgZtRr6VLy9ZF5BXXC7cDZRqourKi4ghEMgISbCsubvgCkHf5DZctQjVot11/vVvN9NNHQ=="); + let key2 = SymmetricCryptoKey::try_from(key.clone()).unwrap(); assert_eq!(key, key2.to_base64()); } } diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index 3c1aced24..8c368580a 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -40,6 +40,8 @@ pub use util::generate_random_bytes; mod wordlist; pub use util::pbkdf2; pub use wordlist::EFF_LONG_WORD_LIST; +mod sensitive; +pub use sensitive::*; #[cfg(feature = "mobile")] uniffi::setup_scaffolding!(); diff --git a/crates/bitwarden-crypto/src/sensitive/decrypted.rs b/crates/bitwarden-crypto/src/sensitive/decrypted.rs new file mode 100644 index 000000000..02096d081 --- /dev/null +++ b/crates/bitwarden-crypto/src/sensitive/decrypted.rs @@ -0,0 +1,16 @@ +use zeroize::Zeroize; + +use crate::{CryptoError, CryptoKey, KeyEncryptable, Sensitive}; + +/// Type alias for a [`Sensitive`] value to denote decrypted data. +pub type Decrypted = Sensitive; +pub type DecryptedVec = Decrypted>; +pub type DecryptedString = Decrypted; + +impl + Zeroize + Clone, Key: CryptoKey, Output> + KeyEncryptable for Decrypted +{ + fn encrypt_with_key(self, key: &Key) -> Result { + self.value.clone().encrypt_with_key(key) + } +} diff --git a/crates/bitwarden-crypto/src/sensitive/mod.rs b/crates/bitwarden-crypto/src/sensitive/mod.rs new file mode 100644 index 000000000..0da2329b9 --- /dev/null +++ b/crates/bitwarden-crypto/src/sensitive/mod.rs @@ -0,0 +1,5 @@ +#[allow(clippy::module_inception)] +mod sensitive; +pub use sensitive::{Sensitive, SensitiveString, SensitiveVec}; +mod decrypted; +pub use decrypted::{Decrypted, DecryptedString, DecryptedVec}; diff --git a/crates/bitwarden-crypto/src/sensitive/sensitive.rs b/crates/bitwarden-crypto/src/sensitive/sensitive.rs new file mode 100644 index 000000000..996b20330 --- /dev/null +++ b/crates/bitwarden-crypto/src/sensitive/sensitive.rs @@ -0,0 +1,220 @@ +use std::{ + borrow::Cow, + fmt::{self, Formatter}, +}; + +use schemars::JsonSchema; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use zeroize::{Zeroize, ZeroizeOnDrop}; + +use crate::CryptoError; + +/// Wrapper for sensitive values which makes a best effort to enforce zeroization of the inner value +/// on drop. The inner value exposes a [`Sensitive::expose`] method which returns a reference to the +/// inner value. Care must be taken to avoid accidentally exposing the inner value through copying +/// or cloning. +/// +/// Internally [`Sensitive`] contains a [`Box`] which ensures the value is placed on the heap. It +/// implements the [`Drop`] trait which calls `zeroize` on the inner value. +#[derive(PartialEq, Clone, Zeroize, ZeroizeOnDrop)] +pub struct Sensitive { + pub(super) value: Box, +} + +/// Important: This type does not protect against reallocations made by the Vec. +/// This means that if you insert any elements past the capacity, the data will be copied to a +/// new allocation and the old allocation will not be zeroized. +/// To avoid this, use Vec::with_capacity to preallocate the capacity you need. +pub type SensitiveVec = Sensitive>; + +/// Important: This type does not protect against reallocations made by the String. +/// This means that if you insert any characters past the capacity, the data will be copied to a +/// new allocation and the old allocation will not be zeroized. +/// To avoid this, use String::with_capacity to preallocate the capacity you need. +pub type SensitiveString = Sensitive; + +impl Sensitive { + /// Create a new [`Sensitive`] value. In an attempt to avoid accidentally placing this on the + /// stack it only accepts a [`Box`] value. The rust compiler should be able to optimize away the + /// initial stack allocation presuming the value is not used before being boxed. + pub fn new(value: Box) -> Self { + Self { value } + } + + /// Expose the inner value. By exposing the inner value, you take responsibility for ensuring + /// that any copy of the value is zeroized. + pub fn expose(&self) -> &V { + &self.value + } + + /// Expose the inner value mutable. By exposing the inner value, you take responsibility for + /// ensuring that any copy of the value is zeroized. + pub fn expose_mut(&mut self) -> &mut V { + &mut self.value + } +} + +/// Helper to convert a `Sensitive>` to a `Sensitive`, care is taken to ensure any +/// intermediate copies are zeroed to avoid leaking sensitive data. +impl TryFrom for SensitiveString { + type Error = CryptoError; + + fn try_from(mut v: SensitiveVec) -> Result { + let value = std::mem::take(&mut v.value); + + let rtn = String::from_utf8(*value).map_err(|_| CryptoError::InvalidUtf8String); + rtn.map(|v| Sensitive::new(Box::new(v))) + } +} + +impl SensitiveString { + pub fn decode_base64(self, engine: T) -> Result { + // Prevent accidental copies by allocating the full size + let len = base64::decoded_len_estimate(self.value.len()); + let mut value = SensitiveVec::new(Box::new(Vec::with_capacity(len))); + + engine + .decode_vec(self.value.as_ref(), &mut value.value) + .map_err(|_| CryptoError::InvalidKey)?; + + Ok(value) + } +} + +impl SensitiveVec { + pub fn encode_base64(self, engine: T) -> SensitiveString { + use base64::engine::Config; + + // Prevent accidental copies by allocating the full size + let padding = engine.config().encode_padding(); + let len = base64::encoded_len(self.value.len(), padding).expect("Valid length"); + let mut value = SensitiveString::new(Box::new(String::with_capacity(len))); + + engine.encode_string(self.value.as_ref(), &mut value.value); + + value + } +} + +impl Default for Sensitive { + fn default() -> Self { + Self::new(Box::default()) + } +} + +impl fmt::Debug for Sensitive { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Sensitive") + .field("type", &std::any::type_name::()) + .field("value", &"********") + .finish() + } +} + +/// Unfortunately once we serialize a `SensitiveString` we can't control the future memory. +impl Serialize for Sensitive { + fn serialize(&self, serializer: S) -> Result { + self.value.serialize(serializer) + } +} + +impl<'de, V: Zeroize + Deserialize<'de>> Deserialize<'de> for Sensitive { + fn deserialize>(deserializer: D) -> Result { + Ok(Self::new(Box::new(V::deserialize(deserializer)?))) + } +} + +/// Transparently expose the inner value for serialization +impl JsonSchema for Sensitive { + fn schema_name() -> String { + V::schema_name() + } + + fn schema_id() -> Cow<'static, str> { + V::schema_id() + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + V::json_schema(gen) + } +} + +impl Sensitive { + // We use a lot of `&str` in our tests, so we expose this helper + // to make it easier. + // IMPORTANT: This should not be used outside of test code + // Note that we can't just mark it with #[cfg(test)] because that only applies + // when testing this crate, not when testing other crates that depend on it. + // By at least limiting it to &'static str we should be able to avoid accidental usages + pub fn test(value: &'static str) -> Self { + Self::new(Box::new(value.to_string())) + } +} + +#[cfg(test)] +mod tests { + use schemars::schema_for; + + use super::*; + + #[test] + fn test_debug() { + let string = Sensitive::test("test"); + assert_eq!( + format!("{:?}", string), + "Sensitive { type: \"alloc::string::String\", value: \"********\" }" + ); + + let vector = Sensitive::new(Box::new(vec![1, 2, 3])); + assert_eq!( + format!("{:?}", vector), + "Sensitive { type: \"alloc::vec::Vec\", value: \"********\" }" + ); + } + + #[test] + fn test_schemars() { + #[derive(JsonSchema)] + struct TestStruct { + #[allow(dead_code)] + s: SensitiveString, + #[allow(dead_code)] + v: SensitiveVec, + } + + let schema = schema_for!(TestStruct); + let json = serde_json::to_string_pretty(&schema).unwrap(); + let expected = r##"{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "TestStruct", + "type": "object", + "required": ["s", "v"], + "properties": { + "s": { + "$ref": "#/definitions/String" + }, + "v": { + "$ref": "#/definitions/Array_of_uint8" + } + }, + "definitions": { + "Array_of_uint8": { + "type": "array", + "items": { + "type": "integer", + "format": "uint8", + "minimum": 0.0 + } + }, + "String": { + "type": "string" + } + } + }"##; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ); + } +} diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index 7f1249da0..f99b55da5 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,6 +1,8 @@ use std::{num::NonZeroU32, str::FromStr}; -use crate::{AsymmetricEncString, CryptoError, EncString, UniffiCustomTypeConverter}; +use crate::{ + AsymmetricEncString, CryptoError, EncString, SensitiveString, UniffiCustomTypeConverter, +}; uniffi::custom_type!(NonZeroU32, u32); @@ -43,3 +45,24 @@ impl UniffiCustomTypeConverter for AsymmetricEncString { obj.to_string() } } + +uniffi::custom_type!(SensitiveString, String); + +impl UniffiCustomTypeConverter for SensitiveString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Ok(SensitiveString::new(Box::new(val))) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.expose().to_owned() + } +} + +/// Uniffi doesn't seem to be generating the SensitiveString unless it's being used by +/// a record somewhere. This is a workaround to make sure the type is generated. +#[derive(uniffi::Record)] +struct SupportSensitiveString { + sensitive_string: SensitiveString, +} diff --git a/crates/bitwarden-uniffi/src/crypto.rs b/crates/bitwarden-uniffi/src/crypto.rs index 0f877d52e..f3abe694a 100644 --- a/crates/bitwarden-uniffi/src/crypto.rs +++ b/crates/bitwarden-uniffi/src/crypto.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use bitwarden::mobile::crypto::{ DerivePinKeyResponse, InitOrgCryptoRequest, InitUserCryptoRequest, UpdatePasswordResponse, }; -use bitwarden_crypto::{AsymmetricEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString, SensitiveString}; use crate::{error::Result, Client}; @@ -40,7 +40,7 @@ impl ClientCrypto { /// Get the uses's decrypted encryption key. Note: It's very important /// to keep this key safe, as it can be used to decrypt all of the user's data - pub async fn get_user_encryption_key(&self) -> Result { + pub async fn get_user_encryption_key(&self) -> Result { Ok(self .0 .0 diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index 663d5c41e..a49e347b6 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,7 +1,8 @@ -use bitwarden_crypto::{AsymmetricEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString, SensitiveString}; // Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(AsymmetricEncString, bitwarden::UniFfiTag, crate::UniFfiTag); +uniffi::ffi_converter_forward!(SensitiveString, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden/src/auth/access_token.rs b/crates/bitwarden/src/auth/access_token.rs index 667a78529..4b6f050c8 100644 --- a/crates/bitwarden/src/auth/access_token.rs +++ b/crates/bitwarden/src/auth/access_token.rs @@ -79,7 +79,7 @@ mod tests { "ec2c1d46-6a4b-4751-a310-af9601317f2d" ); assert_eq!(token.client_secret, "C2IgxjjLF7qSshsbwe8JGcbM075YXw"); - assert_eq!(token.encryption_key.to_base64(), "H9/oIRLtL9nGCQOVDjSMoEbJsjWXSOCb3qeyDt6ckzS3FhyboEDWyTP/CQfbIszNmAVg2ExFganG1FVFGXO/Jg=="); + assert_eq!(token.encryption_key.to_base64().expose(), "H9/oIRLtL9nGCQOVDjSMoEbJsjWXSOCb3qeyDt6ckzS3FhyboEDWyTP/CQfbIszNmAVg2ExFganG1FVFGXO/Jg=="); } #[test] diff --git a/crates/bitwarden/src/auth/auth_request.rs b/crates/bitwarden/src/auth/auth_request.rs index 18c71afba..04dc9fdce 100644 --- a/crates/bitwarden/src/auth/auth_request.rs +++ b/crates/bitwarden/src/auth/auth_request.rs @@ -92,15 +92,13 @@ pub(crate) fn approve_auth_request( let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; Ok(AsymmetricEncString::encrypt_rsa2048_oaep_sha1( - &key.to_vec(), + key.to_vec().expose(), &public_key, )?) } #[test] fn test_auth_request() { - use zeroize::Zeroizing; - let request = new_auth_request("test@bitwarden.com").unwrap(); let secret: &[u8] = &[ @@ -117,7 +115,7 @@ fn test_auth_request() { let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap(); - assert_eq!(decrypted.to_vec(), Zeroizing::new(secret.to_owned())); + assert_eq!(decrypted.to_vec().expose(), secret); } #[cfg(test)] @@ -167,8 +165,8 @@ mod tests { let dec = auth_request_decrypt_user_key(private_key.to_owned(), enc_user_key).unwrap(); assert_eq!( - dec.to_vec().as_ref(), - vec![ + dec.to_vec().expose(), + &[ 201, 37, 234, 213, 21, 75, 40, 70, 149, 213, 234, 16, 19, 251, 162, 245, 161, 74, 34, 245, 211, 151, 211, 192, 95, 10, 117, 50, 88, 223, 23, 157 ] @@ -186,8 +184,8 @@ mod tests { .unwrap(); assert_eq!( - dec.to_vec().as_ref(), - vec![ + dec.to_vec().expose(), + &[ 109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216, 212, 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91, 215, 21, 128, 91, 226, 222, 165, 67, 251, 34, 83, 81, 77, 147, 225, 76, 13, 41, diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 46c3f2b50..a8c017009 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; -use base64::{engine::general_purpose::STANDARD, Engine}; -use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; +use base64::engine::general_purpose::STANDARD; +use bitwarden_crypto::{EncString, KeyDecryptable, SensitiveString, SymmetricCryptoKey}; use chrono::Utc; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -59,12 +59,12 @@ pub(crate) async fn login_access_token( #[derive(serde::Deserialize)] struct Payload { #[serde(rename = "encryptionKey")] - encryption_key: String, + encryption_key: SensitiveString, } let payload: Payload = serde_json::from_slice(&decrypted_payload)?; - let mut encryption_key = STANDARD.decode(payload.encryption_key.clone())?; - let encryption_key = SymmetricCryptoKey::try_from(encryption_key.as_mut_slice())?; + let encryption_key = payload.encryption_key.clone().decode_base64(STANDARD)?; + let encryption_key = SymmetricCryptoKey::try_from(encryption_key)?; let access_token_obj: JWTToken = r.access_token.parse()?; @@ -125,7 +125,7 @@ fn load_tokens_from_state( let organization_id: Uuid = organization_id .parse() .map_err(|_| "Bad organization id.")?; - let encryption_key: SymmetricCryptoKey = client_state.encryption_key.parse()?; + let encryption_key = SymmetricCryptoKey::try_from(client_state.encryption_key)?; client.set_tokens(client_state.token, None, time_till_expiration as u64); client.initialize_crypto_single_key(encryption_key); diff --git a/crates/bitwarden/src/auth/tde.rs b/crates/bitwarden/src/auth/tde.rs index 1a3de3026..0bbbb904a 100644 --- a/crates/bitwarden/src/auth/tde.rs +++ b/crates/bitwarden/src/auth/tde.rs @@ -22,7 +22,7 @@ pub(super) fn make_register_tde_keys( let key_pair = user_key.make_key_pair()?; let admin_reset = - AsymmetricEncString::encrypt_rsa2048_oaep_sha1(&user_key.0.to_vec(), &public_key)?; + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(user_key.0.to_vec().expose(), &public_key)?; let device_key = if remember_device { Some(DeviceKey::trust_device(&user_key.0)?) diff --git a/crates/bitwarden/src/mobile/client_crypto.rs b/crates/bitwarden/src/mobile/client_crypto.rs index 6ef65975d..26451ffaa 100644 --- a/crates/bitwarden/src/mobile/client_crypto.rs +++ b/crates/bitwarden/src/mobile/client_crypto.rs @@ -1,5 +1,5 @@ #[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmetricEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString, SensitiveString}; use crate::Client; #[cfg(feature = "internal")] @@ -28,7 +28,7 @@ impl<'a> ClientCrypto<'a> { } #[cfg(feature = "internal")] - pub async fn get_user_encryption_key(&mut self) -> Result { + pub async fn get_user_encryption_key(&mut self) -> Result { get_user_encryption_key(self.client).await } diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 214643023..b8891aa09 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use bitwarden_crypto::{AsymmetricEncString, EncString}; #[cfg(feature = "internal")] -use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, MasterKey, SymmetricCryptoKey}; +use bitwarden_crypto::{ + KeyDecryptable, KeyEncryptable, MasterKey, SensitiveString, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -86,7 +88,7 @@ pub enum AuthRequestMethod { #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { - use bitwarden_crypto::DeviceKey; + use bitwarden_crypto::{DecryptedString, DeviceKey}; use crate::auth::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; @@ -105,7 +107,8 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ client.initialize_user_crypto(&password, user_key, private_key)?; } InitUserCryptoMethod::DecryptedKey { decrypted_user_key } => { - let user_key = decrypted_user_key.parse::()?; + let decrypted_user_key = DecryptedString::new(Box::new(decrypted_user_key)); + let user_key = SymmetricCryptoKey::try_from(decrypted_user_key)?; client.initialize_user_crypto_decrypted_key(user_key, private_key)?; } InitUserCryptoMethod::Pin { @@ -138,7 +141,8 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ protected_device_private_key, device_protected_user_key, } => { - let device_key = device_key.parse::()?; + let device_key = DecryptedString::new(Box::new(device_key)); + let device_key = DeviceKey::try_from(device_key)?; let user_key = device_key .decrypt_user_key(protected_device_private_key, device_protected_user_key)?; @@ -166,7 +170,7 @@ pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoReques } #[cfg(feature = "internal")] -pub async fn get_user_encryption_key(client: &mut Client) -> Result { +pub async fn get_user_encryption_key(client: &mut Client) -> Result { let user_key = client .get_encryption_settings()? .get_key(&None) @@ -299,7 +303,7 @@ pub(super) fn enroll_admin_password_reset( let key = enc.get_key(&None).ok_or(Error::VaultLocked)?; Ok(AsymmetricEncString::encrypt_rsa2048_oaep_sha1( - &key.to_vec(), + key.to_vec().expose(), &public_key, )?) } @@ -483,7 +487,7 @@ mod tests { #[cfg(feature = "internal")] #[test] fn test_enroll_admin_password_reset() { - use std::{num::NonZeroU32, ops::Deref}; + use std::num::NonZeroU32; use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_crypto::AsymmetricCryptoKey; @@ -516,10 +520,7 @@ mod tests { .get_encryption_settings() .unwrap() .get_key(&None) - .unwrap() - .to_vec() - .deref() - .clone(); - assert_eq!(decrypted, expected); + .unwrap(); + assert_eq!(&decrypted, expected.to_vec().expose()); } } diff --git a/crates/bitwarden/src/secrets_manager/state.rs b/crates/bitwarden/src/secrets_manager/state.rs index b2b6f6a8e..c677ab7e9 100644 --- a/crates/bitwarden/src/secrets_manager/state.rs +++ b/crates/bitwarden/src/secrets_manager/state.rs @@ -1,6 +1,6 @@ use std::{fmt::Debug, path::Path}; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable}; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SensitiveString}; use serde::{Deserialize, Serialize}; use crate::{ @@ -15,11 +15,11 @@ const STATE_VERSION: u32 = 1; pub struct ClientState { pub(crate) version: u32, pub(crate) token: String, - pub(crate) encryption_key: String, + pub(crate) encryption_key: SensitiveString, } impl ClientState { - pub fn new(token: String, encryption_key: String) -> Self { + pub fn new(token: String, encryption_key: SensitiveString) -> Self { Self { version: STATE_VERSION, token, diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index b23a9cbef..bf1eade70 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,6 +1,6 @@ use std::num::NonZeroU32; -use bitwarden_crypto::{AsymmetricEncString, EncString}; +use bitwarden_crypto::{AsymmetricEncString, EncString, SensitiveString}; use uuid::Uuid; use crate::UniffiCustomTypeConverter; @@ -12,6 +12,11 @@ uniffi::ffi_converter_forward!( bitwarden_crypto::UniFfiTag, crate::UniFfiTag ); +uniffi::ffi_converter_forward!( + SensitiveString, + bitwarden_crypto::UniFfiTag, + crate::UniFfiTag +); type DateTime = chrono::DateTime; uniffi::custom_type!(DateTime, std::time::SystemTime); diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 1ec6be6fe..a573e92b0 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -66,7 +66,12 @@ impl<'a> KeyEncryptable for Attachm // with it, and then encrypt the key with the cipher key let attachment_key = SymmetricCryptoKey::generate(rand::thread_rng()); let encrypted_contents = self.contents.encrypt_with_key(&attachment_key)?; - attachment.key = Some(attachment_key.to_vec().encrypt_with_key(ciphers_key)?); + attachment.key = Some( + attachment_key + .to_vec() + .expose() + .encrypt_with_key(ciphers_key)?, + ); Ok(AttachmentEncryptResult { attachment: attachment.encrypt_with_key(ciphers_key)?, @@ -136,7 +141,7 @@ impl TryFrom for Attachment #[cfg(test)] mod tests { use base64::{engine::general_purpose::STANDARD, Engine}; - use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; + use bitwarden_crypto::{EncString, KeyDecryptable, SensitiveString, SymmetricCryptoKey}; use crate::vault::{ cipher::cipher::{CipherRepromptType, CipherType}, @@ -145,7 +150,7 @@ mod tests { #[test] fn test_attachment_key() { - let user_key : SymmetricCryptoKey = "w2LO+nwV4oxwswVYCxlOfRUseXfvU03VzvKQHrqeklPgiMZrspUe6sOBToCnDn9Ay0tuCBn8ykVVRb7PWhub2Q==".parse().unwrap(); + let user_key : SymmetricCryptoKey = SensitiveString::test("w2LO+nwV4oxwswVYCxlOfRUseXfvU03VzvKQHrqeklPgiMZrspUe6sOBToCnDn9Ay0tuCBn8ykVVRb7PWhub2Q==").try_into().unwrap(); let attachment = Attachment { id: None, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index f0138beb9..5df26ab34 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -308,7 +308,7 @@ impl CipherView { let new_key = SymmetricCryptoKey::generate(rand::thread_rng()); - self.key = Some(new_key.to_vec().encrypt_with_key(key)?); + self.key = Some(new_key.to_vec().expose().encrypt_with_key(key)?); Ok(()) } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 144933899..b6351baa1 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -394,7 +394,7 @@ mod tests { // Get the send key let send_key = Send::get_key(&send_key, k).unwrap(); let send_key_b64 = send_key.to_base64(); - assert_eq!(send_key_b64, "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); + assert_eq!(send_key_b64.expose(), "IR9ImHGm6rRuIjiN7csj94bcZR5WYTJj5GtNfx33zm6tJCHUl+QZlpNPba8g2yn70KnOHsAODLcR0um6E3MAlg=="); } fn build_encryption_settings() -> EncryptionSettings { diff --git a/crates/memory-testing/src/bin/analyze-dumps.rs b/crates/memory-testing/src/bin/analyze-dumps.rs index fee72f2e5..9957bc1cd 100644 --- a/crates/memory-testing/src/bin/analyze-dumps.rs +++ b/crates/memory-testing/src/bin/analyze-dumps.rs @@ -115,9 +115,7 @@ fn main() -> io::Result<()> { mac_final_pos.is_empty(), ); - // TODO: At the moment we are not zeroizing the base64 key in from_str, so this test is - // ignored - add_row( + error |= add_row( &mut table, format!("Symm. Key in Base64, case {}", idx), &b64_initial_pos, diff --git a/crates/memory-testing/src/main.rs b/crates/memory-testing/src/main.rs index 96e4ae175..ee781683c 100644 --- a/crates/memory-testing/src/main.rs +++ b/crates/memory-testing/src/main.rs @@ -1,6 +1,6 @@ -use std::{env, io::Read, path::Path, process, str::FromStr}; +use std::{env, io::Read, path::Path, process}; -use bitwarden_crypto::SymmetricCryptoKey; +use bitwarden_crypto::{SensitiveString, SymmetricCryptoKey}; fn wait_for_dump() { println!("Waiting for dump..."); @@ -22,8 +22,9 @@ fn main() { let mut symmetric_keys = Vec::new(); let mut symmetric_keys_as_vecs = Vec::new(); - for case in &cases.symmetric_key { - let key = SymmetricCryptoKey::from_str(&case.key).unwrap(); + for case in cases.symmetric_key { + let key = SensitiveString::new(Box::new(case.key)); + let key = SymmetricCryptoKey::try_from(key).unwrap(); symmetric_keys_as_vecs.push(key.to_vec()); symmetric_keys.push(key); } From 0b3f17504c4d1766cfba918819f02db057149f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 1 Apr 2024 16:55:01 +0200 Subject: [PATCH 352/378] Add require! macro to include field information in MissingFields error (#686) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Previously the MissingFields error didn't contain any usable information, plus it was unwieldy to use. With the use of a simple macro we can improve the error messaging and also simplify the error handling code. --- crates/bitwarden/src/admin_console/policy.rs | 10 +++---- .../bitwarden/src/auth/login/access_token.rs | 6 ++-- crates/bitwarden/src/auth/login/api_key.rs | 10 ++----- .../bitwarden/src/auth/login/auth_request.rs | 12 ++++---- crates/bitwarden/src/auth/login/password.rs | 10 ++----- crates/bitwarden/src/error.rs | 18 ++++++++++-- crates/bitwarden/src/platform/domain.rs | 8 ++--- .../src/platform/get_user_api_key.rs | 8 ++--- crates/bitwarden/src/platform/sync.rs | 29 +++++++++---------- .../src/secrets_manager/projects/delete.rs | 4 +-- .../projects/project_response.rs | 20 ++++--------- .../src/secrets_manager/secrets/delete.rs | 4 +-- .../src/secrets_manager/secrets/list.rs | 10 +++---- .../secrets/secret_response.rs | 28 +++++------------- crates/bitwarden/src/tool/exporters/mod.rs | 12 ++++---- crates/bitwarden/src/vault/cipher/cipher.rs | 10 +++---- crates/bitwarden/src/vault/cipher/field.rs | 4 +-- .../bitwarden/src/vault/cipher/linked_id.rs | 2 +- crates/bitwarden/src/vault/cipher/login.rs | 18 ++++++------ .../bitwarden/src/vault/cipher/secure_note.rs | 4 +-- crates/bitwarden/src/vault/collection.rs | 6 ++-- crates/bitwarden/src/vault/folder.rs | 6 ++-- crates/bitwarden/src/vault/send.rs | 16 +++++----- 23 files changed, 116 insertions(+), 139 deletions(-) diff --git a/crates/bitwarden/src/admin_console/policy.rs b/crates/bitwarden/src/admin_console/policy.rs index 7e87b8623..d8ed0b761 100644 --- a/crates/bitwarden/src/admin_console/policy.rs +++ b/crates/bitwarden/src/admin_console/policy.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] pub struct Policy { @@ -41,11 +41,11 @@ impl TryFrom for Policy { fn try_from(policy: PolicyResponseModel) -> Result { Ok(Self { - id: policy.id.ok_or(Error::MissingFields)?, - organization_id: policy.organization_id.ok_or(Error::MissingFields)?, - r#type: policy.r#type.ok_or(Error::MissingFields)?.into(), + id: require!(policy.id), + organization_id: require!(policy.organization_id), + r#type: require!(policy.r#type).into(), data: policy.data, - enabled: policy.enabled.ok_or(Error::MissingFields)?, + enabled: require!(policy.enabled), }) } } diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index a8c017009..cca52512b 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -14,7 +14,7 @@ use crate::{ AccessToken, JWTToken, }, client::{LoginMethod, ServiceAccountLoginMethod}, - error::{Error, Result}, + error::{require, Error, Result}, secrets_manager::state::{self, ClientState}, Client, }; @@ -69,9 +69,7 @@ pub(crate) async fn login_access_token( let access_token_obj: JWTToken = r.access_token.parse()?; // This should always be Some() when logging in with an access token - let organization_id = access_token_obj - .organization - .ok_or(Error::MissingFields)? + let organization_id = require!(access_token_obj.organization) .parse() .map_err(|_| Error::InvalidResponse)?; diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index 72d05897a..5d7fdcd96 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -9,7 +9,7 @@ use crate::{ JWTToken, }, client::{LoginMethod, UserLoginMethod}, - error::{Error, Result}, + error::{require, Result}, Client, }; @@ -44,12 +44,8 @@ pub(crate) async fn login_api_key( kdf, })); - let user_key: EncString = r.key.as_deref().ok_or(Error::MissingFields)?.parse()?; - let private_key: EncString = r - .private_key - .as_deref() - .ok_or(Error::MissingFields)? - .parse()?; + let user_key: EncString = require!(r.key.as_deref()).parse()?; + let private_key: EncString = require!(r.private_key.as_deref()).parse()?; client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs index ee2aef254..887809e4b 100644 --- a/crates/bitwarden/src/auth/login/auth_request.rs +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -13,7 +13,7 @@ use crate::{ auth_request::new_auth_request, }, client::{LoginMethod, UserLoginMethod}, - error::{Error, Result}, + error::{require, Result}, mobile::crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest}, Client, }; @@ -50,7 +50,7 @@ pub(crate) async fn send_new_auth_request( fingerprint: auth.fingerprint, email, device_identifier, - auth_request_id: res.id.ok_or(Error::MissingFields)?, + auth_request_id: require!(res.id), access_code: auth.access_code, private_key: auth.private_key, }) @@ -103,11 +103,11 @@ pub(crate) async fn complete_auth_request( let method = match res.master_password_hash { Some(_) => AuthRequestMethod::MasterKey { - protected_master_key: res.key.ok_or(Error::MissingFields)?.parse()?, - auth_request_key: r.key.ok_or(Error::MissingFields)?.parse()?, + protected_master_key: require!(res.key).parse()?, + auth_request_key: require!(r.key).parse()?, }, None => AuthRequestMethod::UserKey { - protected_user_key: res.key.ok_or(Error::MissingFields)?.parse()?, + protected_user_key: require!(res.key).parse()?, }, }; @@ -116,7 +116,7 @@ pub(crate) async fn complete_auth_request( .initialize_user_crypto(InitUserCryptoRequest { kdf_params: kdf, email: auth_req.email, - private_key: r.private_key.ok_or(Error::MissingFields)?, + private_key: require!(r.private_key), method: InitUserCryptoMethod::AuthRequest { request_private_key: auth_req.private_key, method, diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 9fa62a566..8ae9daebc 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -24,7 +24,7 @@ pub(crate) async fn login_password( ) -> Result { use bitwarden_crypto::{EncString, HashPurpose}; - use crate::{auth::determine_password_hash, client::UserLoginMethod, error::Error}; + use crate::{auth::determine_password_hash, client::UserLoginMethod, error::require}; info!("password logging in"); debug!("{:#?}, {:#?}", client, input); @@ -49,12 +49,8 @@ pub(crate) async fn login_password( kdf: input.kdf.to_owned(), })); - let user_key: EncString = r.key.as_deref().ok_or(Error::MissingFields)?.parse()?; - let private_key: EncString = r - .private_key - .as_deref() - .ok_or(Error::MissingFields)? - .parse()?; + let user_key: EncString = require!(r.key.as_deref()).parse()?; + let private_key: EncString = require!(r.private_key.as_deref()).parse()?; client.initialize_user_crypto(&input.password, user_key, private_key)?; } diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index bd040e51b..59fae58d2 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -24,8 +24,8 @@ pub enum Error { #[error("The response received was invalid and could not be processed")] InvalidResponse, - #[error("The response received was missing some of the required fields")] - MissingFields, + #[error("The response received was missing some of the required fields: {0}")] + MissingFields(&'static str), #[error("Cryptography error, {0}")] Crypto(#[from] bitwarden_crypto::CryptoError), @@ -133,4 +133,18 @@ macro_rules! impl_bitwarden_error { impl_bitwarden_error!(ApiError); impl_bitwarden_error!(IdentityError); +/// This macro is used to require that a value is present or return an error otherwise. +/// It is equivalent to using `val.ok_or(Error::MissingFields)?`, but easier to use and +/// with a more descriptive error message. +/// Note that this macro will return early from the function if the value is not present. +macro_rules! require { + ($val:expr) => { + match $val { + Some(val) => val, + None => return Err($crate::error::Error::MissingFields(stringify!($val))), + } + }; +} +pub(crate) use require; + pub type Result = std::result::Result; diff --git a/crates/bitwarden/src/platform/domain.rs b/crates/bitwarden/src/platform/domain.rs index c903dd5a5..482cb1f59 100644 --- a/crates/bitwarden/src/platform/domain.rs +++ b/crates/bitwarden/src/platform/domain.rs @@ -1,7 +1,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] pub struct GlobalDomains { @@ -15,9 +15,9 @@ impl TryFrom for GlobalDomains { fn try_from(global_domains: bitwarden_api_api::models::GlobalDomains) -> Result { Ok(Self { - r#type: global_domains.r#type.ok_or(Error::MissingFields)?, - domains: global_domains.domains.ok_or(Error::MissingFields)?, - excluded: global_domains.excluded.ok_or(Error::MissingFields)?, + r#type: require!(global_domains.r#type), + domains: require!(global_domains.domains), + excluded: require!(global_domains.excluded), }) } } diff --git a/crates/bitwarden/src/platform/get_user_api_key.rs b/crates/bitwarden/src/platform/get_user_api_key.rs index 2eaa21894..3e408d926 100644 --- a/crates/bitwarden/src/platform/get_user_api_key.rs +++ b/crates/bitwarden/src/platform/get_user_api_key.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; use super::SecretVerificationRequest; use crate::{ client::{LoginMethod, UserLoginMethod}, - error::{Error, Result}, + error::{require, Error, Result}, Client, }; @@ -75,9 +75,7 @@ pub struct UserApiKeyResponse { impl UserApiKeyResponse { pub(crate) fn process_response(response: ApiKeyResponseModel) -> Result { - match response.api_key { - Some(api_key) => Ok(UserApiKeyResponse { api_key }), - None => Err(Error::MissingFields), - } + let api_key = require!(response.api_key); + Ok(UserApiKeyResponse { api_key }) } } diff --git a/crates/bitwarden/src/platform/sync.rs b/crates/bitwarden/src/platform/sync.rs index c1a039137..5a5c6ee82 100644 --- a/crates/bitwarden/src/platform/sync.rs +++ b/crates/bitwarden/src/platform/sync.rs @@ -9,7 +9,7 @@ use super::domain::GlobalDomains; use crate::{ admin_console::Policy, client::{encryption_settings::EncryptionSettings, Client}, - error::{Error, Result}, + error::{require, Error, Result}, vault::{Cipher, Collection, Folder}, }; @@ -25,10 +25,7 @@ pub(crate) async fn sync(client: &mut Client, input: &SyncRequest) -> Result = sync - .profile - .as_ref() - .ok_or(Error::MissingFields)? + let org_keys: Vec<_> = require!(sync.profile.as_ref()) .organizations .as_deref() .unwrap_or_default() @@ -86,8 +83,8 @@ impl SyncResponse { response: SyncResponseModel, enc: &EncryptionSettings, ) -> Result { - let profile = *response.profile.ok_or(Error::MissingFields)?; - let ciphers = response.ciphers.ok_or(Error::MissingFields)?; + let profile = require!(response.profile); + let ciphers = require!(response.ciphers); fn try_into_iter(iter: In) -> Result where @@ -99,13 +96,13 @@ impl SyncResponse { } Ok(SyncResponse { - profile: ProfileResponse::process_response(profile, enc)?, - folders: try_into_iter(response.folders.ok_or(Error::MissingFields)?)?, - collections: try_into_iter(response.collections.ok_or(Error::MissingFields)?)?, + profile: ProfileResponse::process_response(*profile, enc)?, + folders: try_into_iter(require!(response.folders))?, + collections: try_into_iter(require!(response.collections))?, ciphers: try_into_iter(ciphers)?, domains: response.domains.map(|d| (*d).try_into()).transpose()?, - policies: try_into_iter(response.policies.ok_or(Error::MissingFields)?)?, - sends: try_into_iter(response.sends.ok_or(Error::MissingFields)?)?, + policies: try_into_iter(require!(response.policies))?, + sends: try_into_iter(require!(response.sends))?, }) } } @@ -115,7 +112,7 @@ impl ProfileOrganizationResponse { response: ProfileOrganizationResponseModel, ) -> Result { Ok(ProfileOrganizationResponse { - id: response.id.ok_or(Error::MissingFields)?, + id: require!(response.id), }) } } @@ -126,9 +123,9 @@ impl ProfileResponse { _enc: &EncryptionSettings, ) -> Result { Ok(ProfileResponse { - id: response.id.ok_or(Error::MissingFields)?, - name: response.name.ok_or(Error::MissingFields)?, - email: response.email.ok_or(Error::MissingFields)?, + id: require!(response.id), + name: require!(response.name), + email: require!(response.email), //key: response.key, //private_key: response.private_key, organizations: response diff --git a/crates/bitwarden/src/secrets_manager/projects/delete.rs b/crates/bitwarden/src/secrets_manager/projects/delete.rs index 55f792669..05c808c7e 100644 --- a/crates/bitwarden/src/secrets_manager/projects/delete.rs +++ b/crates/bitwarden/src/secrets_manager/projects/delete.rs @@ -7,7 +7,7 @@ use uuid::Uuid; use crate::{ client::Client, - error::{Error, Result}, + error::{require, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -62,7 +62,7 @@ impl ProjectDeleteResponse { response: BulkDeleteResponseModel, ) -> Result { Ok(ProjectDeleteResponse { - id: response.id.ok_or(Error::MissingFields)?, + id: require!(response.id), error: response.error, }) } diff --git a/crates/bitwarden/src/secrets_manager/projects/project_response.rs b/crates/bitwarden/src/secrets_manager/projects/project_response.rs index 1e6f6a158..af67df9ab 100644 --- a/crates/bitwarden/src/secrets_manager/projects/project_response.rs +++ b/crates/bitwarden/src/secrets_manager/projects/project_response.rs @@ -7,7 +7,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - error::{Error, Result}, + error::{require, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -25,27 +25,19 @@ impl ProjectResponse { response: ProjectResponseModel, enc: &EncryptionSettings, ) -> Result { - let organization_id = response.organization_id.ok_or(Error::MissingFields)?; + let organization_id = require!(response.organization_id); - let name = response - .name - .ok_or(Error::MissingFields)? + let name = require!(response.name) .parse::()? .decrypt(enc, &Some(organization_id))?; Ok(ProjectResponse { - id: response.id.ok_or(Error::MissingFields)?, + id: require!(response.id), organization_id, name, - creation_date: response - .creation_date - .ok_or(Error::MissingFields)? - .parse()?, - revision_date: response - .revision_date - .ok_or(Error::MissingFields)? - .parse()?, + creation_date: require!(response.creation_date).parse()?, + revision_date: require!(response.revision_date).parse()?, }) } } diff --git a/crates/bitwarden/src/secrets_manager/secrets/delete.rs b/crates/bitwarden/src/secrets_manager/secrets/delete.rs index 19337e7a1..f3fe264e1 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/delete.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/delete.rs @@ -7,7 +7,7 @@ use uuid::Uuid; use crate::{ client::Client, - error::{Error, Result}, + error::{require, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -62,7 +62,7 @@ impl SecretDeleteResponse { response: BulkDeleteResponseModel, ) -> Result { Ok(SecretDeleteResponse { - id: response.id.ok_or(Error::MissingFields)?, + id: require!(response.id), error: response.error, }) } diff --git a/crates/bitwarden/src/secrets_manager/secrets/list.rs b/crates/bitwarden/src/secrets_manager/secrets/list.rs index 7fa46d164..48a507667 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/list.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/list.rs @@ -8,7 +8,7 @@ use uuid::Uuid; use crate::{ client::{encryption_settings::EncryptionSettings, Client}, - error::{Error, Result}, + error::{require, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -93,16 +93,14 @@ impl SecretIdentifierResponse { response: SecretsWithProjectsInnerSecret, enc: &EncryptionSettings, ) -> Result { - let organization_id = response.organization_id.ok_or(Error::MissingFields)?; + let organization_id = require!(response.organization_id); - let key = response - .key - .ok_or(Error::MissingFields)? + let key = require!(response.key) .parse::()? .decrypt(enc, &Some(organization_id))?; Ok(SecretIdentifierResponse { - id: response.id.ok_or(Error::MissingFields)?, + id: require!(response.id), organization_id, key, }) diff --git a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs index fe1a4d342..ffaa7f7e0 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs @@ -9,7 +9,7 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - error::{Error, Result}, + error::{require, Result}, }; #[derive(Serialize, Deserialize, Debug, JsonSchema)] @@ -51,19 +51,13 @@ impl SecretResponse { ) -> Result { let org_id = response.organization_id; - let key = response - .key - .ok_or(Error::MissingFields)? + let key = require!(response.key) .parse::()? .decrypt(enc, &org_id)?; - let value = response - .value - .ok_or(Error::MissingFields)? + let value = require!(response.value) .parse::()? .decrypt(enc, &org_id)?; - let note = response - .note - .ok_or(Error::MissingFields)? + let note = require!(response.note) .parse::()? .decrypt(enc, &org_id)?; @@ -73,21 +67,15 @@ impl SecretResponse { .and_then(|p| p.id); Ok(SecretResponse { - id: response.id.ok_or(Error::MissingFields)?, - organization_id: org_id.ok_or(Error::MissingFields)?, + id: require!(response.id), + organization_id: require!(org_id), project_id: project, key, value, note, - creation_date: response - .creation_date - .ok_or(Error::MissingFields)? - .parse()?, - revision_date: response - .revision_date - .ok_or(Error::MissingFields)? - .parse()?, + creation_date: require!(response.creation_date).parse()?, + revision_date: require!(response.revision_date).parse()?, }) } } diff --git a/crates/bitwarden/src/tool/exporters/mod.rs b/crates/bitwarden/src/tool/exporters/mod.rs index 45bdfd3fd..2da6ac833 100644 --- a/crates/bitwarden/src/tool/exporters/mod.rs +++ b/crates/bitwarden/src/tool/exporters/mod.rs @@ -4,7 +4,7 @@ use schemars::JsonSchema; use crate::{ client::{LoginMethod, UserLoginMethod}, - error::{Error, Result}, + error::{require, Error, Result}, vault::{ login::LoginUriView, Cipher, CipherType, CipherView, Collection, FieldView, Folder, FolderView, SecureNoteType, @@ -83,7 +83,7 @@ impl TryFrom for bitwarden_exporters::Folder { fn try_from(value: FolderView) -> Result { Ok(Self { - id: value.id.ok_or(Error::MissingFields)?, + id: require!(value.id), name: value.name, }) } @@ -95,7 +95,7 @@ impl TryFrom for bitwarden_exporters::Cipher { fn try_from(value: CipherView) -> Result { let r = match value.r#type { CipherType::Login => { - let l = value.login.ok_or(Error::MissingFields)?; + let l = require!(value.login); bitwarden_exporters::CipherType::Login(Box::new(bitwarden_exporters::Login { username: l.username, password: l.password, @@ -118,7 +118,7 @@ impl TryFrom for bitwarden_exporters::Cipher { }, )), CipherType::Card => { - let c = value.card.ok_or(Error::MissingFields)?; + let c = require!(value.card); bitwarden_exporters::CipherType::Card(Box::new(bitwarden_exporters::Card { cardholder_name: c.cardholder_name, exp_month: c.exp_month, @@ -129,7 +129,7 @@ impl TryFrom for bitwarden_exporters::Cipher { })) } CipherType::Identity => { - let i = value.identity.ok_or(Error::MissingFields)?; + let i = require!(value.identity); bitwarden_exporters::CipherType::Identity(Box::new(bitwarden_exporters::Identity { title: i.title, first_name: i.first_name, @@ -154,7 +154,7 @@ impl TryFrom for bitwarden_exporters::Cipher { }; Ok(Self { - id: value.id.ok_or(Error::MissingFields)?, + id: require!(value.id), folder_id: value.folder_id, name: value.name, notes: value.notes, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 5df26ab34..fa85b5969 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -15,7 +15,7 @@ use super::{ login, secure_note, }; use crate::{ - error::{Error, Result}, + error::{require, Error, Result}, vault::password_history, }; @@ -384,9 +384,9 @@ impl TryFrom for Cipher { organization_id: cipher.organization_id, folder_id: cipher.folder_id, collection_ids: cipher.collection_ids.unwrap_or_default(), - name: EncString::try_from_optional(cipher.name)?.ok_or(Error::MissingFields)?, + name: require!(EncString::try_from_optional(cipher.name)?), notes: EncString::try_from_optional(cipher.notes)?, - r#type: cipher.r#type.ok_or(Error::MissingFields)?.into(), + r#type: require!(cipher.r#type).into(), login: cipher.login.map(|l| (*l).try_into()).transpose()?, identity: cipher.identity.map(|i| (*i).try_into()).transpose()?, card: cipher.card.map(|c| (*c).try_into()).transpose()?, @@ -412,9 +412,9 @@ impl TryFrom for Cipher { .password_history .map(|p| p.into_iter().map(|p| p.try_into()).collect()) .transpose()?, - creation_date: cipher.creation_date.ok_or(Error::MissingFields)?.parse()?, + creation_date: require!(cipher.creation_date).parse()?, deleted_date: cipher.deleted_date.map(|d| d.parse()).transpose()?, - revision_date: cipher.revision_date.ok_or(Error::MissingFields)?.parse()?, + revision_date: require!(cipher.revision_date).parse()?, key: EncString::try_from_optional(cipher.key)?, }) } diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 25a318d6f..1f18a9537 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use super::linked_id::LinkedIdType; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -70,7 +70,7 @@ impl TryFrom for Field { Ok(Self { name: EncString::try_from_optional(model.name)?, value: EncString::try_from_optional(model.value)?, - r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + r#type: require!(model.r#type).into(), linked_id: model .linked_id .map(|id| (id as u32).try_into()) diff --git a/crates/bitwarden/src/vault/cipher/linked_id.rs b/crates/bitwarden/src/vault/cipher/linked_id.rs index 77429438e..b52d756c6 100644 --- a/crates/bitwarden/src/vault/cipher/linked_id.rs +++ b/crates/bitwarden/src/vault/cipher/linked_id.rs @@ -112,7 +112,7 @@ impl TryFrom for LinkedIdType { 416 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FirstName)), 417 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::LastName)), 418 => Ok(LinkedIdType::Identity(IdentityLinkedIdType::FullName)), - _ => Err(Error::MissingFields), + _ => Err(Error::MissingFields("LinkedIdType")), } } } diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index e5731dbee..aed691d9a 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -8,7 +8,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -222,22 +222,22 @@ impl TryFrom for Fido2Cre fn try_from(value: bitwarden_api_api::models::CipherFido2CredentialModel) -> Result { Ok(Self { - credential_id: value.credential_id.ok_or(Error::MissingFields)?.parse()?, - key_type: value.key_type.ok_or(Error::MissingFields)?.parse()?, - key_algorithm: value.key_algorithm.ok_or(Error::MissingFields)?.parse()?, - key_curve: value.key_curve.ok_or(Error::MissingFields)?.parse()?, - key_value: value.key_value.ok_or(Error::MissingFields)?.parse()?, - rp_id: value.rp_id.ok_or(Error::MissingFields)?.parse()?, + credential_id: require!(value.credential_id).parse()?, + key_type: require!(value.key_type).parse()?, + key_algorithm: require!(value.key_algorithm).parse()?, + key_curve: require!(value.key_curve).parse()?, + key_value: require!(value.key_value).parse()?, + rp_id: require!(value.rp_id).parse()?, user_handle: EncString::try_from_optional(value.user_handle) .ok() .flatten(), user_name: EncString::try_from_optional(value.user_name).ok().flatten(), - counter: value.counter.ok_or(Error::MissingFields)?.parse()?, + counter: require!(value.counter).parse()?, rp_name: EncString::try_from_optional(value.rp_name).ok().flatten(), user_display_name: EncString::try_from_optional(value.user_display_name) .ok() .flatten(), - discoverable: value.discoverable.ok_or(Error::MissingFields)?.parse()?, + discoverable: require!(value.discoverable).parse()?, creation_date: value.creation_date.parse()?, }) } diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index eba4ea2fb..ebcbc3fa4 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -4,7 +4,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -48,7 +48,7 @@ impl TryFrom for SecureNote { fn try_from(model: CipherSecureNoteModel) -> Result { Ok(Self { - r#type: model.r#type.map(|t| t.into()).ok_or(Error::MissingFields)?, + r#type: require!(model.r#type).into(), }) } } diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index d20e5d729..ce881cb98 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -6,7 +6,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -66,8 +66,8 @@ impl TryFrom for Collection { fn try_from(collection: CollectionDetailsResponseModel) -> Result { Ok(Collection { id: collection.id, - organization_id: collection.organization_id.ok_or(Error::MissingFields)?, - name: collection.name.ok_or(Error::MissingFields)?.parse()?, + organization_id: require!(collection.organization_id), + name: require!(collection.name).parse()?, external_id: collection.external_id, hide_passwords: collection.hide_passwords.unwrap_or(false), read_only: collection.read_only.unwrap_or(false), diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index edd1cac42..65b18e54b 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -7,7 +7,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] @@ -55,8 +55,8 @@ impl TryFrom for Folder { fn try_from(folder: FolderResponseModel) -> Result { Ok(Folder { id: folder.id, - name: EncString::try_from_optional(folder.name)?.ok_or(Error::MissingFields)?, - revision_date: folder.revision_date.ok_or(Error::MissingFields)?.parse()?, + name: require!(EncString::try_from_optional(folder.name)?), + revision_date: require!(folder.revision_date).parse()?, }) } } diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index b6351baa1..37e6efcc9 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; -use crate::error::{Error, Result}; +use crate::error::{require, Error, Result}; const SEND_ITERATIONS: u32 = 100_000; @@ -308,19 +308,19 @@ impl TryFrom for Send { Ok(Send { id: send.id, access_id: send.access_id, - name: send.name.ok_or(Error::MissingFields)?.parse()?, + name: require!(send.name).parse()?, notes: EncString::try_from_optional(send.notes)?, - key: send.key.ok_or(Error::MissingFields)?.parse()?, + key: require!(send.key).parse()?, password: send.password, - r#type: send.r#type.ok_or(Error::MissingFields)?.into(), + r#type: require!(send.r#type).into(), file: send.file.map(|f| (*f).try_into()).transpose()?, text: send.text.map(|t| (*t).try_into()).transpose()?, max_access_count: send.max_access_count.map(|s| s as u32), - access_count: send.access_count.ok_or(Error::MissingFields)? as u32, + access_count: require!(send.access_count) as u32, disabled: send.disabled.unwrap_or(false), hide_email: send.hide_email.unwrap_or(false), - revision_date: send.revision_date.ok_or(Error::MissingFields)?.parse()?, - deletion_date: send.deletion_date.ok_or(Error::MissingFields)?.parse()?, + revision_date: require!(send.revision_date).parse()?, + deletion_date: require!(send.deletion_date).parse()?, expiration_date: send.expiration_date.map(|s| s.parse()).transpose()?, }) } @@ -341,7 +341,7 @@ impl TryFrom for SendFile { fn try_from(file: SendFileModel) -> Result { Ok(SendFile { id: file.id, - file_name: file.file_name.ok_or(Error::MissingFields)?.parse()?, + file_name: require!(file.file_name).parse()?, size: file.size.map(|v| v.to_string()), size_name: file.size_name, }) From a408745959de880a470f31d018f555ce4258a535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Tue, 2 Apr 2024 14:49:40 +0200 Subject: [PATCH 353/378] Publish docker CLI to ACR from feature branches (#692) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective ## Code changes - **.github/workflows/build-cli-docker.yml:** Push the docker image always and run build on PR, and branches push without specifying path of the change ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/build-cli-docker.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-cli-docker.yml b/.github/workflows/build-cli-docker.yml index 5cee3899b..19c5da2ca 100644 --- a/.github/workflows/build-cli-docker.yml +++ b/.github/workflows/build-cli-docker.yml @@ -3,13 +3,12 @@ name: Build bws Docker image on: push: - paths: - - "crates/bws/**" + branches: + - "main" + - "rc" + - "hotfix-rc" workflow_dispatch: pull_request: - paths: - - ".github/workflows/build-cli-docker.yml" - - "crates/bws/**" env: _AZ_REGISTRY: bitwardenprod.azurecr.io @@ -106,7 +105,7 @@ jobs: platforms: | linux/amd64, linux/arm64/v8 - push: ${{ env.is_publish_branch }} + push: true tags: ${{ steps.tag-list.outputs.tags }} secrets: | "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" From d318bbe201ea337509a77975916c74dbefe6afdb Mon Sep 17 00:00:00 2001 From: Matt Bishop Date: Thu, 4 Apr 2024 08:41:49 -0400 Subject: [PATCH 354/378] Exclude not exploitable state from scanner SARIF results (#694) ## Objective Implementation of https://github.com/bitwarden/template/pull/80. ## Before you submit - Please add **unit tests** where it makes sense to do so --- .github/workflows/scan.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 4bed1380f..dea39cfd6 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -40,7 +40,10 @@ jobs: base_uri: https://ast.checkmarx.net/ cx_client_id: ${{ secrets.CHECKMARX_CLIENT_ID }} cx_client_secret: ${{ secrets.CHECKMARX_SECRET }} - additional_params: --report-format sarif --output-path . ${{ env.INCREMENTAL }} + additional_params: | + --report-format sarif \ + --filter "state=TO_VERIFY;PROPOSED_NOT_EXPLOITABLE;CONFIRMED;URGENT" \ + --output-path . ${{ env.INCREMENTAL }} - name: Upload Checkmarx results to GitHub uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 From 423d971e2a5609dd26a86ee44fb4878d59feddbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Fri, 5 Apr 2024 13:55:59 +0200 Subject: [PATCH 355/378] Forbid unwrap usage outside of tests (#693) ## Type of change ``` - [ ] Bug fix - [ ] New feature development - [x] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Replaced uses of unwrap by ? or .expect(), and added lint to forbid them outside of tests. --- Cargo.toml | 3 +++ clippy.toml | 2 ++ crates/bitwarden-c/Cargo.toml | 3 +++ crates/bitwarden-c/src/c.rs | 7 +++--- crates/bitwarden-cli/Cargo.toml | 3 +++ crates/bitwarden-crypto/Cargo.toml | 5 +++- crates/bitwarden-crypto/src/aes.rs | 3 ++- .../src/enc_string/symmetric.rs | 6 ++--- crates/bitwarden-crypto/src/error.rs | 3 +++ crates/bitwarden-crypto/src/fingerprint.rs | 5 +++- .../src/keys/shareable_key.rs | 16 ++++++++----- crates/bitwarden-crypto/src/keys/utils.rs | 7 ++---- crates/bitwarden-exporters/Cargo.toml | 3 +++ crates/bitwarden-exporters/src/csv.rs | 2 +- crates/bitwarden-generators/Cargo.toml | 3 +++ crates/bitwarden-json/Cargo.toml | 3 +++ crates/bitwarden-json/src/response.rs | 2 +- crates/bitwarden-napi/Cargo.toml | 3 +++ crates/bitwarden-py/Cargo.toml | 3 +++ crates/bitwarden-uniffi/Cargo.toml | 3 +++ crates/bitwarden-wasm/Cargo.toml | 3 +++ crates/bitwarden/Cargo.toml | 3 +++ crates/bitwarden/src/auth/api/request/mod.rs | 2 +- .../bitwarden/src/auth/login/auth_request.rs | 2 +- crates/bitwarden/src/client/client.rs | 20 ++++++++++------ crates/bitwarden/src/util.rs | 8 +++---- crates/bitwarden/src/vault/totp.rs | 4 ++-- crates/bw/Cargo.toml | 3 +++ crates/bws/Cargo.toml | 3 +++ crates/bws/src/config.rs | 23 +++++++++++-------- crates/bws/src/main.rs | 2 +- crates/bws/src/render.rs | 10 ++++---- crates/bws/src/state.rs | 10 ++++---- 33 files changed, 123 insertions(+), 55 deletions(-) create mode 100644 clippy.toml diff --git a/Cargo.toml b/Cargo.toml index 64920d58c..7626e4cca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,9 @@ bitwarden-crypto = { path = "crates/bitwarden-crypto", version = "=0.1.0" } bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=0.1.0" } bitwarden-generators = { path = "crates/bitwarden-generators", version = "=0.1.0" } +[workspace.lints.clippy] +unwrap_used = "deny" + # Compile all dependencies with some optimizations when building this crate on debug # This slows down clean builds by about 50%, but the resulting binaries can be orders of magnitude faster # As clean builds won't occur very often, this won't slow down the development process diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000..a29e019ac --- /dev/null +++ b/clippy.toml @@ -0,0 +1,2 @@ +allow-unwrap-in-tests=true +allow-expect-in-tests=true diff --git a/crates/bitwarden-c/Cargo.toml b/crates/bitwarden-c/Cargo.toml index e3f966ee1..47d4ff5cd 100644 --- a/crates/bitwarden-c/Cargo.toml +++ b/crates/bitwarden-c/Cargo.toml @@ -21,3 +21,6 @@ bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } [dependencies] env_logger = ">=0.10.0, <0.12" + +[lints] +workspace = true diff --git a/crates/bitwarden-c/src/c.rs b/crates/bitwarden-c/src/c.rs index 934b20359..32abe3dc0 100644 --- a/crates/bitwarden-c/src/c.rs +++ b/crates/bitwarden-c/src/c.rs @@ -11,7 +11,8 @@ pub async extern "C" fn run_command( client_ptr: *const Client, ) -> *mut c_char { let client = unsafe { ffi_ref!(client_ptr) }; - let input_str = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr).to_bytes() }).unwrap(); + let input_str = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr) }.to_bytes()) + .expect("Input should be a valid string"); let result = client.run_command(input_str).await; match std::ffi::CString::new(result) { @@ -28,8 +29,8 @@ pub extern "C" fn init(c_str_ptr: *const c_char) -> *mut Client { if c_str_ptr.is_null() { box_ptr!(Client::new(None)) } else { - let input_string = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr).to_bytes() }) - .unwrap() + let input_string = str::from_utf8(unsafe { CStr::from_ptr(c_str_ptr) }.to_bytes()) + .expect("Input should be a valid string") .to_owned(); box_ptr!(Client::new(Some(input_string))) } diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index de5a4f9fc..b00479b2f 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -15,3 +15,6 @@ clap = { version = "4.5.1", features = ["derive"] } color-eyre = "0.6" inquire = "0.6.2" supports-color = "3.0.0" + +[lints] +workspace = true diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index ce0424c63..37359367b 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -21,7 +21,7 @@ mobile = ["dep:uniffi"] # Mobile-specific features [dependencies] aes = { version = ">=0.8.2, <0.9", features = ["zeroize"] } argon2 = { version = ">=0.5.0, <0.6", features = [ - "alloc", + "std", "zeroize", ], default-features = false } base64 = ">=0.21.2, <0.22" @@ -48,3 +48,6 @@ zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } [dev-dependencies] rand_chacha = "0.3.1" serde_json = ">=1.0.96, <2.0" + +[lints] +workspace = true diff --git a/crates/bitwarden-crypto/src/aes.rs b/crates/bitwarden-crypto/src/aes.rs index ee76f9936..dde588563 100644 --- a/crates/bitwarden-crypto/src/aes.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -149,7 +149,8 @@ pub fn decrypt_aes128_hmac( /// Generate a MAC using HMAC-SHA256. fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { - let mut hmac = PbkdfSha256Hmac::new_from_slice(mac_key).expect("HMAC can take key of any size"); + let mut hmac = + PbkdfSha256Hmac::new_from_slice(mac_key).expect("hmac new_from_slice should not fail"); hmac.update(iv); hmac.update(data); let mac: [u8; PBKDF_SHA256_HMAC_OUT_SIZE] = (*hmac.finalize().into_bytes()) diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index 0217a4b93..d312882d7 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -119,15 +119,15 @@ impl EncString { match enc_type { 0 => { check_length(buf, 18)?; - let iv = buf[1..17].try_into().unwrap(); + let iv = buf[1..17].try_into().expect("Valid length"); let data = buf[17..].to_vec(); Ok(EncString::AesCbc256_B64 { iv, data }) } 1 | 2 => { check_length(buf, 50)?; - let iv = buf[1..17].try_into().unwrap(); - let mac = buf[17..49].try_into().unwrap(); + let iv = buf[1..17].try_into().expect("Valid length"); + let mac = buf[17..49].try_into().expect("Valid length"); let data = buf[49..].to_vec(); if enc_type == 1 { diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index cf9a9b048..7cfb354d7 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -28,6 +28,9 @@ pub enum CryptoError { #[error("Fingerprint error, {0}")] FingerprintError(#[from] FingerprintError), + #[error("Argon2 error, {0}")] + ArgonError(#[from] argon2::Error), + #[error("Number is zero")] ZeroNumber, } diff --git a/crates/bitwarden-crypto/src/fingerprint.rs b/crates/bitwarden-crypto/src/fingerprint.rs index d3e69d577..b88435dbc 100644 --- a/crates/bitwarden-crypto/src/fingerprint.rs +++ b/crates/bitwarden-crypto/src/fingerprint.rs @@ -51,7 +51,10 @@ fn hash_word(hash: [u8; 32]) -> Result { let remainder = hash_number.clone() % EFF_LONG_WORD_LIST.len(); hash_number /= EFF_LONG_WORD_LIST.len(); - phrase.push(EFF_LONG_WORD_LIST[remainder.to_usize().unwrap()].to_string()); + let index = remainder + .to_usize() + .expect("Remainder is less than EFF_LONG_WORD_LIST.len()"); + phrase.push(EFF_LONG_WORD_LIST[index].to_string()); } Ok(phrase.join("-")) diff --git a/crates/bitwarden-crypto/src/keys/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs index 2b9ec837f..e84e05ca3 100644 --- a/crates/bitwarden-crypto/src/keys/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -2,9 +2,12 @@ use std::pin::Pin; use aes::cipher::typenum::U64; use generic_array::GenericArray; -use hmac::{Hmac, Mac}; +use hmac::Mac; -use crate::{keys::SymmetricCryptoKey, util::hkdf_expand}; +use crate::{ + keys::SymmetricCryptoKey, + util::{hkdf_expand, PbkdfSha256Hmac}, +}; /// Derive a shareable key using hkdf from secret and name. /// @@ -19,15 +22,16 @@ pub fn derive_shareable_key( // TODO: Are these the final `key` and `info` parameters or should we change them? I followed // the pattern used for sends - let res = Hmac::::new_from_slice(format!("bitwarden-{}", name).as_bytes()) - .unwrap() + let res = PbkdfSha256Hmac::new_from_slice(format!("bitwarden-{}", name).as_bytes()) + .expect("hmac new_from_slice should not fail") .chain_update(secret) .finalize() .into_bytes(); - let mut key: Pin>> = hkdf_expand(&res, info).unwrap(); + let mut key: Pin>> = + hkdf_expand(&res, info).expect("Input is a valid size"); - SymmetricCryptoKey::try_from(key.as_mut_slice()).unwrap() + SymmetricCryptoKey::try_from(key.as_mut_slice()).expect("Key is a valid size") } #[cfg(test)] diff --git a/crates/bitwarden-crypto/src/keys/utils.rs b/crates/bitwarden-crypto/src/keys/utils.rs index d83e212d0..a2df336e1 100644 --- a/crates/bitwarden-crypto/src/keys/utils.rs +++ b/crates/bitwarden-crypto/src/keys/utils.rs @@ -25,16 +25,13 @@ pub(super) fn derive_kdf_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result, ciphers: Vec) -> Result ResponseIntoString for Response { Ok(ser) => ser, Err(e) => { let error = Response::error(format!("Failed to serialize Response: {}", e)); - serde_json::to_string(&error).unwrap() + serde_json::to_string(&error).expect("Serialize should be infallible") } } } diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index 016401fe7..ea37593f2 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -32,3 +32,6 @@ napi-build = "2.1.0" [profile.release] lto = true + +[lints] +workspace = true diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index f66a0c11f..85af436bf 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -30,3 +30,6 @@ pyo3-asyncio = { version = "0.20.0", features = [ "attributes", "tokio-runtime", ] } + +[lints] +workspace = true diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 94572b991..2f0a4e175 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -33,3 +33,6 @@ bitwarden-generators = { workspace = true, features = ["mobile"] } [build-dependencies] uniffi = { version = "=0.26.1", features = ["build"] } + +[lints] +workspace = true diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index a688f12b6..4cf65905f 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -30,3 +30,6 @@ bitwarden-json = { path = "../bitwarden-json", features = [ [dev-dependencies] wasm-bindgen-test = "0.3.41" + +[lints] +workspace = true diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 4c9596b81..7d56b4c6e 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -84,3 +84,6 @@ rand_chacha = "0.3.1" tokio = { version = "1.36.0", features = ["rt", "macros"] } wiremock = "0.6.0" zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } + +[lints] +workspace = true diff --git a/crates/bitwarden/src/auth/api/request/mod.rs b/crates/bitwarden/src/auth/api/request/mod.rs index 2b5bde225..263d28357 100644 --- a/crates/bitwarden/src/auth/api/request/mod.rs +++ b/crates/bitwarden/src/auth/api/request/mod.rs @@ -54,7 +54,7 @@ async fn send_identity_connect_request( } let response = request - .body(serde_qs::to_string(&body).unwrap()) + .body(serde_qs::to_string(&body).expect("Serialize should be infallible")) .send() .await?; diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs index 887809e4b..0e9cb6795 100644 --- a/crates/bitwarden/src/auth/login/auth_request.rs +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -87,7 +87,7 @@ pub(crate) async fn complete_auth_request( if let IdentityTokenResponse::Authenticated(r) = response { let kdf = Kdf::PBKDF2 { - iterations: NonZeroU32::new(600_000).unwrap(), + iterations: NonZeroU32::new(600_000).expect("Non-zero number"), }; client.set_tokens( diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 68442d5d3..2374d6263 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -108,16 +108,17 @@ impl Client { client_builder } - let external_client = new_client_builder().build().unwrap(); + let external_client = new_client_builder().build().expect("Build should not fail"); let mut headers = header::HeaderMap::new(); headers.append( "Device-Type", - HeaderValue::from_str(&(settings.device_type as u8).to_string()).unwrap(), + HeaderValue::from_str(&(settings.device_type as u8).to_string()) + .expect("All numbers are valid ASCII"), ); let client_builder = new_client_builder().default_headers(headers); - let client = client_builder.build().unwrap(); + let client = client_builder.build().expect("Build should not fail"); let identity = bitwarden_api_identity::apis::configuration::Configuration { base_path: settings.identity_url, @@ -262,7 +263,10 @@ impl Client { user_key, private_key, )?); - Ok(self.encryption_settings.as_ref().unwrap()) + Ok(self + .encryption_settings + .as_ref() + .expect("Value is initialized previously")) } #[cfg(feature = "internal")] @@ -278,7 +282,7 @@ impl Client { Ok(self .encryption_settings .as_ref() - .expect("It was initialized on the previous line")) + .expect("Value is initialized previously")) } #[cfg(feature = "mobile")] @@ -307,7 +311,9 @@ impl Client { key: SymmetricCryptoKey, ) -> &EncryptionSettings { self.encryption_settings = Some(EncryptionSettings::new_single_key(key)); - self.encryption_settings.as_ref().unwrap() + self.encryption_settings + .as_ref() + .expect("Value is initialized previously") } #[cfg(feature = "internal")] @@ -321,7 +327,7 @@ impl Client { .ok_or(Error::VaultLocked)?; enc.set_org_keys(org_keys)?; - Ok(self.encryption_settings.as_ref().unwrap()) + Ok(&*enc) } } diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index f6568986d..5611b4077 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -6,19 +6,19 @@ use base64::{ }; pub fn default_pbkdf2_iterations() -> NonZeroU32 { - NonZeroU32::new(600_000).unwrap() + NonZeroU32::new(600_000).expect("Non-zero number") } #[cfg(feature = "internal")] pub fn default_argon2_iterations() -> NonZeroU32 { - NonZeroU32::new(3).unwrap() + NonZeroU32::new(3).expect("Non-zero number") } #[cfg(feature = "internal")] pub fn default_argon2_memory() -> NonZeroU32 { - NonZeroU32::new(64).unwrap() + NonZeroU32::new(64).expect("Non-zero number") } #[cfg(feature = "internal")] pub fn default_argon2_parallelism() -> NonZeroU32 { - NonZeroU32::new(4).unwrap() + NonZeroU32::new(4).expect("Non-zero number") } const INDIFFERENT: GeneralPurposeConfig = diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index 6ba754034..4586eda48 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -220,8 +220,8 @@ fn decode_b32(s: &str) -> Vec { let mut bytes = Vec::new(); for chunk in bits.as_bytes().chunks_exact(8) { - let byte_str = std::str::from_utf8(chunk).unwrap(); - let byte = u8::from_str_radix(byte_str, 2).unwrap(); + let byte_str = std::str::from_utf8(chunk).expect("The value is a valid string"); + let byte = u8::from_str_radix(byte_str, 2).expect("The value is a valid binary string"); bytes.push(byte); } diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index c54c35e28..ce69f87e9 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -26,3 +26,6 @@ bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } [dev-dependencies] tempfile = "3.10.0" + +[lints] +workspace = true diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index ccf143c47..491887f93 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -46,3 +46,6 @@ bitwarden = { workspace = true, features = ["secrets"] } [dev-dependencies] tempfile = "3.10.0" + +[lints] +workspace = true diff --git a/crates/bws/src/config.rs b/crates/bws/src/config.rs index 0ea1259f9..6cc471f97 100644 --- a/crates/bws/src/config.rs +++ b/crates/bws/src/config.rs @@ -46,23 +46,28 @@ impl ProfileKey { pub(crate) const FILENAME: &str = "config"; pub(crate) const DIRECTORY: &str = ".bws"; -pub(crate) fn get_config_path(config_file: Option<&Path>, ensure_folder_exists: bool) -> PathBuf { - let config_file = config_file.map(ToOwned::to_owned).unwrap_or_else(|| { - let base_dirs = BaseDirs::new().unwrap(); - base_dirs.home_dir().join(DIRECTORY).join(FILENAME) - }); +fn get_config_path(config_file: Option<&Path>, ensure_folder_exists: bool) -> Result { + let config_file = match config_file { + Some(path) => path.to_owned(), + None => { + let Some(base_dirs) = BaseDirs::new() else { + bail!("A valid home directory doesn't exist"); + }; + base_dirs.home_dir().join(DIRECTORY).join(FILENAME) + } + }; if ensure_folder_exists { if let Some(parent_folder) = config_file.parent() { - std::fs::create_dir_all(parent_folder).unwrap(); + std::fs::create_dir_all(parent_folder)?; } } - config_file + Ok(config_file) } pub(crate) fn load_config(config_file: Option<&Path>, must_exist: bool) -> Result { - let file = get_config_path(config_file, false); + let file = get_config_path(config_file, false)?; let content = match file.exists() { true => read_to_string(file), @@ -75,7 +80,7 @@ pub(crate) fn load_config(config_file: Option<&Path>, must_exist: bool) -> Resul } fn write_config(config: Config, config_file: Option<&Path>) -> Result<()> { - let file = get_config_path(config_file, true); + let file = get_config_path(config_file, true)?; let content = toml::to_string_pretty(&config)?; diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 6ed78f7b7..182e20679 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -328,7 +328,7 @@ async fn process_commands() -> Result<()> { let state_file_path = state::get_state_file_path( profile.and_then(|p| p.state_file_dir).map(Into::into), access_token_obj.access_token_id.to_string(), - ); + )?; let mut client = bitwarden::Client::new(settings); diff --git a/crates/bws/src/render.rs b/crates/bws/src/render.rs index f9563c81b..c92c78662 100644 --- a/crates/bws/src/render.rs +++ b/crates/bws/src/render.rs @@ -41,18 +41,20 @@ pub(crate) fn serialize_response, const N: usiz ) { match output { Output::JSON => { - let mut text = serde_json::to_string_pretty(&data).unwrap(); + let mut text = + serde_json::to_string_pretty(&data).expect("Serialize should be infallible"); // Yaml/table/tsv serializations add a newline at the end, so we do the same here for // consistency text.push('\n'); pretty_print("json", &text, color); } Output::YAML => { - let text = serde_yaml::to_string(&data).unwrap(); + let text = serde_yaml::to_string(&data).expect("Serialize should be infallible"); pretty_print("yaml", &text, color); } Output::Env => { - let valid_key_regex = regex::Regex::new("^[a-zA-Z_][a-zA-Z0-9_]*$").unwrap(); + let valid_key_regex = + regex::Regex::new("^[a-zA-Z_][a-zA-Z0-9_]*$").expect("regex is valid"); let mut commented_out = false; let mut text: Vec = data @@ -105,7 +107,7 @@ fn pretty_print(language: &str, data: &str, color: bool) { .input_from_bytes(data.as_bytes()) .language(language) .print() - .unwrap(); + .expect("Input is valid"); } else { print!("{}", data); } diff --git a/crates/bws/src/state.rs b/crates/bws/src/state.rs index ef0ef07e2..9c90da81f 100644 --- a/crates/bws/src/state.rs +++ b/crates/bws/src/state.rs @@ -1,18 +1,20 @@ use std::path::PathBuf; +use color_eyre::eyre::Result; + pub(crate) fn get_state_file_path( state_file_dir: Option, access_token_id: String, -) -> Option { +) -> Result> { if let Some(mut state_file_path) = state_file_dir { state_file_path.push(access_token_id); if let Some(parent_folder) = state_file_path.parent() { - std::fs::create_dir_all(parent_folder).unwrap(); + std::fs::create_dir_all(parent_folder)?; } - return Some(state_file_path); + return Ok(Some(state_file_path)); } - None + Ok(None) } From 014855cf17e194d45cb56cd8302aa5df900702d4 Mon Sep 17 00:00:00 2001 From: tangowithfoxtrot <5676771+tangowithfoxtrot@users.noreply.github.com> Date: Mon, 8 Apr 2024 07:04:50 -0700 Subject: [PATCH 356/378] [PM-7068] - Use a distroless container image for `bws` (#681) ## Type of change - [ ] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [x] Other ## Objective Addresses [PM-7068](https://bitwarden.atlassian.net/browse/PM-7068). Build the `bws` Docker image from an empty file system. This results in a much smaller Docker image (~16MB, uncompressed) with a smaller threat surface than bundling it with a distro. ## Code changes - **./crates/bws/Dockerfile:** Use `scratch` for the final build stage. This results in a distroless image that only contains our binary, the libraries that it depends on, and the CA certificates needed for SSL to work. The `ldd` line automatically determines what dependencies we need to copy over so we don't have to manually maintain a list of them. ## Before you submit - Please add **unit tests** where it makes sense to do so [PM-7068]: https://bitwarden.atlassian.net/browse/PM-7068?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- crates/bws/Dockerfile | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/bws/Dockerfile b/crates/bws/Dockerfile index 4f16f8e6c..cc9e1c481 100644 --- a/crates/bws/Dockerfile +++ b/crates/bws/Dockerfile @@ -15,27 +15,35 @@ COPY . /app # Build project WORKDIR /app/crates/bws -RUN cargo build --release +RUN cargo build --release --bin bws + +# Bundle bws dependencies +RUN mkdir /lib-bws +RUN ldd /app/target/release/bws | tr -s '[:blank:]' '\n' | grep '^/' | xargs -I % cp % /lib-bws + +# Make a HOME directory for the app stage +RUN mkdir -p /home/app ############################################### # App stage # ############################################### -FROM debian:bookworm-slim +FROM scratch ARG TARGETPLATFORM LABEL com.bitwarden.product="bitwarden" +# Set a HOME directory +COPY --from=build /home/app /home/app +ENV HOME=/home/app + # Copy built project from the build stage WORKDIR /usr/local/bin COPY --from=build /app/target/release/bws . -COPY --from=build /etc/ssl/certs /etc/ssl/certs - -# Create a non-root user -RUN useradd -ms /bin/bash app -# Switch to the non-root user -USER app +# Copy certs +COPY --from=build /etc/ssl/certs /etc/ssl/certs -WORKDIR /home/app +# Copy bws dependencies +COPY --from=build /lib-bws /lib ENTRYPOINT ["bws"] From 69d5104c0608900c0ea0294efc77c87167ae674b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 09:50:28 -0600 Subject: [PATCH 357/378] [deps]: Update bitwarden/gh-actions digest to 2e9a183 (#689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | bitwarden/gh-actions | action | digest | `4f37134` -> `2e9a183` | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/publish-php.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index 782ffee1d..2b716c893 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -86,7 +86,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -167,7 +167,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -247,7 +247,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@4f37134d838f21609c38cb56694d8605f176704c + uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope, From c272758b7211948fa51f2cf5a5982ed15e4768a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 09:57:42 -0600 Subject: [PATCH 358/378] [deps]: Update dtolnay/rust-toolchain digest to dc63535 (#690) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | dtolnay/rust-toolchain | action | digest | `be73d79` -> `dc63535` | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 8 ++++---- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-python-wheels.yml | 2 +- .github/workflows/build-rust-crates.yml | 4 ++-- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/memory-testing.yml | 2 +- .github/workflows/minimum-rust-version.yml | 2 +- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/rust-test.yml | 6 +++--- .github/workflows/version-bump.yml | 2 +- 15 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index cad899ef3..8bff66f33 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable @@ -70,7 +70,7 @@ jobs: fetch-depth: 0 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index e60928807..ad3386ddf 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -61,7 +61,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -151,7 +151,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -260,7 +260,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -411,7 +411,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index aa1cfdd16..3737d3767 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -61,7 +61,7 @@ jobs: cache-dependency-path: crates/bitwarden-napi/package-lock.json - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index 7ffc2f24f..1c0459dd6 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -71,7 +71,7 @@ jobs: node-version: 18 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 5d45b6f95..dc6db5c91 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -69,7 +69,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index 0db2d0cde..cacacf0e0 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 8db6e3c2e..084ed3cff 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: nightly targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index bd206b21e..5c62cee01 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 771b368f5..8767cba89 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/memory-testing.yml b/.github/workflows/memory-testing.yml index af5ef6b7c..1723644f2 100644 --- a/.github/workflows/memory-testing.yml +++ b/.github/workflows/memory-testing.yml @@ -30,7 +30,7 @@ jobs: sudo apt -y install gdb - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/minimum-rust-version.yml b/.github/workflows/minimum-rust-version.yml index d3eccf653..6213fed32 100644 --- a/.github/workflows/minimum-rust-version.yml +++ b/.github/workflows/minimum-rust-version.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: # Important: When updating this, make sure to update the Readme file # and also the `rust-version` field in all the `Cargo.toml`. diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index e3b2a1626..f6a52d5d1 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -137,7 +137,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index daf6dd622..3b42c3238 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -142,7 +142,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 8408dd1d7..06904ee3b 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable @@ -58,7 +58,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable components: llvm-tools @@ -87,7 +87,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable targets: wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 704bee01d..f94a51346 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable with: toolchain: stable From a9d90f2d9a733429efc178f5164f0d95e136ef8e Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 9 Apr 2024 13:23:11 +0200 Subject: [PATCH 359/378] Use same version for bitwarden crates (#663) Rather than maintaining separate versions for every crate let's keep them locked. That means the rust sdk packages will always have the same version. Unfortunately a side effect of this is that every package will be released even if that package hasn't changed. --- .github/workflows/version-bump.yml | 51 ++++-------------------- Cargo.lock | 12 +++--- Cargo.toml | 15 ++++--- crates/bitwarden-api-api/Cargo.toml | 2 +- crates/bitwarden-api-identity/Cargo.toml | 2 +- crates/bitwarden-cli/Cargo.toml | 2 +- crates/bitwarden-crypto/Cargo.toml | 2 +- crates/bitwarden-exporters/Cargo.toml | 2 +- crates/bitwarden-generators/Cargo.toml | 2 +- crates/bitwarden-json/Cargo.toml | 3 +- crates/bitwarden-napi/Cargo.toml | 7 ++-- crates/bitwarden-py/Cargo.toml | 3 +- crates/bitwarden-uniffi/Cargo.toml | 7 ++-- crates/bitwarden-wasm/Cargo.toml | 9 ++--- crates/bitwarden/Cargo.toml | 2 +- crates/bw/Cargo.toml | 5 +-- crates/bws/Cargo.toml | 3 +- crates/sdk-schemas/Cargo.toml | 7 ++-- 18 files changed, 48 insertions(+), 88 deletions(-) diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index f94a51346..8b4c33ee3 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -11,12 +11,7 @@ on: type: choice options: - bitwarden - - bitwarden-api-api - - bitwarden-api-identity - - bitwarden-crypto - - bitwarden-generators - - bitwarden-json - - cli + - bws - napi - python-sdk - ruby-sdk @@ -45,7 +40,7 @@ jobs: uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 - name: Install cargo-release - run: cargo install cargo-edit + run: cargo install cargo-edit --locked - name: Login to Azure - CI Subscription uses: Azure/login@e15b166166a8746d1a47596803bd8c1b595455cf # v1.6.0 @@ -103,49 +98,19 @@ jobs: - name: Bump napi crate Version if: ${{ inputs.project == 'napi' }} - run: cargo-set-version set-version -p bitwarden-napi ${{ inputs.version_number }} + run: cargo set-version -p bitwarden-napi ${{ inputs.version_number }} ### bitwarden - name: Bump bitwarden crate Version if: ${{ inputs.project == 'bitwarden' }} - run: cargo-set-version set-version -p bitwarden ${{ inputs.version_number }} + run: cargo set-version -p bitwarden ${{ inputs.version_number }} - ### bitwarden-api-api + ### bws - - name: Bump bitwarden-api-api crate Version - if: ${{ inputs.project == 'bitwarden-api-api' }} - run: cargo-set-version set-version -p bitwarden-api-api ${{ inputs.version_number }} - - ### bitwarden-api-identity - - - name: Bump bitwarden-api-identity crate Version - if: ${{ inputs.project == 'bitwarden-api-identity' }} - run: cargo-set-version set-version -p bitwarden-api-identity ${{ inputs.version_number }} - - ### bitwarden-crypto - - - name: Bump bitwarden-crypto crate Version - if: ${{ inputs.project == 'bitwarden-crypto' }} - run: cargo-set-version set-version -p bitwarden-crypto ${{ inputs.version_number }} - - ### bitwarden-generators - - - name: Bump bitwarden-generators crate Version - if: ${{ inputs.project == 'bitwarden-generators' }} - run: cargo-set-version set-version -p bitwarden-generators ${{ inputs.version_number }} - - ### cli - - - name: Bump cli Version - if: ${{ inputs.project == 'cli' }} - run: cargo-set-version set-version -p bws ${{ inputs.version_number }} - - ### bitwarden-json - - - name: Bump bitwarden-json crate Version - if: ${{ inputs.project == 'bitwarden-json' }} - run: cargo-set-version set-version -p bitwarden-json ${{ inputs.version_number }} + - name: Bump bws Version + if: ${{ inputs.project == 'bws' }} + run: cargo set-version -p bws ${{ inputs.version_number }} ### python - name: Bump python-sdk Version diff --git a/Cargo.lock b/Cargo.lock index dfa714cc6..b3538ccab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -363,7 +363,7 @@ dependencies = [ [[package]] name = "bitwarden-api-api" -version = "0.2.3" +version = "0.4.0" dependencies = [ "reqwest", "serde", @@ -376,7 +376,7 @@ dependencies = [ [[package]] name = "bitwarden-api-identity" -version = "0.2.3" +version = "0.4.0" dependencies = [ "reqwest", "serde", @@ -398,7 +398,7 @@ dependencies = [ [[package]] name = "bitwarden-cli" -version = "0.1.0" +version = "0.4.0" dependencies = [ "clap", "color-eyre", @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "bitwarden-crypto" -version = "0.1.0" +version = "0.4.0" dependencies = [ "aes", "argon2", @@ -438,7 +438,7 @@ dependencies = [ [[package]] name = "bitwarden-exporters" -version = "0.1.0" +version = "0.4.0" dependencies = [ "base64", "bitwarden-crypto", @@ -452,7 +452,7 @@ dependencies = [ [[package]] name = "bitwarden-generators" -version = "0.1.0" +version = "0.4.0" dependencies = [ "bitwarden-crypto", "rand", diff --git a/Cargo.toml b/Cargo.toml index 7626e4cca..75685a7bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ members = ["crates/*"] # Global settings for all crates should be defined here [workspace.package] +# Update using `cargo set-version -p bitwarden ` +version = "0.4.0" authors = ["Bitwarden Inc"] edition = "2021" # Note: Changing rust-version should be considered a breaking change @@ -15,12 +17,13 @@ keywords = ["bitwarden"] # Define dependencies that are expected to be consistent across all crates [workspace.dependencies] -bitwarden = { path = "crates/bitwarden", version = "0.4.0" } -bitwarden-api-api = { path = "crates/bitwarden-api-api", version = "0.2.3" } -bitwarden-api-identity = { path = "crates/bitwarden-api-identity", version = "=0.2.3" } -bitwarden-crypto = { path = "crates/bitwarden-crypto", version = "=0.1.0" } -bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=0.1.0" } -bitwarden-generators = { path = "crates/bitwarden-generators", version = "=0.1.0" } +bitwarden = { path = "crates/bitwarden", version = "=0.4.0" } +bitwarden-api-api = { path = "crates/bitwarden-api-api", version = "=0.4.0" } +bitwarden-api-identity = { path = "crates/bitwarden-api-identity", version = "=0.4.0" } +bitwarden-cli = { path = "crates/bitwarden-cli", version = "=0.4.0" } +bitwarden-crypto = { path = "crates/bitwarden-crypto", version = "=0.4.0" } +bitwarden-exporters = { path = "crates/bitwarden-exporters", version = "=0.4.0" } +bitwarden-generators = { path = "crates/bitwarden-generators", version = "=0.4.0" } [workspace.lints.clippy] unwrap_used = "deny" diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index 538d590ec..a06a0f0e5 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "bitwarden-api-api" -version = "0.2.3" description = """ Api bindings for the Bitwarden API. """ categories = ["api-bindings"] +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index 067d90648..e5a49efac 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "bitwarden-api-identity" -version = "0.2.3" description = """ Api bindings for the Bitwarden Identity API. """ categories = ["api-bindings"] +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-cli/Cargo.toml b/crates/bitwarden-cli/Cargo.toml index b00479b2f..69a21704c 100644 --- a/crates/bitwarden-cli/Cargo.toml +++ b/crates/bitwarden-cli/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bitwarden-cli" -version = "0.1.0" +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 37359367b..e42ca686f 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "bitwarden-crypto" -version = "0.1.0" description = """ Internal crate for the bitwarden crate. Do not use. """ +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-exporters/Cargo.toml b/crates/bitwarden-exporters/Cargo.toml index c43e4b274..fc118b922 100644 --- a/crates/bitwarden-exporters/Cargo.toml +++ b/crates/bitwarden-exporters/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "bitwarden-exporters" -version = "0.1.0" description = """ Internal crate for the bitwarden crate. Do not use. """ exclude = ["/resources"] +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index 82315b680..af8ce60aa 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "bitwarden-generators" -version = "0.1.0" description = """ Internal crate for the bitwarden crate. Do not use. """ +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bitwarden-json/Cargo.toml b/crates/bitwarden-json/Cargo.toml index 549b9040d..4981e8f4b 100644 --- a/crates/bitwarden-json/Cargo.toml +++ b/crates/bitwarden-json/Cargo.toml @@ -21,12 +21,11 @@ secrets = ["bitwarden/secrets"] # Secrets manager API [dependencies] async-lock = ">=3.3.0, <4.0" +bitwarden = { workspace = true } log = ">=0.4.18, <0.5" schemars = ">=0.8.12, <0.9" serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" -bitwarden = { workspace = true } - [lints] workspace = true diff --git a/crates/bitwarden-napi/Cargo.toml b/crates/bitwarden-napi/Cargo.toml index ea37593f2..16853dbbf 100644 --- a/crates/bitwarden-napi/Cargo.toml +++ b/crates/bitwarden-napi/Cargo.toml @@ -18,15 +18,14 @@ license-file.workspace = true crate-type = ["cdylib", "rlib"] [dependencies] +bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = [ + "secrets", +] } env_logger = "0.11.1" log = "0.4.20" napi = { version = "2", features = ["async"] } napi-derive = "2" -bitwarden-json = { path = "../bitwarden-json", version = "0.3.0", features = [ - "secrets", -] } - [build-dependencies] napi-build = "2.1.0" diff --git a/crates/bitwarden-py/Cargo.toml b/crates/bitwarden-py/Cargo.toml index 85af436bf..e9073d802 100644 --- a/crates/bitwarden-py/Cargo.toml +++ b/crates/bitwarden-py/Cargo.toml @@ -16,11 +16,10 @@ name = "bitwarden_py" crate-type = ["cdylib"] [dependencies] +bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } pyo3 = { version = "0.20.2", features = ["extension-module"] } pyo3-log = "0.9.0" -bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] } - [build-dependencies] pyo3-build-config = { version = "0.20.2" } diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 2f0a4e175..8dfddb820 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -19,6 +19,9 @@ bench = false [dependencies] async-lock = "3.3.0" +bitwarden = { workspace = true, features = ["mobile", "internal"] } +bitwarden-crypto = { workspace = true, features = ["mobile"] } +bitwarden-generators = { workspace = true, features = ["mobile"] } chrono = { version = ">=0.4.26, <0.5", features = [ "serde", "std", @@ -27,10 +30,6 @@ env_logger = "0.11.1" schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.26.1" -bitwarden = { workspace = true, features = ["mobile", "internal"] } -bitwarden-crypto = { workspace = true, features = ["mobile"] } -bitwarden-generators = { workspace = true, features = ["mobile"] } - [build-dependencies] uniffi = { version = "=0.26.1", features = ["build"] } diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index 4cf65905f..ff4cf13c3 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -15,6 +15,10 @@ keywords.workspace = true crate-type = ["cdylib"] [dependencies] +bitwarden-json = { path = "../bitwarden-json", features = [ + "secrets", + "internal", +] } console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.68" @@ -23,11 +27,6 @@ serde = { version = "1.0.196", features = ["derive"] } wasm-bindgen = { version = "0.2.91", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.41" -bitwarden-json = { path = "../bitwarden-json", features = [ - "secrets", - "internal", -] } - [dev-dependencies] wasm-bindgen-test = "0.3.41" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 7d56b4c6e..e064360c8 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "bitwarden" -version = "0.4.0" description = """ Bitwarden Secrets Manager SDK """ keywords = ["bitwarden", "secrets-manager"] +version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/crates/bw/Cargo.toml b/crates/bw/Cargo.toml index ce69f87e9..3fa5efd4a 100644 --- a/crates/bw/Cargo.toml +++ b/crates/bw/Cargo.toml @@ -14,6 +14,8 @@ repository.workspace = true license-file.workspace = true [dependencies] +bitwarden = { workspace = true, features = ["internal", "mobile"] } +bitwarden-cli = { workspace = true } clap = { version = "4.5.1", features = ["derive", "env"] } color-eyre = "0.6" env_logger = "0.11.1" @@ -21,9 +23,6 @@ inquire = "0.6.2" log = "0.4.20" tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } -bitwarden = { workspace = true, features = ["internal", "mobile"] } -bitwarden-cli = { path = "../bitwarden-cli", version = "0.1.0" } - [dev-dependencies] tempfile = "3.10.0" diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 491887f93..23f78cfd5 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -18,6 +18,7 @@ license-file.workspace = true bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } +bitwarden = { workspace = true, features = ["secrets"] } chrono = { version = "0.4.35", features = [ "clock", "std", @@ -42,8 +43,6 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread", "macros"] } toml = "0.8.10" uuid = { version = "^1.7.0", features = ["serde"] } -bitwarden = { workspace = true, features = ["secrets"] } - [dev-dependencies] tempfile = "3.10.0" diff --git a/crates/sdk-schemas/Cargo.toml b/crates/sdk-schemas/Cargo.toml index c4cc9139b..3c5e0d50b 100644 --- a/crates/sdk-schemas/Cargo.toml +++ b/crates/sdk-schemas/Cargo.toml @@ -20,10 +20,9 @@ internal = [ [dependencies] anyhow = "1.0.81" +bitwarden = { workspace = true } +bitwarden-json = { path = "../bitwarden-json" } +bitwarden-uniffi = { path = "../bitwarden-uniffi" } itertools = "0.12.1" schemars = { version = "0.8.16", features = ["preserve_order"] } serde_json = "1.0.113" - -bitwarden = { path = "../bitwarden" } -bitwarden-json = { path = "../bitwarden-json" } -bitwarden-uniffi = { path = "../bitwarden-uniffi" } From 8d09775a11c8a0a085ea2a3887d8510d198fd8e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:43:12 +0200 Subject: [PATCH 360/378] Bump h2 from 0.4.3 to 0.4.4 (#700) Bumps [h2](https://github.com/hyperium/h2) from 0.4.3 to 0.4.4.
Release notes

Sourced from h2's releases.

v0.4.4

Fixes

  • Limit number of CONTINUATION frames for misbehaving connections.

See https://seanmonstar.com/blog/hyper-http2-continuation-flood/ for more info.

Changelog

Sourced from h2's changelog.

0.4.4 (April 3, 2024)

  • Limit number of CONTINUATION frames for misbehaving connections.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=h2&package-manager=cargo&previous-version=0.4.3&new-version=0.4.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/bitwarden/sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3538ccab..cc24ecfc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1481,9 +1481,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" dependencies = [ "bytes", "fnv", From dac4751a22f4517e39350c72284fa7d80ad7fea9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 13:46:03 +0200 Subject: [PATCH 361/378] Bump follow-redirects from 1.15.5 to 1.15.6 (#701) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.5 to 1.15.6.
Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=follow-redirects&package-manager=npm_and_yarn&previous-version=1.15.5&new-version=1.15.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/bitwarden/sdk/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2c4b9b478..5728464b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -923,9 +923,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { From 1ccf11b664a6d5210a4a140438ccb5b3597e05c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Tue, 9 Apr 2024 14:28:19 +0200 Subject: [PATCH 362/378] [PM-6764] Move cipher to organization (#695) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Added function to allow moving a cipher to an organization, which requires reencrypting the cipher key if it has one. --- Cargo.lock | 1 + crates/bitwarden-uniffi/Cargo.toml | 1 + crates/bitwarden-uniffi/src/uniffi_support.rs | 2 + crates/bitwarden-uniffi/src/vault/ciphers.rs | 18 ++ .../src/mobile/vault/client_ciphers.rs | 11 ++ crates/bitwarden/src/vault/cipher/cipher.rs | 157 +++++++++++++----- languages/kotlin/doc.md | 26 ++- 7 files changed, 177 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc24ecfc1..47e2b9e9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -515,6 +515,7 @@ dependencies = [ "env_logger", "schemars", "uniffi", + "uuid", ] [[package]] diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 8dfddb820..90a106bce 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -29,6 +29,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [ env_logger = "0.11.1" schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.26.1" +uuid = ">=1.3.3, <2" [build-dependencies] uniffi = { version = "=0.26.1", features = ["build"] } diff --git a/crates/bitwarden-uniffi/src/uniffi_support.rs b/crates/bitwarden-uniffi/src/uniffi_support.rs index a49e347b6..f487dfaa0 100644 --- a/crates/bitwarden-uniffi/src/uniffi_support.rs +++ b/crates/bitwarden-uniffi/src/uniffi_support.rs @@ -1,4 +1,5 @@ use bitwarden_crypto::{AsymmetricEncString, EncString, SensitiveString}; +use uuid::Uuid; // Forward the type definitions to the main bitwarden crate type DateTime = chrono::DateTime; @@ -6,3 +7,4 @@ uniffi::ffi_converter_forward!(DateTime, bitwarden::UniFfiTag, crate::UniFfiTag) uniffi::ffi_converter_forward!(EncString, bitwarden::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(AsymmetricEncString, bitwarden::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(SensitiveString, bitwarden::UniFfiTag, crate::UniFfiTag); +uniffi::ffi_converter_forward!(Uuid, bitwarden::UniFfiTag, crate::UniFfiTag); diff --git a/crates/bitwarden-uniffi/src/vault/ciphers.rs b/crates/bitwarden-uniffi/src/vault/ciphers.rs index eb8543947..dcf224a38 100644 --- a/crates/bitwarden-uniffi/src/vault/ciphers.rs +++ b/crates/bitwarden-uniffi/src/vault/ciphers.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use bitwarden::vault::{Cipher, CipherListView, CipherView}; +use uuid::Uuid; use crate::{Client, Result}; @@ -47,4 +48,21 @@ impl ClientCiphers { .decrypt_list(ciphers) .await?) } + + /// Move a cipher to an organization, reencrypting the cipher key if necessary + pub async fn move_to_organization( + &self, + cipher: CipherView, + organization_id: Uuid, + ) -> Result { + Ok(self + .0 + .0 + .read() + .await + .vault() + .ciphers() + .move_to_organization(cipher, organization_id) + .await?) + } } diff --git a/crates/bitwarden/src/mobile/vault/client_ciphers.rs b/crates/bitwarden/src/mobile/vault/client_ciphers.rs index c35cf3080..71203374f 100644 --- a/crates/bitwarden/src/mobile/vault/client_ciphers.rs +++ b/crates/bitwarden/src/mobile/vault/client_ciphers.rs @@ -1,4 +1,5 @@ use bitwarden_crypto::{Decryptable, Encryptable, LocateKey}; +use uuid::Uuid; use super::client_vault::ClientVault; use crate::{ @@ -44,6 +45,16 @@ impl<'a> ClientCiphers<'a> { Ok(cipher_views) } + + pub async fn move_to_organization( + &self, + mut cipher_view: CipherView, + organization_id: Uuid, + ) -> Result { + let enc = self.client.get_encryption_settings()?; + cipher_view.move_to_organization(enc, organization_id)?; + Ok(cipher_view) + } } impl<'a> ClientVault<'a> { diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index fa85b5969..f245fdc3a 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,6 +1,6 @@ use bitwarden_api_api::models::CipherDetailsResponseModel; use bitwarden_crypto::{ - CryptoError, EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, + CryptoError, EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, SensitiveVec, SymmetricCryptoKey, }; use chrono::{DateTime, Utc}; @@ -325,6 +325,29 @@ impl CipherView { uris.retain(|u| u.is_checksum_valid()); } } + + pub fn move_to_organization( + &mut self, + enc: &dyn KeyContainer, + organization_id: Uuid, + ) -> Result<()> { + // If the cipher has a key, we need to re-encrypt it with the new organization key + if let Some(cipher_key) = &mut self.key { + let old_key = enc + .get_key(&self.organization_id) + .ok_or(Error::VaultLocked)?; + + let new_key = enc + .get_key(&Some(organization_id)) + .ok_or(Error::VaultLocked)?; + + let dec_cipher_key = SensitiveVec::new(Box::new(cipher_key.decrypt_with_key(old_key)?)); + *cipher_key = dec_cipher_key.expose().encrypt_with_key(new_key)?; + } + + self.organization_id = Some(organization_id); + Ok(()) + } } impl KeyDecryptable for Cipher { @@ -443,49 +466,51 @@ impl From for CipherRepromptType #[cfg(test)] mod tests { + use std::collections::HashMap; + use super::*; + fn generate_cipher() -> CipherView { + CipherView { + r#type: CipherType::Login, + login: Some(login::LoginView { + username: Some("test_username".to_string()), + password: Some("test_password".to_string()), + password_revision_date: None, + uris: None, + totp: None, + autofill_on_page_load: None, + fido2_credentials: None, + }), + id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), + organization_id: None, + folder_id: None, + collection_ids: vec![], + key: None, + name: "My test login".to_string(), + notes: None, + identity: None, + card: None, + secure_note: None, + favorite: false, + reprompt: CipherRepromptType::None, + organization_use_totp: true, + edit: true, + view_password: true, + local_data: None, + attachments: None, + fields: None, + password_history: None, + creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + deleted_date: None, + revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), + } + } + #[test] fn test_generate_cipher_key() { let key = SymmetricCryptoKey::generate(rand::thread_rng()); - fn generate_cipher() -> CipherView { - CipherView { - r#type: CipherType::Login, - login: Some(login::LoginView { - username: Some("test_username".to_string()), - password: Some("test_password".to_string()), - password_revision_date: None, - uris: None, - totp: None, - autofill_on_page_load: None, - fido2_credentials: None, - }), - id: "fd411a1a-fec8-4070-985d-0e6560860e69".parse().ok(), - organization_id: None, - folder_id: None, - collection_ids: vec![], - key: None, - name: "My test login".to_string(), - notes: None, - identity: None, - card: None, - secure_note: None, - favorite: false, - reprompt: CipherRepromptType::None, - organization_use_totp: true, - edit: true, - view_password: true, - local_data: None, - attachments: None, - fields: None, - password_history: None, - creation_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), - deleted_date: None, - revision_date: "2024-01-30T17:55:36.150Z".parse().unwrap(), - } - } - let original_cipher = generate_cipher(); // Check that the cipher gets encrypted correctly without it's own key @@ -504,4 +529,60 @@ mod tests { assert!(key_cipher_dec.key.is_some()); assert_eq!(key_cipher_dec.name, original_cipher.name); } + + struct MockKeyContainer(HashMap, SymmetricCryptoKey>); + impl KeyContainer for MockKeyContainer { + fn get_key<'a>(&'a self, org_id: &Option) -> Option<&'a SymmetricCryptoKey> { + self.0.get(org_id) + } + } + + #[test] + fn test_move_user_cipher_to_org() { + let org = uuid::Uuid::new_v4(); + + let enc = MockKeyContainer(HashMap::from([ + (None, SymmetricCryptoKey::generate(rand::thread_rng())), + (Some(org), SymmetricCryptoKey::generate(rand::thread_rng())), + ])); + + // Create a cipher with a user key + let mut cipher = generate_cipher(); + cipher + .generate_cipher_key(enc.get_key(&None).unwrap()) + .unwrap(); + + cipher.move_to_organization(&enc, org).unwrap(); + assert_eq!(cipher.organization_id, Some(org)); + + // Check that the cipher can be encrypted/decrypted with the new org key + let org_key = enc.get_key(&Some(org)).unwrap(); + let cipher_enc = cipher.encrypt_with_key(org_key).unwrap(); + let cipher_dec: CipherView = cipher_enc.decrypt_with_key(org_key).unwrap(); + + assert_eq!(cipher_dec.name, "My test login"); + } + + #[test] + fn test_move_user_cipher_to_org_manually() { + let org = uuid::Uuid::new_v4(); + + let enc = MockKeyContainer(HashMap::from([ + (None, SymmetricCryptoKey::generate(rand::thread_rng())), + (Some(org), SymmetricCryptoKey::generate(rand::thread_rng())), + ])); + + // Create a cipher with a user key + let mut cipher = generate_cipher(); + cipher + .generate_cipher_key(enc.get_key(&None).unwrap()) + .unwrap(); + + cipher.organization_id = Some(org); + + // Check that the cipher can not be encrypted, as the + // cipher key is tied to the user key and not the org key + let org_key = enc.get_key(&Some(org)).unwrap(); + assert!(cipher.encrypt_with_key(org_key).is_err()); + } } diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md index 5dce0dbb4..e12914f64 100644 --- a/languages/kotlin/doc.md +++ b/languages/kotlin/doc.md @@ -132,6 +132,18 @@ Generate keys needed for registration process **Output**: std::result::Result +### `make_register_tde_keys` + +Generate keys needed for TDE process + +**Arguments**: + +- self: +- org_public_key: String +- remember_device: + +**Output**: std::result::Result + ### `validate_password` Validate the user password @@ -288,6 +300,18 @@ Decrypt cipher list **Output**: std::result::Result +### `move_to_organization` + +Move a cipher to an organization, reencrypting the cipher key if necessary + +**Arguments**: + +- self: +- cipher: [CipherView](#cipherview) +- organization_id: Uuid + +**Output**: std::result::Result + ## ClientCollections ### `decrypt` @@ -346,7 +370,7 @@ as it can be used to decrypt all of the user's data - self: -**Output**: std::result::Result +**Output**: std::result::Result ### `update_password` From 4a339a911e6db1583465f69b4c9ff981104ea0ef Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 9 Apr 2024 16:27:51 +0200 Subject: [PATCH 363/378] Remove doc.md (#699) Remove the `doc.md` now that we have proper documentation in the generated bindings. --- .prettierignore | 3 - crates/bitwarden-uniffi/README.md | 4 +- languages/kotlin/doc.md | 1825 ----------------------------- 3 files changed, 3 insertions(+), 1829 deletions(-) delete mode 100644 languages/kotlin/doc.md diff --git a/.prettierignore b/.prettierignore index 97474cca9..36c418776 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,8 +1,5 @@ target languages/* -!/languages/kotlin -languages/kotlin/* -!/languages/kotlin/doc.md schemas /crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts about.hbs diff --git a/crates/bitwarden-uniffi/README.md b/crates/bitwarden-uniffi/README.md index 1be7706bb..4b2e61714 100644 --- a/crates/bitwarden-uniffi/README.md +++ b/crates/bitwarden-uniffi/README.md @@ -2,10 +2,12 @@ ## Generating documentation +If desired we have some scripts that generates markdown documentation from the rustdoc output. + ```bash cargo +nightly rustdoc -p bitwarden -- -Zunstable-options --output-format json cargo +nightly rustdoc -p bitwarden-uniffi -- -Zunstable-options --output-format json npm run schemas -npx ts-node ./support/docs/docs.ts > languages/kotlin/doc.md +npx ts-node ./support/docs/docs.ts > doc.md ``` diff --git a/languages/kotlin/doc.md b/languages/kotlin/doc.md deleted file mode 100644 index e12914f64..000000000 --- a/languages/kotlin/doc.md +++ /dev/null @@ -1,1825 +0,0 @@ -# Bitwarden Mobile SDK - -Auto generated documentation for the Bitwarden Mobile SDK. For more information please refer to the -rust crates `bitwarden` and `bitwarden-uniffi`. For code samples check the `languages/kotlin/app` -and `languages/swift/app` directories. - -## Client - -### `new` - -Initialize a new instance of the SDK client - -**Arguments**: - -- settings: Option - -**Output**: Arc - -### `crypto` - -Crypto operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `vault` - -Vault item operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `generators` - -Generator operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `exporters` - -Exporters - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `auth` - -Auth operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `echo` - -Test method, echoes back the input - -**Arguments**: - -- self: -- msg: String - -**Output**: String - -## ClientAuth - -### `password_strength` - -**API Draft:** Calculate Password Strength - -**Arguments**: - -- self: -- password: String -- email: String -- additional_inputs: Vec - -**Output**: - -### `satisfies_policy` - -Evaluate if the provided password satisfies the provided policy - -**Arguments**: - -- self: -- password: String -- strength: -- policy: [MasterPasswordPolicyOptions](#masterpasswordpolicyoptions) - -**Output**: - -### `hash_password` - -Hash the user password - -**Arguments**: - -- self: -- email: String -- password: String -- kdf_params: [Kdf](#kdf) -- purpose: [HashPurpose](#hashpurpose) - -**Output**: std::result::Result - -### `make_register_keys` - -Generate keys needed for registration process - -**Arguments**: - -- self: -- email: String -- password: String -- kdf: [Kdf](#kdf) - -**Output**: std::result::Result - -### `make_register_tde_keys` - -Generate keys needed for TDE process - -**Arguments**: - -- self: -- org_public_key: String -- remember_device: - -**Output**: std::result::Result - -### `validate_password` - -Validate the user password - -To retrieve the user's password hash, use [`ClientAuth::hash_password`] with -`HashPurpose::LocalAuthentication` during login and persist it. If the login method has no -password, use the email OTP. - -**Arguments**: - -- self: -- password: String -- password_hash: String - -**Output**: std::result::Result<,BitwardenError> - -### `validate_password_user_key` - -Validate the user password without knowing the password hash - -Used for accounts that we know have master passwords but that have not logged in with a password. -Some example are login with device or TDE. - -This works by comparing the provided password against the encrypted user key. - -**Arguments**: - -- self: -- password: String -- encrypted_user_key: String - -**Output**: std::result::Result - -### `new_auth_request` - -Initialize a new auth request - -**Arguments**: - -- self: -- email: String - -**Output**: std::result::Result - -### `approve_auth_request` - -Approve an auth request - -**Arguments**: - -- self: -- public_key: String - -**Output**: std::result::Result - -### `trust_device` - -Trust the current device - -**Arguments**: - -- self: - -**Output**: std::result::Result - -## ClientAttachments - -### `encrypt_buffer` - -Encrypt an attachment file in memory - -**Arguments**: - -- self: -- cipher: [Cipher](#cipher) -- attachment: [AttachmentView](#attachmentview) -- buffer: Vec<> - -**Output**: std::result::Result - -### `encrypt_file` - -Encrypt an attachment file located in the file system - -**Arguments**: - -- self: -- cipher: [Cipher](#cipher) -- attachment: [AttachmentView](#attachmentview) -- decrypted_file_path: String -- encrypted_file_path: String - -**Output**: std::result::Result - -### `decrypt_buffer` - -Decrypt an attachment file in memory - -**Arguments**: - -- self: -- cipher: [Cipher](#cipher) -- attachment: [Attachment](#attachment) -- buffer: Vec<> - -**Output**: std::result::Result - -### `decrypt_file` - -Decrypt an attachment file located in the file system - -**Arguments**: - -- self: -- cipher: [Cipher](#cipher) -- attachment: [Attachment](#attachment) -- encrypted_file_path: String -- decrypted_file_path: String - -**Output**: std::result::Result<,BitwardenError> - -## ClientCiphers - -### `encrypt` - -Encrypt cipher - -**Arguments**: - -- self: -- cipher_view: [CipherView](#cipherview) - -**Output**: std::result::Result - -### `decrypt` - -Decrypt cipher - -**Arguments**: - -- self: -- cipher: [Cipher](#cipher) - -**Output**: std::result::Result - -### `decrypt_list` - -Decrypt cipher list - -**Arguments**: - -- self: -- ciphers: Vec - -**Output**: std::result::Result - -### `move_to_organization` - -Move a cipher to an organization, reencrypting the cipher key if necessary - -**Arguments**: - -- self: -- cipher: [CipherView](#cipherview) -- organization_id: Uuid - -**Output**: std::result::Result - -## ClientCollections - -### `decrypt` - -Decrypt collection - -**Arguments**: - -- self: -- collection: [Collection](#collection) - -**Output**: std::result::Result - -### `decrypt_list` - -Decrypt collection list - -**Arguments**: - -- self: -- collections: Vec - -**Output**: std::result::Result - -## ClientCrypto - -### `initialize_user_crypto` - -Initialization method for the user crypto. Needs to be called before any other crypto operations. - -**Arguments**: - -- self: -- req: [InitUserCryptoRequest](#initusercryptorequest) - -**Output**: std::result::Result<,BitwardenError> - -### `initialize_org_crypto` - -Initialization method for the organization crypto. Needs to be called after -`initialize_user_crypto` but before any other crypto operations. - -**Arguments**: - -- self: -- req: [InitOrgCryptoRequest](#initorgcryptorequest) - -**Output**: std::result::Result<,BitwardenError> - -### `get_user_encryption_key` - -Get the uses's decrypted encryption key. Note: It's very important to keep this key safe, -as it can be used to decrypt all of the user's data - -**Arguments**: - -- self: - -**Output**: std::result::Result - -### `update_password` - -Update the user's password, which will re-encrypt the user's encryption key with the new -password. This returns the new encrypted user key and the new password hash. - -**Arguments**: - -- self: -- new_password: String - -**Output**: std::result::Result - -### `derive_pin_key` - -Generates a PIN protected user key from the provided PIN. The result can be stored and later used to -initialize another client instance by using the PIN and the PIN key with -`initialize_user_crypto`. - -**Arguments**: - -- self: -- pin: String - -**Output**: std::result::Result - -### `derive_pin_user_key` - -Derives the pin protected user key from encrypted pin. Used when pin requires master password on -first unlock. - -**Arguments**: - -- self: -- encrypted_pin: [EncString](#encstring) - -**Output**: std::result::Result - -## ClientExporters - -### `export_vault` - -**API Draft:** Export user vault - -**Arguments**: - -- self: -- folders: Vec -- ciphers: Vec -- format: [ExportFormat](#exportformat) - -**Output**: std::result::Result - -### `export_organization_vault` - -**API Draft:** Export organization vault - -**Arguments**: - -- self: -- collections: Vec -- ciphers: Vec -- format: [ExportFormat](#exportformat) - -**Output**: std::result::Result - -## ClientFolders - -### `encrypt` - -Encrypt folder - -**Arguments**: - -- self: -- folder: [FolderView](#folderview) - -**Output**: std::result::Result - -### `decrypt` - -Decrypt folder - -**Arguments**: - -- self: -- folder: [Folder](#folder) - -**Output**: std::result::Result - -### `decrypt_list` - -Decrypt folder list - -**Arguments**: - -- self: -- folders: Vec - -**Output**: std::result::Result - -## ClientGenerators - -### `password` - -**API Draft:** Generate Password - -**Arguments**: - -- self: -- settings: [PasswordGeneratorRequest](#passwordgeneratorrequest) - -**Output**: std::result::Result - -### `passphrase` - -**API Draft:** Generate Passphrase - -**Arguments**: - -- self: -- settings: [PassphraseGeneratorRequest](#passphrasegeneratorrequest) - -**Output**: std::result::Result - -### `username` - -**API Draft:** Generate Username - -**Arguments**: - -- self: -- settings: UsernameGeneratorRequest - -**Output**: std::result::Result - -## ClientPasswordHistory - -### `encrypt` - -Encrypt password history - -**Arguments**: - -- self: -- password_history: [PasswordHistoryView](#passwordhistoryview) - -**Output**: std::result::Result - -### `decrypt_list` - -Decrypt password history - -**Arguments**: - -- self: -- list: Vec - -**Output**: std::result::Result - -## ClientPlatform - -### `fingerprint` - -Fingerprint (public key) - -**Arguments**: - -- self: -- req: [FingerprintRequest](#fingerprintrequest) - -**Output**: std::result::Result - -### `user_fingerprint` - -Fingerprint using logged in user's public key - -**Arguments**: - -- self: -- fingerprint_material: String - -**Output**: std::result::Result - -### `load_flags` - -Load feature flags into the client - -**Arguments**: - -- self: -- flags: std::collections::HashMap - -**Output**: std::result::Result<,BitwardenError> - -## ClientSends - -### `encrypt` - -Encrypt send - -**Arguments**: - -- self: -- send: [SendView](#sendview) - -**Output**: std::result::Result - -### `encrypt_buffer` - -Encrypt a send file in memory - -**Arguments**: - -- self: -- send: [Send](#send) -- buffer: Vec<> - -**Output**: std::result::Result - -### `encrypt_file` - -Encrypt a send file located in the file system - -**Arguments**: - -- self: -- send: [Send](#send) -- decrypted_file_path: String -- encrypted_file_path: String - -**Output**: std::result::Result<,BitwardenError> - -### `decrypt` - -Decrypt send - -**Arguments**: - -- self: -- send: [Send](#send) - -**Output**: std::result::Result - -### `decrypt_list` - -Decrypt send list - -**Arguments**: - -- self: -- sends: Vec - -**Output**: std::result::Result - -### `decrypt_buffer` - -Decrypt a send file in memory - -**Arguments**: - -- self: -- send: [Send](#send) -- buffer: Vec<> - -**Output**: std::result::Result - -### `decrypt_file` - -Decrypt a send file located in the file system - -**Arguments**: - -- self: -- send: [Send](#send) -- encrypted_file_path: String -- decrypted_file_path: String - -**Output**: std::result::Result<,BitwardenError> - -## ClientVault - -### `folders` - -Folder operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `collections` - -Collections operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `ciphers` - -Ciphers operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `password_history` - -Password history operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `sends` - -Sends operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `attachments` - -Attachment file operations - -**Arguments**: - -- self: Arc - -**Output**: Arc - -### `generate_totp` - -Generate a TOTP code from a provided key. - -The key can be either: - -- A base32 encoded string -- OTP Auth URI -- Steam URI - -**Arguments**: - -- self: -- key: String -- time: Option - -**Output**: std::result::Result - -# References - -References are generated from the JSON schemas and should mostly match the kotlin and swift -implementations. - -## `Attachment` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
urlstring,null
sizestring,null
sizeNamestring,nullReadable size, ex: "4.2 KB" or "1.43 GB"
fileName
key
- -## `AttachmentView` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
urlstring,null
sizestring,null
sizeNamestring,null
fileNamestring,null
key
- -## `Cipher` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
organizationIdstring,null
folderIdstring,null
collectionIdsarray
keyMore recent ciphers uses individual encryption keys to encrypt the other fields of the Cipher.
name
notes
type
login
identity
card
secureNote
favoriteboolean
reprompt
organizationUseTotpboolean
editboolean
viewPasswordboolean
localData
attachmentsarray,null
fieldsarray,null
passwordHistoryarray,null
creationDatestring
deletedDatestring,null
revisionDatestring
- -## `CipherView` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
organizationIdstring,null
folderIdstring,null
collectionIdsarray
key
namestring
notesstring,null
type
login
identity
card
secureNote
favoriteboolean
reprompt
organizationUseTotpboolean
editboolean
viewPasswordboolean
localData
attachmentsarray,null
fieldsarray,null
passwordHistoryarray,null
creationDatestring
deletedDatestring,null
revisionDatestring
- -## `Collection` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
organizationIdstring
name
externalIdstring,null
hidePasswordsboolean
readOnlyboolean
- -## `EncString` - - - - - - - -
KeyTypeDescription
- -## `ExportFormat` - - - - - - - - - - - - - - - -
KeyTypeDescription
EncryptedJsonobject
- - - - - - - - - - - -
KeyTypeDescription
passwordstring
-
- -## `FingerprintRequest` - - - - - - - - - - - - - - - - - -
KeyTypeDescription
fingerprintMaterialstringThe input material, used in the fingerprint generation process.
publicKeystringThe user's public key encoded with base64.
- -## `Folder` - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
name
revisionDatestring
- -## `FolderView` - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
namestring
revisionDatestring
- -## `HashPurpose` - - - - - - - -
KeyTypeDescription
- -## `InitOrgCryptoRequest` - - - - - - - - - - - - -
KeyTypeDescription
organizationKeysobjectThe encryption keys for all the organizations the user is a part of
- -## `InitUserCryptoMethod` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
passwordobject
- - - - - - - - - - - - - - - - -
KeyTypeDescription
passwordstringThe user's master password
user_keystringThe user's encrypted symmetric crypto key
-
decryptedKeyobject
- - - - - - - - - - - -
KeyTypeDescription
decrypted_user_keystringThe user's decrypted encryption key, obtained using `get_user_encryption_key`
-
pinobject
- - - - - - - - - - - - - - - - -
KeyTypeDescription
pinstringThe user's PIN
pin_protected_user_keyThe user's symmetric crypto key, encrypted with the PIN. Use `derive_pin_key` to obtain this.
-
authRequestobject
- - - - - - - - - - - - - - - - -
KeyTypeDescription
request_private_keystringPrivate Key generated by the `crate::auth::new_auth_request`.
method
-
deviceKeyobject
- - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
device_keystringThe device's DeviceKey
protected_device_private_keyThe Device Private Key
device_protected_user_keyThe user's symmetric crypto key, encrypted with the Device Key.
-
- -## `InitUserCryptoRequest` - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
kdfParamsThe user's KDF parameters, as received from the prelogin request
emailstringThe user's email address
privateKeystringThe user's encrypted private key
methodThe initialization method to use
- -## `Kdf` - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
pBKDF2object
- - - - - - - - - - - -
KeyTypeDescription
iterationsinteger
-
argon2idobject
- - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
iterationsinteger
memoryinteger
parallelisminteger
-
- -## `MasterPasswordPolicyOptions` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
min_complexityinteger
min_lengthinteger
require_upperboolean
require_lowerboolean
require_numbersboolean
require_specialboolean
enforce_on_loginbooleanFlag to indicate if the policy should be enforced on login. If true, and the user's password does not meet the policy requirements, the user will be forced to update their password.
- -## `PassphraseGeneratorRequest` - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
numWordsintegerNumber of words in the generated passphrase. This value must be between 3 and 20.
wordSeparatorstringCharacter separator between words in the generated passphrase. The value cannot be empty.
capitalizebooleanWhen set to true, capitalize the first letter of each word in the generated passphrase.
includeNumberbooleanWhen set to true, include a number at the end of one of the words in the generated passphrase.
- -## `PasswordGeneratorRequest` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
lowercasebooleanInclude lowercase characters (a-z).
uppercasebooleanInclude uppercase characters (A-Z).
numbersbooleanInclude numbers (0-9).
specialbooleanInclude special characters: ! @ # $ % ^ & *
lengthintegerThe length of the generated password. Note that the password length must be greater than the sum of all the minimums.
avoidAmbiguousbooleanWhen set to true, the generated password will not contain ambiguous characters. The ambiguous characters are: I, O, l, 0, 1
minLowercaseinteger,nullThe minimum number of lowercase characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is lowercase is false
minUppercaseinteger,nullThe minimum number of uppercase characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is uppercase is false
minNumberinteger,nullThe minimum number of numbers in the generated password. When set, the value must be between 1 and 9. This value is ignored is numbers is false
minSpecialinteger,nullThe minimum number of special characters in the generated password. When set, the value must be between 1 and 9. This value is ignored is special is false
- -## `PasswordHistoryView` - - - - - - - - - - - - - - - - - -
KeyTypeDescription
passwordstring
lastUsedDatestring
- -## `Send` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
accessIdstring,null
name
notes
key
passwordstring,null
type
file
text
maxAccessCountinteger,null
accessCountinteger
disabledboolean
hideEmailboolean
revisionDatestring
deletionDatestring
expirationDatestring,null
- -## `SendView` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyTypeDescription
idstring,null
accessIdstring,null
namestring
notesstring,null
keystring,nullBase64 encoded key
newPasswordstring,nullReplace or add a password to an existing send. The SDK will always return None when decrypting a [Send] TODO: We should revisit this, one variant is to have `[Create, Update]SendView` DTOs.
hasPasswordbooleanDenote if an existing send has a password. The SDK will ignore this value when creating or updating sends.
type
file
text
maxAccessCountinteger,null
accessCountinteger
disabledboolean
hideEmailboolean
revisionDatestring
deletionDatestring
expirationDatestring,null
From 09d28266dcdfc00a6536832c26a575b9f6613a11 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Wed, 10 Apr 2024 18:56:39 -0400 Subject: [PATCH 364/378] [SM-1178] Rename Service Accounts to Machine Accounts (#698) ## Type of change - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective Rename instances (& similar) of "service account" to "machine account". This only impacts public facing text, so items in README's, documentation, help docs, etc. ## Before you submit - Please add **unit tests** where it makes sense to do so --- crates/bitwarden-napi/README.md | 2 +- crates/bws/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-napi/README.md b/crates/bitwarden-napi/README.md index d16c8152d..d9e3e7f27 100644 --- a/crates/bitwarden-napi/README.md +++ b/crates/bitwarden-napi/README.md @@ -20,7 +20,7 @@ const accessToken = "-- REDACTED --"; const client = new BitwardenClient(settings, LogLevel.Info); -// Authenticating using a service accounts access token +// Authenticating using a machine account access token const result = await client.loginWithAccessToken(accessToken); if (!result.success) { throw Error("Authentication failed"); diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 182e20679..0f94fd7ec 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -40,7 +40,7 @@ struct Cli { #[arg(short = 'c', long, global = true, value_enum, default_value_t = Color::Auto, help="Use colors in the output")] color: Color, - #[arg(short = 't', long, global = true, env = ACCESS_TOKEN_KEY_VAR_NAME, hide_env_values = true, help="Specify access token for the service account")] + #[arg(short = 't', long, global = true, env = ACCESS_TOKEN_KEY_VAR_NAME, hide_env_values = true, help="Specify access token for the machine account")] access_token: Option, #[arg( From 4b5aaa628ac7814da2672983b405d34ba2f82546 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Apr 2024 11:23:35 +0200 Subject: [PATCH 365/378] Fix android build errors (#703) Since we share the same version across crates we need to load it from the root `cargo.Toml` instead of `crates/bitwarden/cargo.Toml`. Resolves the Android SDK no longer building. --- languages/kotlin/sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/kotlin/sdk/build.gradle b/languages/kotlin/sdk/build.gradle index 9b3ca3585..d92dad56a 100644 --- a/languages/kotlin/sdk/build.gradle +++ b/languages/kotlin/sdk/build.gradle @@ -55,7 +55,7 @@ publishing { def branchName = "git branch --show-current".execute().text.trim() if (branchName == "main") { - def content = ['grep', '-o', '^version = ".*"', '../../crates/bitwarden/Cargo.toml'].execute().text.trim() + def content = ['grep', '-o', '^version = ".*"', '../../Cargo.toml'].execute().text.trim() def match = ~/version = "(.*)"/ def matcher = match.matcher(content) matcher.find() From 975ac0c8992d7723c284173808e5771395fa79d2 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Apr 2024 14:04:30 +0200 Subject: [PATCH 366/378] Add bitwarden-cli and bitwarden-exporters to publish-rust-crates (#704) We need to be able to publish these crates to release the SDK. --- .github/workflows/publish-rust-crates.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index f6a52d5d1..d470b5194 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -34,11 +34,21 @@ on: required: true default: true type: boolean + publish_bitwarden-cli: + description: "Publish bitwarden-cli crate" + required: true + default: true + type: boolean publish_bitwarden-generators: description: "Publish bitwarden-generators crate" required: true default: true type: boolean + publish_bitwarden-exporters: + description: "Publish bitwarden-exporters crate" + required: true + default: true + type: boolean defaults: run: @@ -72,7 +82,9 @@ jobs: PUBLISH_BITWARDEN_API_API: ${{ github.event.inputs.publish_bitwarden-api-api }} PUBLISH_BITWARDEN_API_IDENTITY: ${{ github.event.inputs.publish_bitwarden-api-identity }} PUBLISH_BITWARDEN_CRYPTO: ${{ github.event.inputs.publish_bitwarden-crypto }} + PUBLISH_BITWARDEN_CLI: ${{ github.event.inputs.publish_bitwarden-cli }} PUBLISH_BITWARDEN_GENERATORS: ${{ github.event.inputs.publish_bitwarden-generators }} + PUBLISH_BITWARDEN_EXPORTERS: ${{ github.event.inputs.publish_bitwarden-exporters }} run: | if [[ "$PUBLISH_BITWARDEN" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_API" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_IDENTITY" == "false" ]]; then echo "===================================" @@ -104,11 +116,21 @@ jobs: PACKAGES_LIST="$PACKAGES_LIST bitwarden-crypto" fi + if [[ "$PUBLISH_BITWARDEN_CLI" == "true" ]]; then + PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-cli" + PACKAGES_LIST="$PACKAGES_LIST bitwarden-cli" + fi + if [[ "$PUBLISH_BITWARDEN_GENERATORS" == "true" ]]; then PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-generators" PACKAGES_LIST="$PACKAGES_LIST bitwarden-generators" fi + if [[ "$PUBLISH_BITWARDEN_EXPORTERS" == "true" ]]; then + PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-generators" + PACKAGES_LIST="$PACKAGES_LIST bitwarden-generators" + fi + echo "Packages command: " $PACKAGES_COMMAND echo "Packages list: " $PACKAGES_LIST From b4205cc7e508862818461dd739f81fae9a4bca62 Mon Sep 17 00:00:00 2001 From: Colton Hurst Date: Thu, 11 Apr 2024 09:59:56 -0400 Subject: [PATCH 367/378] SM-1147: Switch to try_init with pyo3_log (#676) ## Type of change - [x] Bug fix - [ ] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [ ] Build/deploy pipeline (DevOps) - [ ] Other ## Objective When running the `ansible-playbook` command, we needed to export the following variable: `export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES`. This suppresses fork safety warnings on Mac OS. With this set, you can safely query for individual secrets. However, if you query for secrets within an Ansible loop or with a Jinja2 template, we receive an error that is caused by setting up a logger more than once. (This error comes from the `pyo3_log` crate.) If we switch to using the `pyo3_log::try_init` function, we ignore the case where a logger is already set up if the attempt fails. This happens because the `pyo3_log::init` function [can panic](https://github.com/vorner/pyo3-log/blob/70819388bfcb58a7ca91a27179a73cea0abde31e/src/lib.rs#L569). This also introduces panic safety. ## Code changes - **client.rs:** Switch to `try_init` ## Before you submit - Please add **unit tests** where it makes sense to do so --- crates/bitwarden-py/src/client.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden-py/src/client.rs b/crates/bitwarden-py/src/client.rs index f1d282b41..c3ea62444 100644 --- a/crates/bitwarden-py/src/client.rs +++ b/crates/bitwarden-py/src/client.rs @@ -8,7 +8,10 @@ pub struct BitwardenClient(JsonClient); impl BitwardenClient { #[new] pub fn new(settings_string: Option) -> Self { - pyo3_log::init(); + // This will only fail if another logger was already initialized, so we can ignore the + // result + let _ = pyo3_log::try_init(); + Self(JsonClient::new(settings_string)) } From e7b6c1ded84f863929d02dd769a90ad3ce095ff0 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Apr 2024 17:24:40 +0200 Subject: [PATCH 368/378] Use the shared bitwarden-cli in bws (#705) Now that we are publishing the `bitwarden-cli` crate we should start using the shared functionality in the `bws` crate. And continually extract common code out from it. --- Cargo.lock | 1 + crates/bitwarden-cli/src/color.rs | 6 ++++++ crates/bws/Cargo.toml | 1 + crates/bws/src/main.rs | 14 ++++---------- crates/bws/src/render.rs | 24 ++++-------------------- 5 files changed, 16 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47e2b9e9d..b17f861ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -597,6 +597,7 @@ version = "0.4.0" dependencies = [ "bat", "bitwarden", + "bitwarden-cli", "chrono", "clap", "clap_complete", diff --git a/crates/bitwarden-cli/src/color.rs b/crates/bitwarden-cli/src/color.rs index 410a8b6ed..2e3a2c007 100644 --- a/crates/bitwarden-cli/src/color.rs +++ b/crates/bitwarden-cli/src/color.rs @@ -8,6 +8,9 @@ pub enum Color { } impl Color { + /** + * Evaluate if colors are supported + */ pub fn is_enabled(self) -> bool { match self { Color::No => false, @@ -17,6 +20,9 @@ impl Color { } } +/** + * Installs color_eyre, if Color is disabled we use an empty theme to disable error colors. + */ pub fn install_color_eyre(color: Color) -> color_eyre::Result<(), color_eyre::Report> { if color.is_enabled() { color_eyre::install() diff --git a/crates/bws/Cargo.toml b/crates/bws/Cargo.toml index 23f78cfd5..d27daca6f 100644 --- a/crates/bws/Cargo.toml +++ b/crates/bws/Cargo.toml @@ -19,6 +19,7 @@ bat = { version = "0.24.0", features = [ "regex-onig", ], default-features = false } bitwarden = { workspace = true, features = ["secrets"] } +bitwarden-cli = { workspace = true } chrono = { version = "0.4.35", features = [ "clock", "std", diff --git a/crates/bws/src/main.rs b/crates/bws/src/main.rs index 0f94fd7ec..d57aee5a6 100644 --- a/crates/bws/src/main.rs +++ b/crates/bws/src/main.rs @@ -14,6 +14,7 @@ use bitwarden::{ }, }, }; +use bitwarden_cli::{install_color_eyre, Color}; use clap::{ArgGroup, CommandFactory, Parser, Subcommand}; use clap_complete::Shell; use color_eyre::eyre::{bail, Result}; @@ -24,7 +25,7 @@ mod render; mod state; use config::ProfileKey; -use render::{serialize_response, Color, Output}; +use render::{serialize_response, Output}; use uuid::Uuid; #[derive(Parser, Debug)] @@ -236,16 +237,9 @@ const SERVER_URL_KEY_VAR_NAME: &str = "BWS_SERVER_URL"; #[allow(clippy::comparison_chain)] async fn process_commands() -> Result<()> { let cli = Cli::parse(); + let color = cli.color; - let color = cli.color.is_enabled(); - if color { - color_eyre::install()?; - } else { - // Use an empty theme to disable error coloring - color_eyre::config::HookBuilder::new() - .theme(color_eyre::config::Theme::new()) - .install()?; - } + install_color_eyre(color)?; let Some(command) = cli.command else { let mut cmd = Cli::command(); diff --git a/crates/bws/src/render.rs b/crates/bws/src/render.rs index c92c78662..7acdd30a6 100644 --- a/crates/bws/src/render.rs +++ b/crates/bws/src/render.rs @@ -1,4 +1,5 @@ use bitwarden::secrets_manager::{projects::ProjectResponse, secrets::SecretResponse}; +use bitwarden_cli::Color; use chrono::{DateTime, Utc}; use clap::ValueEnum; use comfy_table::Table; @@ -15,29 +16,12 @@ pub(crate) enum Output { None, } -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Debug)] -pub(crate) enum Color { - No, - Yes, - Auto, -} - -impl Color { - pub(crate) fn is_enabled(self) -> bool { - match self { - Color::No => false, - Color::Yes => true, - Color::Auto => supports_color::on(supports_color::Stream::Stdout).is_some(), - } - } -} - const ASCII_HEADER_ONLY: &str = " -- "; pub(crate) fn serialize_response, const N: usize>( data: T, output: Output, - color: bool, + color: Color, ) { match output { Output::JSON => { @@ -101,8 +85,8 @@ pub(crate) fn serialize_response, const N: usiz } } -fn pretty_print(language: &str, data: &str, color: bool) { - if color { +fn pretty_print(language: &str, data: &str, color: Color) { + if color.is_enabled() { bat::PrettyPrinter::new() .input_from_bytes(data.as_bytes()) .language(language) From e0513dcd14c8a7e6b44ae858d83abfe34d796691 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Thu, 11 Apr 2024 17:25:06 +0200 Subject: [PATCH 369/378] Change fastMail to use forDomain instead of url (#707) It seems the web clients use `forDomain` instead of `url` for website. This changes the SDK to send the same values. --- crates/bitwarden-generators/src/username_forwarders/fastmail.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-generators/src/username_forwarders/fastmail.rs b/crates/bitwarden-generators/src/username_forwarders/fastmail.rs index 6cc63647a..8a73250c4 100644 --- a/crates/bitwarden-generators/src/username_forwarders/fastmail.rs +++ b/crates/bitwarden-generators/src/username_forwarders/fastmail.rs @@ -34,7 +34,7 @@ pub async fn generate_with_api_url( "new-masked-email": { "state": "enabled", "description": "", - "url": website, + "forDomain": website, "emailPrefix": null, }, }, From 7e1a3cb73014a7c12f30d769f49dd57c217dd504 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 12 Apr 2024 11:56:16 +0200 Subject: [PATCH 370/378] Enable http2 feature for reqwest (#708) Some websites will require `http2` support and we should have that feature enabled to avoid errors. --- Cargo.lock | 1 + crates/bitwarden-api-api/Cargo.toml | 2 +- crates/bitwarden-api-identity/Cargo.toml | 2 +- crates/bitwarden-generators/Cargo.toml | 1 + crates/bitwarden/Cargo.toml | 1 + support/openapi-template/Cargo.mustache | 2 +- 6 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b17f861ec..a00d91bd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2617,6 +2617,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", diff --git a/crates/bitwarden-api-api/Cargo.toml b/crates/bitwarden-api-api/Cargo.toml index a06a0f0e5..cfe357998 100644 --- a/crates/bitwarden-api-api/Cargo.toml +++ b/crates/bitwarden-api-api/Cargo.toml @@ -23,7 +23,7 @@ url = ">=2.3.1, <3" uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] version = ">=0.12, <0.13" -features = ["json", "multipart"] +features = ["http2", "json", "multipart"] default-features = false [dev-dependencies] diff --git a/crates/bitwarden-api-identity/Cargo.toml b/crates/bitwarden-api-identity/Cargo.toml index e5a49efac..74d96d144 100644 --- a/crates/bitwarden-api-identity/Cargo.toml +++ b/crates/bitwarden-api-identity/Cargo.toml @@ -23,7 +23,7 @@ url = ">=2.3.1, <3" uuid = { version = ">=1.3.3, <2", features = ["serde"] } [dependencies.reqwest] version = ">=0.12, <0.13" -features = ["json", "multipart"] +features = ["http2", "json", "multipart"] default-features = false [dev-dependencies] diff --git a/crates/bitwarden-generators/Cargo.toml b/crates/bitwarden-generators/Cargo.toml index af8ce60aa..3f79ac539 100644 --- a/crates/bitwarden-generators/Cargo.toml +++ b/crates/bitwarden-generators/Cargo.toml @@ -20,6 +20,7 @@ mobile = ["dep:uniffi"] # Mobile-specific features bitwarden-crypto = { workspace = true } rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.12, <0.13", features = [ + "http2", "json", ], default-features = false } schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index e064360c8..b34f9c9a1 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -48,6 +48,7 @@ hmac = ">=0.12.1, <0.13" log = ">=0.4.18, <0.5" rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.12, <0.13", features = [ + "http2", "json", ], default-features = false } schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } diff --git a/support/openapi-template/Cargo.mustache b/support/openapi-template/Cargo.mustache index 6417d15cd..08f1a942e 100644 --- a/support/openapi-template/Cargo.mustache +++ b/support/openapi-template/Cargo.mustache @@ -65,7 +65,7 @@ reqwest-middleware = "0.2.0" {{/supportMiddleware}} [dependencies.reqwest] version = "^0.11" -features = ["json", "multipart"] +features = ["http2", "json", "multipart"] default-features = false {{/supportAsync}} {{/reqwest}} From b611974a84b10d5bce10f4c299f5589e9416fbd5 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 12 Apr 2024 13:26:59 +0200 Subject: [PATCH 371/378] Fix java build (#709) In #703 we fixed the android java build, but forgot that java also needed to be updated. --- languages/java/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/java/build.gradle b/languages/java/build.gradle index f044ea485..ed4a72f22 100644 --- a/languages/java/build.gradle +++ b/languages/java/build.gradle @@ -36,7 +36,7 @@ repositories { def branchName = "git branch --show-current".execute().text.trim() if (branchName == "main") { - def content = ['grep', '-o', '^version = ".*"', '../../crates/bitwarden/Cargo.toml'].execute().text.trim() + def content = ['grep', '-o', '^version = ".*"', '../../Cargo.toml'].execute().text.trim() def match = ~/version = "(.*)"/ def matcher = match.matcher(content) matcher.find() From 499e2131bc4cb58d7cbae372262a85be138adead Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:04:02 +0200 Subject: [PATCH 372/378] [deps]: Update @types/node to v18.19.31 (#715) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@types/node](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://togithub.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`18.19.26` -> `18.19.31`](https://renovatebot.com/diffs/npm/@types%2fnode/18.19.26/18.19.31) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/18.19.31?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/18.19.31?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/18.19.26/18.19.31?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/18.19.26/18.19.31?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week of the year before 4am on Monday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://developer.mend.io/github/bitwarden/sdk). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- languages/js/sdk-client/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/languages/js/sdk-client/package-lock.json b/languages/js/sdk-client/package-lock.json index dc788c8ce..071d01578 100644 --- a/languages/js/sdk-client/package-lock.json +++ b/languages/js/sdk-client/package-lock.json @@ -39,9 +39,9 @@ } }, "node_modules/@types/node": { - "version": "18.19.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", - "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 6d45212dae09c99ab8ac79e20a1bf2182afaacb0 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Mon, 15 Apr 2024 14:10:08 +0200 Subject: [PATCH 373/378] Set login_method when registering for tde (#711) We should set login_method when registering TDE keys --- .../bitwarden-crypto/src/keys/master_key.rs | 21 +++++++++++++++++++ crates/bitwarden-crypto/src/keys/mod.rs | 5 ++++- crates/bitwarden-uniffi/src/auth/mod.rs | 13 ++++++------ .../api/response/identity_success_response.rs | 6 ++++-- crates/bitwarden/src/auth/client_auth.rs | 3 ++- .../bitwarden/src/auth/login/auth_request.rs | 6 +----- crates/bitwarden/src/auth/login/mod.rs | 3 +-- crates/bitwarden/src/auth/register.rs | 8 +++---- crates/bitwarden/src/auth/tde.rs | 10 ++++++++- crates/bitwarden/src/util.rs | 18 ---------------- 10 files changed, 51 insertions(+), 42 deletions(-) diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index b6921fc6b..1fd678452 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -21,6 +21,27 @@ pub enum Kdf { }, } +impl Default for Kdf { + fn default() -> Self { + Kdf::PBKDF2 { + iterations: default_pbkdf2_iterations(), + } + } +} + +pub fn default_pbkdf2_iterations() -> NonZeroU32 { + NonZeroU32::new(600_000).expect("Non-zero number") +} +pub fn default_argon2_iterations() -> NonZeroU32 { + NonZeroU32::new(3).expect("Non-zero number") +} +pub fn default_argon2_memory() -> NonZeroU32 { + NonZeroU32::new(64).expect("Non-zero number") +} +pub fn default_argon2_parallelism() -> NonZeroU32 { + NonZeroU32::new(4).expect("Non-zero number") +} + #[derive(Copy, Clone, JsonSchema)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] pub enum HashPurpose { diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 435f1011b..62b378808 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -1,7 +1,10 @@ mod key_encryptable; pub use key_encryptable::{CryptoKey, KeyDecryptable, KeyEncryptable}; mod master_key; -pub use master_key::{HashPurpose, Kdf, MasterKey}; +pub use master_key::{ + default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, + default_pbkdf2_iterations, HashPurpose, Kdf, MasterKey, +}; mod shareable_key; pub use shareable_key::derive_shareable_key; mod symmetric_crypto_key; diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 62b709045..c6aed44eb 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -82,16 +82,15 @@ impl ClientAuth { /// Generate keys needed for TDE process pub async fn make_register_tde_keys( &self, + email: String, org_public_key: String, remember_device: bool, ) -> Result { - Ok(self - .0 - .0 - .write() - .await - .auth() - .make_register_tde_keys(org_public_key, remember_device)?) + Ok(self.0 .0.write().await.auth().make_register_tde_keys( + email, + org_public_key, + remember_device, + )?) } /// Validate the user password diff --git a/crates/bitwarden/src/auth/api/response/identity_success_response.rs b/crates/bitwarden/src/auth/api/response/identity_success_response.rs index fb59c1caa..94ebe9445 100644 --- a/crates/bitwarden/src/auth/api/response/identity_success_response.rs +++ b/crates/bitwarden/src/auth/api/response/identity_success_response.rs @@ -22,7 +22,7 @@ pub struct IdentityTokenSuccessResponse { #[serde( rename = "kdfIterations", alias = "KdfIterations", - default = "crate::util::default_pbkdf2_iterations" + default = "bitwarden_crypto::default_pbkdf2_iterations" )] kdf_iterations: NonZeroU32, @@ -41,6 +41,8 @@ pub struct IdentityTokenSuccessResponse { #[cfg(test)] mod test { + use bitwarden_crypto::default_pbkdf2_iterations; + use super::*; impl Default for IdentityTokenSuccessResponse { @@ -54,7 +56,7 @@ mod test { key: Default::default(), two_factor_token: Default::default(), kdf: KdfType::default(), - kdf_iterations: crate::util::default_pbkdf2_iterations(), + kdf_iterations: default_pbkdf2_iterations(), reset_master_password: Default::default(), force_password_reset: Default::default(), api_use_key_connector: Default::default(), diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 5029d389b..b3afe133a 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -76,10 +76,11 @@ impl<'a> ClientAuth<'a> { pub fn make_register_tde_keys( &mut self, + email: String, org_public_key: String, remember_device: bool, ) -> Result { - make_register_tde_keys(self.client, org_public_key, remember_device) + make_register_tde_keys(self.client, email, org_public_key, remember_device) } pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { diff --git a/crates/bitwarden/src/auth/login/auth_request.rs b/crates/bitwarden/src/auth/login/auth_request.rs index 0e9cb6795..fb449e5d4 100644 --- a/crates/bitwarden/src/auth/login/auth_request.rs +++ b/crates/bitwarden/src/auth/login/auth_request.rs @@ -1,5 +1,3 @@ -use std::num::NonZeroU32; - use bitwarden_api_api::{ apis::auth_requests_api::{auth_requests_id_response_get, auth_requests_post}, models::{AuthRequestCreateRequestModel, AuthRequestType}, @@ -86,9 +84,7 @@ pub(crate) async fn complete_auth_request( .await?; if let IdentityTokenResponse::Authenticated(r) = response { - let kdf = Kdf::PBKDF2 { - iterations: NonZeroU32::new(600_000).expect("Non-zero number"), - }; + let kdf = Kdf::default(); client.set_tokens( r.access_token.clone(), diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 53ea712cc..745e0b78c 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -58,8 +58,7 @@ pub(crate) fn parse_prelogin(response: PreloginResponseModel) -> Result { use std::num::NonZeroU32; use bitwarden_api_identity::models::KdfType; - - use crate::util::{ + use bitwarden_crypto::{ default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, default_pbkdf2_iterations, }; diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 31b69c515..5cedd9c53 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -2,11 +2,11 @@ use bitwarden_api_identity::{ apis::accounts_api::accounts_register_post, models::{KeysRequestModel, RegisterRequestModel}, }; -use bitwarden_crypto::{HashPurpose, MasterKey, RsaKeyPair}; +use bitwarden_crypto::{default_pbkdf2_iterations, HashPurpose, MasterKey, RsaKeyPair}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{client::Kdf, error::Result, util::default_pbkdf2_iterations, Client}; +use crate::{client::Kdf, error::Result, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -21,9 +21,7 @@ pub struct RegisterRequest { pub(super) async fn register(client: &mut Client, req: &RegisterRequest) -> Result<()> { let config = client.get_api_configurations().await; - let kdf = Kdf::PBKDF2 { - iterations: default_pbkdf2_iterations(), - }; + let kdf = Kdf::default(); let keys = make_register_keys(req.email.to_owned(), req.password.to_owned(), kdf)?; diff --git a/crates/bitwarden/src/auth/tde.rs b/crates/bitwarden/src/auth/tde.rs index 0bbbb904a..420448f16 100644 --- a/crates/bitwarden/src/auth/tde.rs +++ b/crates/bitwarden/src/auth/tde.rs @@ -1,6 +1,6 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_crypto::{ - AsymmetricEncString, AsymmetricPublicCryptoKey, DeviceKey, EncString, SymmetricCryptoKey, + AsymmetricEncString, AsymmetricPublicCryptoKey, DeviceKey, EncString, Kdf, SymmetricCryptoKey, TrustDeviceResponse, UserKey, }; @@ -11,6 +11,7 @@ use crate::{error::Result, Client}; /// password reset. If remember_device is true, it also generates a device key. pub(super) fn make_register_tde_keys( client: &mut Client, + email: String, org_public_key: String, remember_device: bool, ) -> Result { @@ -30,6 +31,13 @@ pub(super) fn make_register_tde_keys( None }; + client.set_login_method(crate::client::LoginMethod::User( + crate::client::UserLoginMethod::Username { + client_id: "".to_owned(), + email, + kdf: Kdf::default(), + }, + )); client.initialize_user_crypto_decrypted_key(user_key.0, key_pair.private.clone())?; Ok(RegisterTdeKeyResponse { diff --git a/crates/bitwarden/src/util.rs b/crates/bitwarden/src/util.rs index 5611b4077..aaf47a1a6 100644 --- a/crates/bitwarden/src/util.rs +++ b/crates/bitwarden/src/util.rs @@ -1,26 +1,8 @@ -use std::num::NonZeroU32; - use base64::{ alphabet, engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, }; -pub fn default_pbkdf2_iterations() -> NonZeroU32 { - NonZeroU32::new(600_000).expect("Non-zero number") -} -#[cfg(feature = "internal")] -pub fn default_argon2_iterations() -> NonZeroU32 { - NonZeroU32::new(3).expect("Non-zero number") -} -#[cfg(feature = "internal")] -pub fn default_argon2_memory() -> NonZeroU32 { - NonZeroU32::new(64).expect("Non-zero number") -} -#[cfg(feature = "internal")] -pub fn default_argon2_parallelism() -> NonZeroU32 { - NonZeroU32::new(4).expect("Non-zero number") -} - const INDIFFERENT: GeneralPurposeConfig = GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent); From 0be54d1820f053056f6ba530633400579928f1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Garc=C3=ADa?= Date: Mon, 15 Apr 2024 14:58:31 +0200 Subject: [PATCH 374/378] Publish WASM package to enable argon2 support on CLI (#691) ## Type of change ``` - [ ] Bug fix - [x] New feature development - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - [x] Build/deploy pipeline (DevOps) - [ ] Other ``` ## Objective Continuation of #680 I've created workflows to publish the WASM builds to NPM, so that it can be used from the CLI client. The publishing step is based on the NAPI builds, and I've tested it against the Github NPM registry. We'll need to get a build going and published on the NPM registry to be able to use it on the CLI. --------- Co-authored-by: Hinton --- .github/workflows/build-wasm.yml | 58 ++++++++++++ .github/workflows/release-wasm.yml | 132 ++++++++++++++++++++++++++++ Cargo.lock | 1 + crates/bitwarden-wasm/Cargo.toml | 4 + crates/bitwarden-wasm/src/client.rs | 25 ++++++ languages/js/wasm/package.json | 5 +- 6 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-wasm.yml create mode 100644 .github/workflows/release-wasm.yml diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml new file mode 100644 index 000000000..0bc29b4e0 --- /dev/null +++ b/.github/workflows/build-wasm.yml @@ -0,0 +1,58 @@ +--- +name: Build @bitwarden/sdk-wasm + +on: + pull_request: + push: + branches: + - "main" + - "rc" + - "hotfix-rc" + workflow_dispatch: + +defaults: + run: + shell: bash + working-directory: crates/bitwarden-wasm + +jobs: + build: + name: Building @bitwarden/sdk-wasm + runs-on: ubuntu-22.04 + + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 18 + cache: "npm" + + - name: Install dependencies + run: npm i -g binaryen + + - name: Install rust + uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + with: + toolchain: stable + targets: wasm32-unknown-unknown + + - name: Cache cargo registry + uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + with: + key: wasm-cargo-cache + + - name: Install wasm-bindgen-cli + run: cargo install wasm-bindgen-cli + + - name: Build + run: ./build.sh -r + + - name: Upload artifact + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: sdk-bitwarden-wasm + path: ${{ github.workspace }}/languages/js/wasm/* + if-no-files-found: error diff --git a/.github/workflows/release-wasm.yml b/.github/workflows/release-wasm.yml new file mode 100644 index 000000000..c4946a0e1 --- /dev/null +++ b/.github/workflows/release-wasm.yml @@ -0,0 +1,132 @@ +--- +name: Release @bitwarden/sdk-wasm +run-name: Release @bitwarden/sdk-wasm ${{ inputs.release_type }} + +on: + workflow_dispatch: + inputs: + release_type: + description: "Release Options" + required: true + default: "Release" + type: choice + options: + - Release + - Dry Run + npm_publish: + description: "Publish to NPM registry" + required: true + default: true + type: boolean + +defaults: + run: + shell: bash + working-directory: languages/js/wasm + +jobs: + setup: + name: Setup + runs-on: ubuntu-22.04 + outputs: + release-version: ${{ steps.version.outputs.version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Branch check + if: ${{ github.event.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: ${{ github.event.inputs.release_type }} + project-type: ts + file: languages/js/wasm/package.json + monorepo: false + + - name: Create GitHub deployment + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: chrnorm/deployment-action@55729fcebec3d284f60f5bcabbd8376437d696b1 # v2.0.7 + id: deployment + with: + token: "${{ secrets.GITHUB_TOKEN }}" + initial-status: "in_progress" + environment: "Bitwarden SDK WASM - Production" + description: "Deployment ${{ steps.version.outputs.version }} from branch ${{ github.ref_name }}" + task: release + + - name: Update deployment status to Success + if: ${{ github.event.inputs.release_type != 'Dry Run' && success() }} + uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + state: "success" + deployment-id: ${{ steps.deployment.outputs.deployment_id }} + + - name: Update deployment status to Failure + if: ${{ github.event.inputs.release_type != 'Dry Run' && failure() }} + uses: chrnorm/deployment-status@2afb7d27101260f4a764219439564d954d10b5b0 # v2.0.1 + with: + token: "${{ secrets.GITHUB_TOKEN }}" + state: "failure" + deployment-id: ${{ steps.deployment.outputs.deployment_id }} + + npm: + name: Publish NPM + runs-on: ubuntu-22.04 + needs: setup + if: inputs.npm_publish + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout repo + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + + - name: Setup Node + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: 18 + cache: "npm" + + - 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: "npm-api-key" + + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@main + with: + workflow: build-wasm.yml + path: ${{ github.workspace }}/languages/js/wasm + workflow_conclusion: success + branch: ${{ github.event.inputs.release_type == 'Dry Run' && 'main' || github.ref_name }} + + - name: Setup NPM + run: | + echo 'registry="https://registry.npmjs.org/"' > ./.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ./.npmrc + + echo 'registry="https://registry.npmjs.org/"' > ~/.npmrc + echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc + env: + NPM_TOKEN: ${{ steps.retrieve-secrets.outputs.npm-api-key }} + + - name: Publish NPM + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: npm publish --access public --registry=https://registry.npmjs.org/ --userconfig=./.npmrc diff --git a/Cargo.lock b/Cargo.lock index a00d91bd8..bda3a9c4a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -522,6 +522,7 @@ dependencies = [ name = "bitwarden-wasm" version = "0.1.0" dependencies = [ + "argon2", "bitwarden-json", "console_error_panic_hook", "console_log", diff --git a/crates/bitwarden-wasm/Cargo.toml b/crates/bitwarden-wasm/Cargo.toml index ff4cf13c3..a4ba8b6ae 100644 --- a/crates/bitwarden-wasm/Cargo.toml +++ b/crates/bitwarden-wasm/Cargo.toml @@ -15,6 +15,10 @@ keywords.workspace = true crate-type = ["cdylib"] [dependencies] +argon2 = { version = ">=0.5.0, <0.6", features = [ + "alloc", + "zeroize", +], default-features = false } bitwarden-json = { path = "../bitwarden-json", features = [ "secrets", "internal", diff --git a/crates/bitwarden-wasm/src/client.rs b/crates/bitwarden-wasm/src/client.rs index 542759731..bca8c2383 100644 --- a/crates/bitwarden-wasm/src/client.rs +++ b/crates/bitwarden-wasm/src/client.rs @@ -1,6 +1,7 @@ extern crate console_error_panic_hook; use std::rc::Rc; +use argon2::{Algorithm, Argon2, Params, Version}; use bitwarden_json::client::Client as JsonClient; use js_sys::Promise; use log::Level; @@ -54,3 +55,27 @@ impl BitwardenClient { }) } } + +#[wasm_bindgen] +pub fn argon2( + password: &[u8], + salt: &[u8], + iterations: u32, + memory: u32, + parallelism: u32, +) -> Result, JsError> { + let argon = Argon2::new( + Algorithm::Argon2id, + Version::V0x13, + Params::new( + memory * 1024, // Convert MiB to KiB + iterations, + parallelism, + Some(32), + )?, + ); + + let mut hash = [0u8; 32]; + argon.hash_password_into(password, salt, &mut hash)?; + Ok(hash.to_vec()) +} diff --git a/languages/js/wasm/package.json b/languages/js/wasm/package.json index 26379c9a6..eadbb5fb3 100644 --- a/languages/js/wasm/package.json +++ b/languages/js/wasm/package.json @@ -4,17 +4,20 @@ "files": [ "bitwarden_wasm_bg.js", "bitwarden_wasm_bg.wasm", + "bitwarden_wasm_bg.wasm.d.ts", + "bitwarden_wasm_bg.wasm.js", "bitwarden_wasm.d.ts", "bitwarden_wasm.js", "index.js", - "node/bitwarden_wasm_bg.wasm.d.ts", "node/bitwarden_wasm_bg.wasm", + "node/bitwarden_wasm_bg.wasm.d.ts", "node/bitwarden_wasm.d.ts", "node/bitwarden_wasm.js" ], "main": "node/bitwarden_wasm.js", "module": "index.js", "types": "bitwarden_wasm.d.ts", + "scripts": {}, "sideEffects": [ "./bitwarden_wasm.js", "./snippets/*" From 38b4d25dd7e2b0c64aa7acca5b92d29f8f639fae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:57:14 -0400 Subject: [PATCH 375/378] [deps]: Update dtolnay/rust-toolchain digest to bb45937 (#713) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-android.yml | 4 ++-- .github/workflows/build-cli.yml | 8 ++++---- .github/workflows/build-napi.yml | 2 +- .github/workflows/build-python-wheels.yml | 2 +- .github/workflows/build-rust-crates.yml | 4 ++-- .github/workflows/build-rust-cross-platform.yml | 2 +- .github/workflows/build-wasm.yml | 2 +- .github/workflows/direct-minimal-versions.yml | 2 +- .github/workflows/generate_schemas.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/memory-testing.yml | 2 +- .github/workflows/minimum-rust-version.yml | 2 +- .github/workflows/publish-rust-crates.yml | 2 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/rust-test.yml | 6 +++--- .github/workflows/version-bump.yml | 2 +- 16 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 8bff66f33..c6b2ae5c5 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -28,7 +28,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable @@ -70,7 +70,7 @@ jobs: fetch-depth: 0 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml index ad3386ddf..37f5c15c8 100644 --- a/.github/workflows/build-cli.yml +++ b/.github/workflows/build-cli.yml @@ -61,7 +61,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -151,7 +151,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -260,7 +260,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -411,7 +411,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/build-napi.yml b/.github/workflows/build-napi.yml index 3737d3767..3bf8f2add 100644 --- a/.github/workflows/build-napi.yml +++ b/.github/workflows/build-napi.yml @@ -61,7 +61,7 @@ jobs: cache-dependency-path: crates/bitwarden-napi/package-lock.json - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-python-wheels.yml b/.github/workflows/build-python-wheels.yml index 1c0459dd6..9578a42d6 100644 --- a/.github/workflows/build-python-wheels.yml +++ b/.github/workflows/build-python-wheels.yml @@ -71,7 +71,7 @@ jobs: node-version: 18 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index dc6db5c91..09952a126 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} @@ -69,7 +69,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/build-rust-cross-platform.yml b/.github/workflows/build-rust-cross-platform.yml index cacacf0e0..ae745cbde 100644 --- a/.github/workflows/build-rust-cross-platform.yml +++ b/.github/workflows/build-rust-cross-platform.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml index 0bc29b4e0..7b5de8435 100644 --- a/.github/workflows/build-wasm.yml +++ b/.github/workflows/build-wasm.yml @@ -34,7 +34,7 @@ jobs: run: npm i -g binaryen - name: Install rust - uses: dtolnay/rust-toolchain@be73d7920c329f220ce78e0234b8f96b7ae60248 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: wasm32-unknown-unknown diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 084ed3cff..3340cd767 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: nightly targets: ${{ matrix.settings.target }} diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 5c62cee01..6513ee998 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8767cba89..cb35c99c1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/memory-testing.yml b/.github/workflows/memory-testing.yml index 1723644f2..d8b6db002 100644 --- a/.github/workflows/memory-testing.yml +++ b/.github/workflows/memory-testing.yml @@ -30,7 +30,7 @@ jobs: sudo apt -y install gdb - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/minimum-rust-version.yml b/.github/workflows/minimum-rust-version.yml index 6213fed32..e371d4026 100644 --- a/.github/workflows/minimum-rust-version.yml +++ b/.github/workflows/minimum-rust-version.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: # Important: When updating this, make sure to update the Readme file # and also the `rust-version` field in all the `Cargo.toml`. diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index d470b5194..705624d7e 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -159,7 +159,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 3b42c3238..a9bc9e3fe 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -142,7 +142,7 @@ jobs: secrets: "cratesio-api-token" - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 06904ee3b..2ea84b6aa 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable @@ -58,7 +58,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable components: llvm-tools @@ -87,7 +87,7 @@ jobs: uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable targets: wasm32-unknown-unknown diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 8b4c33ee3..b2809518b 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Install rust - uses: dtolnay/rust-toolchain@dc6353516c68da0f06325f42ad880f76a5e77ec9 # stable + uses: dtolnay/rust-toolchain@bb45937a053e097f8591208d8e74c90db1873d07 # stable with: toolchain: stable From 9c7a1a0f4d96f841416fb3acf8cc683cd0f7707c Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:17:53 -0400 Subject: [PATCH 376/378] DEVOPS-1939 - Pin actions to main (#717) --- .github/workflows/publish-php.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-php.yml b/.github/workflows/publish-php.yml index 2b716c893..dca601213 100644 --- a/.github/workflows/publish-php.yml +++ b/.github/workflows/publish-php.yml @@ -86,7 +86,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -167,7 +167,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope" @@ -247,7 +247,7 @@ jobs: - name: Retrieve secrets id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@2e9a183f0543d25868fbb784dfe205fea6ff09a5 + uses: bitwarden/gh-actions/get-keyvault-secrets@main with: keyvault: ${{ env._KEY_VAULT }} secrets: "github-pat-bitwarden-devops-bot-repo-scope, From 0e7bc70a2f91a99f64eea2703f064463907cf1bf Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 16 Apr 2024 13:45:17 +0200 Subject: [PATCH 377/378] [PM-7447] Publish prerelease to GitHub packages (#716) We have a desire to publish every build of the wasm to gh package for faster use in the clients repository. --- .github/workflows/build-wasm.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml index 7b5de8435..9f1752a06 100644 --- a/.github/workflows/build-wasm.yml +++ b/.github/workflows/build-wasm.yml @@ -28,6 +28,7 @@ jobs: uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: 18 + registry-url: "https://npm.pkg.github.com" cache: "npm" - name: Install dependencies @@ -56,3 +57,20 @@ jobs: name: sdk-bitwarden-wasm path: ${{ github.workspace }}/languages/js/wasm/* if-no-files-found: error + + - name: Set version + if: ${{ github.ref == 'refs/head/main' }} + # Fetches current version from registry and uses prerelease to bump it + run: | + npm version --no-git-tag-version $(npm view @bitwarden/sdk-wasm@latest version) + npm version --no-git-tag-version prerelease + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + working-directory: languages/js/wasm + + - name: Publish NPM + if: ${{ github.ref == 'refs/head/main' }} + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + working-directory: languages/js/wasm From 21ad6b2387f9a971d2bab5fec8ddc04338589958 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Tue, 16 Apr 2024 15:12:39 +0200 Subject: [PATCH 378/378] Fix if condition on wasm workflow (#718) Should be `refs/heads/main` not `refs/head/main`. --- .github/workflows/build-wasm.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-wasm.yml b/.github/workflows/build-wasm.yml index 9f1752a06..87e14d2e2 100644 --- a/.github/workflows/build-wasm.yml +++ b/.github/workflows/build-wasm.yml @@ -59,7 +59,7 @@ jobs: if-no-files-found: error - name: Set version - if: ${{ github.ref == 'refs/head/main' }} + if: ${{ github.ref == 'refs/heads/main' }} # Fetches current version from registry and uses prerelease to bump it run: | npm version --no-git-tag-version $(npm view @bitwarden/sdk-wasm@latest version) @@ -69,7 +69,7 @@ jobs: working-directory: languages/js/wasm - name: Publish NPM - if: ${{ github.ref == 'refs/head/main' }} + if: ${{ github.ref == 'refs/heads/main' }} run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Changelog

Sourced from mio's changelog.

0.8.11