diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b10ec1b4..6968746f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,9 +4,19 @@ # # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +# BRE for publish workflow changes +.github/workflows/publish-*.yml @bitwarden/dept-bre -# DevOps for Actions and other workflow changes. -.github/workflows @bitwarden/dept-devops +# Shared workflows ownership + +## Multiple owners +.github/workflows/build-android.yml +.github/workflows/build-rust-crates.yml +.github/workflows/build-swift.yml +.github/workflows/build-wasm-internal.yml +.github/workflows/release-rust-crates.yml +.github/workflows/release-swift.yml +.github/workflows/version-bump.yml # Secrets Manager team crates/bitwarden-sm @bitwarden/team-secrets-manager-dev diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index 7607d530..49ee2084 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -1,4 +1,3 @@ ---- name: Build Android on: @@ -25,7 +24,7 @@ jobs: - target: i686-linux-android steps: - name: Checkout repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -33,7 +32,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: ${{ matrix.settings.target }}-cargo @@ -46,7 +45,7 @@ jobs: run: cross build -p bitwarden-uniffi --release --target=${{ matrix.settings.target }} - name: Upload artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: android-${{ matrix.settings.target }} path: ./target/${{ matrix.settings.target }}/release/libbitwarden_uniffi.so @@ -57,14 +56,14 @@ jobs: needs: build steps: - name: Checkout repo (PR) - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 if: github.event_name == 'push' with: fetch-depth: 0 @@ -75,7 +74,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: cargo-combine-cache diff --git a/.github/workflows/build-rust-crates.yml b/.github/workflows/build-rust-crates.yml index 8400fcbf..bc00dd97 100644 --- a/.github/workflows/build-rust-crates.yml +++ b/.github/workflows/build-rust-crates.yml @@ -1,4 +1,3 @@ ---- name: Build Rust crates on: @@ -34,7 +33,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -42,7 +41,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Build run: cargo build -p ${{ matrix.package }} --release @@ -56,7 +55,7 @@ jobs: needs: build steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -64,7 +63,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/build-swift.yml b/.github/workflows/build-swift.yml index 37224134..93cb314c 100644 --- a/.github/workflows/build-swift.yml +++ b/.github/workflows/build-swift.yml @@ -1,4 +1,3 @@ ---- name: Build Swift Package on: @@ -17,7 +16,7 @@ jobs: package_version: ${{ steps.retrieve-version.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Get Package Version id: retrieve-version @@ -33,7 +32,7 @@ jobs: _VERSION: ${{ needs.version.outputs.package_version }} steps: - name: Checkout repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -41,7 +40,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: sdk-swift-cargo @@ -67,14 +66,14 @@ jobs: cp -rf languages/swift/BitwardenFFI.xcframework artifacts - name: Upload BitwardenFFI.xcframework artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: BitwardenFFI-${{ env._VERSION }}-${{ steps.build.outputs.short-sha }}.xcframework path: artifacts if-no-files-found: error - name: Upload BitwardenSdk sources - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: BitwardenSdk-${{ env._VERSION }}-${{ steps.build.outputs.short-sha }}-sources path: languages/swift/Sources/BitwardenSdk diff --git a/.github/workflows/build-wasm-internal.yml b/.github/workflows/build-wasm-internal.yml index 99fe06c4..2262babc 100644 --- a/.github/workflows/build-wasm-internal.yml +++ b/.github/workflows/build-wasm-internal.yml @@ -1,4 +1,3 @@ ---- name: Build @bitwarden/sdk-internal on: @@ -22,7 +21,7 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Setup Node uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 @@ -37,22 +36,22 @@ jobs: - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable with: - toolchain: stable + toolchain: 1.81.0 targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: wasm-cargo-cache - name: Install wasm-bindgen-cli - run: cargo install wasm-bindgen-cli + run: cargo install wasm-bindgen-cli --version 0.2.95 - name: Build run: ./build.sh -r - name: Upload artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: sdk-internal path: ${{ github.workspace }}/languages/js/sdk-internal/* diff --git a/.github/workflows/cloc.yml b/.github/workflows/cloc.yml index 644dc0bf..c78c2855 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@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up cloc run: | diff --git a/.github/workflows/delete-old-packages.yml b/.github/workflows/delete-old-packages.yml index b3be807a..f690e801 100644 --- a/.github/workflows/delete-old-packages.yml +++ b/.github/workflows/delete-old-packages.yml @@ -1,4 +1,3 @@ ---- name: Delete old packages on: diff --git a/.github/workflows/direct-minimal-versions.yml b/.github/workflows/direct-minimal-versions.yml index 22feb04c..66623ed6 100644 --- a/.github/workflows/direct-minimal-versions.yml +++ b/.github/workflows/direct-minimal-versions.yml @@ -1,4 +1,3 @@ ---- name: Direct Minimum Version on: @@ -36,7 +35,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -45,7 +44,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: dmv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml index a98c4ae1..40ddfe77 100644 --- a/.github/workflows/enforce-labels.yml +++ b/.github/workflows/enforce-labels.yml @@ -1,4 +1,3 @@ ---- name: Enforce PR labels on: diff --git a/.github/workflows/generate_schemas.yml b/.github/workflows/generate_schemas.yml index 434174c7..66e6f450 100644 --- a/.github/workflows/generate_schemas.yml +++ b/.github/workflows/generate_schemas.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -37,61 +37,61 @@ jobs: run: npm ci - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: NPM Schemas run: npm run schemas - name: Upload ts schemas artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: schemas.rb path: ${{ github.workspace }}/languages/ruby/bitwarden_sdk_secrets/lib/schemas.rb if-no-files-found: error - name: Upload json schemas artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: sdk-schemas-json path: ${{ github.workspace }}/support/schemas/* if-no-files-found: error - name: Upload Go schemas artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: schemas.go path: ${{ github.workspace }}/languages/go/schema.go - name: Upload java schemas artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: sdk-schemas-java path: ${{ github.workspace }}/languages/java/src/main/java/com/bitwarden/sdk/schema/* if-no-files-found: error - name: Upload cpp schemas artifact - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: sdk-schemas-cpp path: ${{ github.workspace }}/languages/cpp/include/schemas.hpp diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a12e263c..a8d14a69 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -30,7 +30,7 @@ jobs: rustup component add rustfmt --toolchain nightly-x86_64-unknown-linux-gnu - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Cargo fmt run: cargo +nightly fmt --check @@ -45,7 +45,7 @@ jobs: RUSTFLAGS: "-D warnings" - name: Upload Clippy results to GitHub - uses: github/codeql-action/upload-sarif@461ef6c76dfe95d5c364de2f431ddbd31a417628 # v3.26.9 + uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: sarif_file: clippy_result.sarif diff --git a/.github/workflows/memory-testing.yml b/.github/workflows/memory-testing.yml index 41b15853..619fbb46 100644 --- a/.github/workflows/memory-testing.yml +++ b/.github/workflows/memory-testing.yml @@ -1,4 +1,3 @@ ---- name: Test for memory leaks on: @@ -22,7 +21,7 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Set up gdb run: | @@ -35,7 +34,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: memtest-cargo diff --git a/.github/workflows/minimum-rust-version.yml b/.github/workflows/minimum-rust-version.yml index fa95eb0b..812822c6 100644 --- a/.github/workflows/minimum-rust-version.yml +++ b/.github/workflows/minimum-rust-version.yml @@ -1,4 +1,3 @@ ---- name: Minimum Rust Version on: @@ -27,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -38,7 +37,7 @@ jobs: targets: ${{ matrix.settings.target }} - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 with: key: msrv-${{ matrix.settings.target }}-cargo-${{ matrix.settings.os }} diff --git a/.github/workflows/publish-internal.yml b/.github/workflows/publish-internal.yml index 13f3a9d9..eef5b4d0 100644 --- a/.github/workflows/publish-internal.yml +++ b/.github/workflows/publish-internal.yml @@ -1,4 +1,3 @@ ---- name: Publish @bitwarden/sdk-internal run-name: Publish @bitwarden/sdk-internal ${{ inputs.release_type }} @@ -27,7 +26,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Branch check if: ${{ inputs.release_type != 'Dry Run' }} @@ -45,10 +44,10 @@ jobs: needs: setup steps: - name: Checkout repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Setup Node - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version: 20 diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index bb79aad2..30921f6b 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -1,4 +1,3 @@ ---- name: Publish Rust crates run-name: Publish Rust crates ${{ inputs.release_type }} @@ -29,7 +28,7 @@ jobs: release-tag: ${{ steps.version-output.outputs.tag_name }} steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Branch check if: ${{ inputs.release_type != 'Dry Run' }} @@ -63,7 +62,7 @@ jobs: needs: setup steps: - name: Checkout - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ needs.setup.outputs.release-tag }} @@ -85,7 +84,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Install cargo-release run: cargo install cargo-release diff --git a/.github/workflows/release-ruby.yml b/.github/workflows/release-ruby.yml deleted file mode 100644 index 9c3e82b7..00000000 --- a/.github/workflows/release-ruby.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Release Ruby SDK -run-name: Release Ruby SDK ${{ inputs.release_type }} - -on: - workflow_dispatch: - inputs: - release_type: - description: "Release Options" - required: true - default: "Release" - type: choice - options: - - Release - - Dry Run - -jobs: - setup: - name: Setup - runs-on: ubuntu-22.04 - outputs: - version: ${{ steps.version.outputs.version }} - steps: - - name: Checkout repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Branch check - if: ${{ inputs.release_type != 'Dry Run' }} - run: | - if [[ "$GITHUB_REF" != "refs/heads/main" ]]; then - echo "===================================" - echo "[!] Can only release from the 'main' branch" - echo "===================================" - exit 1 - fi - - - name: Get version - id: version - run: | - VERSION=$(cat languages/ruby/lib/version.rb | grep -Eo 'VERSION = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') - echo "version=$VERSION" >> $GITHUB_OUTPUT - - release: - name: Create GitHub release - runs-on: ubuntu-22.04 - needs: setup - steps: - - name: Checkout Repository - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - - - name: Download ruby artifact - uses: bitwarden/gh-actions/download-artifacts@main - with: - workflow: build-ruby.yml - workflow_conclusion: success - branch: main - artifacts: bitwarden-sdk-secrets - - - name: Create release - if: ${{ inputs.release_type != 'Dry Run' }} - uses: ncipollo/release-action@2c591bcc8ecdcd2db72b97d6147f871fcd833ba5 # v1.14.0 - env: - PKG_VERSION: ${{ needs.setup.outputs.version }} - with: - commit: ${{ github.sha }} - tag: ruby-v${{ env.PKG_VERSION }} - name: Ruby v${{ env.PKG_VERSION }} - body: "" - token: ${{ secrets.GITHUB_TOKEN }} - draft: true - artifacts: | - bitwarden-sdk-secrets-${{ env.PKG_VERSION }}.gem diff --git a/.github/workflows/release-rust-crates.yml b/.github/workflows/release-rust-crates.yml index 54845e14..abf48a50 100644 --- a/.github/workflows/release-rust-crates.yml +++ b/.github/workflows/release-rust-crates.yml @@ -21,7 +21,7 @@ jobs: release-version: ${{ steps.version.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Branch check if: ${{ inputs.release_type != 'Dry Run' }} diff --git a/.github/workflows/release-swift.yml b/.github/workflows/release-swift.yml index 351581a7..c5c25d65 100644 --- a/.github/workflows/release-swift.yml +++ b/.github/workflows/release-swift.yml @@ -1,4 +1,3 @@ ---- name: Release Swift Package on: @@ -42,7 +41,7 @@ jobs: swift_checksum: ${{ steps.calculate-swift-checksum.outputs.checksum }} steps: - name: Checkout repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Get version id: version @@ -114,7 +113,7 @@ jobs: _BUILD_RUN_ID: ${{ needs.validate.outputs.run_id }} steps: - name: Checkout SDK repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: sdk @@ -142,7 +141,7 @@ jobs: github-pat-bitwarden-devops-bot-repo-scope" - name: Checkout SDK-Swift repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: repository: bitwarden/sdk-swift path: sdk-swift diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 2ddb853c..afc144a2 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -34,7 +34,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -42,7 +42,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Test # Termporarily exclude NAPI due to a test error on windows @@ -54,7 +54,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -63,7 +63,7 @@ jobs: components: llvm-tools - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Install cargo-llvm-cov run: cargo install cargo-llvm-cov --version 0.5.38 @@ -72,7 +72,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@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 + uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} @@ -83,7 +83,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable @@ -92,7 +92,7 @@ jobs: targets: wasm32-unknown-unknown - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Check run: cargo check -p bitwarden-wasm --target wasm32-unknown-unknown diff --git a/.github/workflows/rustdoc.yml b/.github/workflows/rustdoc.yml index 45ab6d07..afa12fd5 100644 --- a/.github/workflows/rustdoc.yml +++ b/.github/workflows/rustdoc.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 - name: Install rust uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a # stable diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 193c9fcf..f337e17a 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -26,12 +26,12 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ github.event.pull_request.head.sha }} - name: Scan with Checkmarx - uses: checkmarx/ast-github-action@9fda5a4a2c297608117a5a56af424502a9192e57 # 2.0.34 + uses: checkmarx/ast-github-action@f0869bd1a37fddc06499a096101e6c900e815d81 # 2.0.36 env: INCREMENTAL: "${{ contains(github.event_name, 'pull_request') && '--sast-incremental' || '' }}" with: @@ -46,7 +46,7 @@ jobs: --output-path . ${{ env.INCREMENTAL }} - name: Upload Checkmarx results to GitHub - uses: github/codeql-action/upload-sarif@461ef6c76dfe95d5c364de2f431ddbd31a417628 # v3.26.9 + uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: sarif_file: cx_result.sarif @@ -60,13 +60,13 @@ jobs: steps: - name: Check out repo - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - name: Scan with SonarCloud - uses: sonarsource/sonarcloud-github-action@eb211723266fe8e83102bac7361f0a05c3ac1d1b # v3.0.0 + uses: sonarsource/sonarcloud-github-action@383f7e52eae3ab0510c3cb0e7d9d150bbaeab838 # v3.1.0 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 960febd4..6a24d7df 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -1,4 +1,3 @@ ---- name: Version Bump run-name: Version Bump - ${{ inputs.project }} - v${{ inputs.version_number }} @@ -30,7 +29,7 @@ jobs: toolchain: stable - name: Cache cargo registry - uses: Swatinem/rust-cache@23bce251a8cd2ffc3c1075eaa2367cf899916d84 # v2.7.3 + uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab # v2.7.5 - name: Install cargo-release run: cargo install cargo-edit --locked @@ -50,7 +49,7 @@ jobs: github-pat-bitwarden-devops-bot-repo-scope" - name: Checkout Branch - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: main repository: bitwarden/sdk @@ -165,7 +164,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Branch - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0 + uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: main diff --git a/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml deleted file mode 100644 index 24f10f1e..00000000 --- a/.github/workflows/workflow-linter.yml +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: Workflow linter - -on: - pull_request: - paths: - - .github/workflows/** - -jobs: - call-workflow: - name: Lint - uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main diff --git a/Cargo.lock b/Cargo.lock index a73f7c68..be749ab9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,9 +127,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "argon2" @@ -167,7 +167,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -216,7 +216,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -406,8 +406,10 @@ dependencies = [ "sha2", "subtle", "thiserror", + "tsify-next", "uniffi", "uuid", + "wasm-bindgen", "zeroize", ] @@ -553,8 +555,10 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tsify-next", "uniffi", "uuid", + "wasm-bindgen", ] [[package]] @@ -562,6 +566,8 @@ name = "bitwarden-wasm-internal" version = "0.1.0" dependencies = [ "bitwarden-core", + "bitwarden-crypto", + "bitwarden-vault", "console_error_panic_hook", "console_log", "js-sys", @@ -683,9 +689,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -786,7 +792,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1081,7 +1087,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1092,7 +1098,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1171,7 +1177,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1181,7 +1187,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1401,7 +1407,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -1659,9 +1665,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1883,9 +1889,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.71" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb94a0ffd3f3ee755c20f7d8752f45cac88605a4dcf808abcff72873296ec7b" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1901,9 +1907,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" @@ -2409,9 +2415,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -2681,9 +2687,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.14" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "once_cell", "ring", @@ -2717,9 +2723,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-platform-verifier" @@ -2761,9 +2767,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "ryu" @@ -2812,7 +2818,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -2838,7 +2844,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -2917,7 +2923,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -2928,14 +2934,14 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "indexmap 2.6.0", "itoa", @@ -2963,7 +2969,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3005,7 +3011,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3185,7 +3191,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3198,7 +3204,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3228,9 +3234,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", @@ -3285,7 +3291,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3378,7 +3384,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3488,7 +3494,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3499,12 +3505,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -3603,7 +3606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2c801f0f05b06df456a2da4c41b9c2c4fdccc6b9916643c6c67275c4c9e4d07" dependencies = [ "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3635,7 +3638,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.79", + "syn 2.0.82", "toml", "uniffi_meta", ] @@ -3703,9 +3706,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", "serde", @@ -3738,7 +3741,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -3780,9 +3783,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef073ced962d62984fb38a36e5fdc1a2b23c9e0e1fa0689bb97afa4202ef6887" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -3793,24 +3796,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4bfab14ef75323f4eb75fa52ee0a3fb59611977fd3240da19b2cf36ff85030e" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65471f79c1022ffa5291d33520cbbb53b7687b01c2f8e83b57d102eed7ed479d" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -3820,9 +3823,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7bec9830f60924d9ceb3ef99d55c155be8afa76954edffbb5936ff4509474e7" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3830,28 +3833,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c74f6e152a76a2ad448e223b0fc0b6b5747649c3d769cc6bf45737bf97d0ed6" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.94" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42f6c679374623f295a8623adfe63d9284091245c3504bde47c17a3ce2777d9" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "web-sys" -version = "0.3.71" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44188d185b5bdcae1052d08bcbcf9091a5524038d4572cc4f4f2bb9d5554ddd9" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -4135,7 +4138,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] @@ -4156,7 +4159,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.79", + "syn 2.0.82", ] [[package]] diff --git a/crates/bitwarden-core/src/mobile/crypto.rs b/crates/bitwarden-core/src/mobile/crypto.rs index 2aae903c..1b027df4 100644 --- a/crates/bitwarden-core/src/mobile/crypto.rs +++ b/crates/bitwarden-core/src/mobile/crypto.rs @@ -6,6 +6,8 @@ use bitwarden_crypto::{ }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +#[cfg(feature = "wasm")] +use {tsify_next::Tsify, wasm_bindgen::prelude::*}; use crate::{ client::{encryption_settings::EncryptionSettingsError, LoginMethod, UserLoginMethod}, @@ -16,6 +18,7 @@ use crate::{ #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct InitUserCryptoRequest { /// The user's KDF parameters, as received from the prelogin request pub kdf_params: Kdf, @@ -30,6 +33,7 @@ pub struct InitUserCryptoRequest { #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub enum InitUserCryptoMethod { Password { /// The user's master password @@ -73,6 +77,7 @@ pub enum InitUserCryptoMethod { #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub enum AuthRequestMethod { UserKey { /// User Key protected by the private key provided in `AuthRequestResponse`. @@ -185,6 +190,7 @@ pub async fn initialize_user_crypto( #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct InitOrgCryptoRequest { /// The encryption keys for all the organizations the user is a part of pub organization_keys: HashMap, diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 3254640f..7671a776 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -15,6 +15,7 @@ keywords.workspace = true [features] default = [] +wasm = ["dep:tsify-next", "dep:wasm-bindgen"] # WASM support uniffi = ["dep:uniffi"] # Uniffi bindings no-memory-hardening = [] # Disable memory hardening features @@ -42,8 +43,10 @@ sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" subtle = ">=2.5.0, <3.0" thiserror = { workspace = true } +tsify-next = { workspace = true, optional = true } uniffi = { workspace = true, optional = true } uuid = { workspace = true } +wasm-bindgen = { workspace = true, optional = true } zeroize = { version = ">=1.7.0, <2.0", features = ["derive", "aarch64"] } [dev-dependencies] diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index f9bda838..9d4f0d63 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -11,11 +11,16 @@ use crate::{ rsa::encrypt_rsa2048_oaep_sha1, AsymmetricCryptoKey, AsymmetricEncryptable, KeyDecryptable, }; - // This module is a workaround to avoid deprecated warnings that come from the ZeroizeOnDrop // macro expansion #[allow(deprecated)] mod internal { + #[cfg(feature = "wasm")] + #[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)] + const TS_CUSTOM_TYPES: &'static str = r#" + export type AsymmetricEncString = string; + "#; + /// # Encrypted string primitive /// /// [AsymmetricEncString] is a Bitwarden specific primitive that represents an asymmetrically diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index 1fc9b3a9..69711f74 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -11,6 +11,12 @@ use crate::{ KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, }; +#[cfg(feature = "wasm")] +#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)] +const TS_CUSTOM_TYPES: &'static str = r#" +export type EncString = string; +"#; + /// # Encrypted string primitive /// /// [EncString] is a Bitwarden specific primitive that represents a symmetrically encrypted string. diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index fc9762c3..7a1e4959 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -5,6 +5,8 @@ use generic_array::{typenum::U32, GenericArray}; use rand::Rng; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +#[cfg(feature = "wasm")] +use {tsify_next::Tsify, wasm_bindgen::prelude::*}; use super::utils::{derive_kdf_key, stretch_kdf_key}; use crate::{util, CryptoError, EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey}; @@ -16,6 +18,7 @@ use crate::{util, CryptoError, EncString, KeyDecryptable, Result, SymmetricCrypt #[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub enum Kdf { PBKDF2 { iterations: NonZeroU32, diff --git a/crates/bitwarden-exporters/resources/json_export.json b/crates/bitwarden-exporters/resources/json_export.json index ad538055..27a0921d 100644 --- a/crates/bitwarden-exporters/resources/json_export.json +++ b/crates/bitwarden-exporters/resources/json_export.json @@ -141,6 +141,26 @@ "revisionDate": "2024-01-30T17:54:50.706Z", "creationDate": "2024-01-30T17:54:50.706Z", "deletedDate": null + }, + { + "id": "646594a9-a9cb-4082-9d57-0024c3fbcaa9", + "folderId": null, + "organizationId": null, + "collectionIds": null, + "name": "My ssh key", + "notes": null, + "type": 5, + "sshKey": { + "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\nQyNTUxOQAAACBinNE5chMtCHh3BV0H1+CpPlEQBwR5cD+Xb9i8MaHGiwAAAKAy48fwMuPH\n8AAAAAtzc2gtZWQyNTUxOQAAACBinNE5chMtCHh3BV0H1+CpPlEQBwR5cD+Xb9i8MaHGiw\nAAAEAYUCIdfLI14K3XIy9V0FDZLQoZ9gcjOnvFjb4uA335HmKc0TlyEy0IeHcFXQfX4Kk+\nURAHBHlwP5dv2LwxocaLAAAAHHF1ZXh0ZW5ATWFjQm9vay1Qcm8tMTYubG9jYWwB\n-----END OPENSSH PRIVATE KEY-----", + "publicKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGKc0TlyEy0IeHcFXQfX4Kk+URAHBHlwP5dv2LwxocaL", + "fingerprint": "SHA256:1JjFjvPRkj1Gbf2qRP1dgHiIzEuNAEvp+92x99jw3K0" + }, + "favorite": false, + "reprompt": 0, + "passwordHistory": null, + "revisionDate": "2024-01-30T11:25:25.466Z", + "creationDate": "2024-01-30T11:25:25.466Z", + "deletedDate": null } ] } \ No newline at end of file diff --git a/crates/bitwarden-exporters/src/json.rs b/crates/bitwarden-exporters/src/json.rs index 3f6c72c1..7ed85d45 100644 --- a/crates/bitwarden-exporters/src/json.rs +++ b/crates/bitwarden-exporters/src/json.rs @@ -2,7 +2,9 @@ use chrono::{DateTime, Utc}; use thiserror::Error; use uuid::Uuid; -use crate::{Card, Cipher, CipherType, Field, Folder, Identity, Login, LoginUri, SecureNote}; +use crate::{ + Card, Cipher, CipherType, Field, Folder, Identity, Login, LoginUri, SecureNote, SshKey, +}; #[derive(Error, Debug)] pub enum JsonError { @@ -69,6 +71,8 @@ struct JsonCipher { card: Option, #[serde(skip_serializing_if = "Option::is_none")] secure_note: Option, + #[serde(skip_serializing_if = "Option::is_none")] + ssh_key: Option, favorite: bool, reprompt: u8, @@ -206,6 +210,24 @@ impl From for JsonIdentity { } } +#[derive(serde::Serialize)] +#[serde(rename_all = "camelCase")] +struct JsonSshKey { + private_key: Option, + public_key: Option, + fingerprint: Option, +} + +impl From for JsonSshKey { + fn from(ssh_key: SshKey) -> Self { + JsonSshKey { + private_key: ssh_key.private_key, + public_key: ssh_key.public_key, + fingerprint: ssh_key.fingerprint, + } + } +} + #[derive(serde::Serialize)] #[serde(rename_all = "camelCase")] struct JsonField { @@ -233,13 +255,15 @@ impl From for JsonCipher { CipherType::SecureNote(_) => 2, CipherType::Card(_) => 3, CipherType::Identity(_) => 4, + CipherType::SshKey(_) => 5, }; - 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())), + let (login, secure_note, card, identity, ssh_key) = match cipher.r#type { + CipherType::Login(l) => (Some((*l).into()), None, None, None, None), + CipherType::SecureNote(s) => (None, Some((*s).into()), None, None, None), + CipherType::Card(c) => (None, None, Some((*c).into()), None, None), + CipherType::Identity(i) => (None, None, None, Some((*i).into()), None), + CipherType::SshKey(ssh) => (None, None, None, None, Some((*ssh).into())), }; JsonCipher { @@ -254,6 +278,7 @@ impl From for JsonCipher { identity, card, secure_note, + ssh_key, favorite: cipher.favorite, reprompt: cipher.reprompt, fields: cipher.fields.into_iter().map(|f| f.into()).collect(), @@ -594,6 +619,60 @@ mod tests { ) } + #[test] + fn test_convert_ssh_key() { + let cipher = Cipher { + id: "23f0f877-42b1-4820-a850-b10700bc41eb".parse().unwrap(), + folder_id: None, + + name: "My ssh key".to_string(), + notes: None, + + r#type: CipherType::SshKey(Box::new(SshKey { + private_key: Some("private".to_string()), + public_key: Some("public".to_string()), + fingerprint: Some("fingerprint".to_string()), + })), + + 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": 5, + "reprompt": 0, + "name": "My ssh key", + "notes": null, + "sshKey": { + "privateKey": "private", + "publicKey": "public", + "fingerprint": "fingerprint" + }, + "favorite": false, + "collectionIds": null + }"#; + + assert_eq!( + json.parse::().unwrap(), + expected.parse::().unwrap() + ) + } + #[test] pub fn test_export() { let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -750,6 +829,28 @@ mod tests { creation_date: "2024-01-30T17:54:50.706Z".parse().unwrap(), deleted_date: None, }, + Cipher { + id: "646594a9-a9cb-4082-9d57-0024c3fbcaa9".parse().unwrap(), + folder_id: None, + + name: "My ssh key".to_string(), + notes: None, + + r#type: CipherType::SshKey(Box::new(SshKey { + private_key: Some("-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\nQyNTUxOQAAACBinNE5chMtCHh3BV0H1+CpPlEQBwR5cD+Xb9i8MaHGiwAAAKAy48fwMuPH\n8AAAAAtzc2gtZWQyNTUxOQAAACBinNE5chMtCHh3BV0H1+CpPlEQBwR5cD+Xb9i8MaHGiw\nAAAEAYUCIdfLI14K3XIy9V0FDZLQoZ9gcjOnvFjb4uA335HmKc0TlyEy0IeHcFXQfX4Kk+\nURAHBHlwP5dv2LwxocaLAAAAHHF1ZXh0ZW5ATWFjQm9vay1Qcm8tMTYubG9jYWwB\n-----END OPENSSH PRIVATE KEY-----".to_string()), + public_key: Some("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGKc0TlyEy0IeHcFXQfX4Kk+URAHBHlwP5dv2LwxocaL".to_string()), + fingerprint: Some("SHA256:1JjFjvPRkj1Gbf2qRP1dgHiIzEuNAEvp+92x99jw3K0".to_string()), + })), + + 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, + } ], ) .unwrap(); diff --git a/crates/bitwarden-exporters/src/lib.rs b/crates/bitwarden-exporters/src/lib.rs index 75b0503e..f6bb8dbf 100644 --- a/crates/bitwarden-exporters/src/lib.rs +++ b/crates/bitwarden-exporters/src/lib.rs @@ -70,6 +70,7 @@ pub enum CipherType { SecureNote(Box), Card(Box), Identity(Box), + SshKey(Box), } impl fmt::Display for CipherType { @@ -79,6 +80,7 @@ impl fmt::Display for CipherType { CipherType::SecureNote(_) => write!(f, "note"), CipherType::Card(_) => write!(f, "card"), CipherType::Identity(_) => write!(f, "identity"), + CipherType::SshKey(_) => write!(f, "ssh_key"), } } } @@ -132,3 +134,12 @@ pub struct Identity { pub passport_number: Option, pub license_number: Option, } + +pub struct SshKey { + /// [OpenSSH private key](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key), in PEM encoding. + pub private_key: Option, + /// Ssh public key (ed25519/rsa) according to [RFC4253](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6) + pub public_key: Option, + /// SSH fingerprint using SHA256 in the format: `SHA256:BASE64_ENCODED_FINGERPRINT` + pub fingerprint: Option, +} diff --git a/crates/bitwarden-exporters/src/models.rs b/crates/bitwarden-exporters/src/models.rs index 1d56e723..1d2e80d9 100644 --- a/crates/bitwarden-exporters/src/models.rs +++ b/crates/bitwarden-exporters/src/models.rs @@ -74,6 +74,14 @@ impl TryFrom for crate::Cipher { license_number: i.license_number, })) } + CipherType::SshKey => { + let s = require!(value.ssh_key); + crate::CipherType::SshKey(Box::new(crate::SshKey { + private_key: s.private_key, + public_key: s.public_key, + fingerprint: s.fingerprint, + })) + } }; Ok(Self { @@ -172,6 +180,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: true, diff --git a/crates/bitwarden-vault/Cargo.toml b/crates/bitwarden-vault/Cargo.toml index 4c41e139..3c7757e2 100644 --- a/crates/bitwarden-vault/Cargo.toml +++ b/crates/bitwarden-vault/Cargo.toml @@ -19,6 +19,7 @@ uniffi = [ "bitwarden-crypto/uniffi", "dep:uniffi", ] # Uniffi bindings +wasm = ["dep:tsify-next", "dep:wasm-bindgen"] # WASM support [dependencies] base64 = ">=0.22.1, <0.23" @@ -38,6 +39,8 @@ sha2 = ">=0.10.6, <0.11" thiserror = { workspace = true } uniffi = { version = "=0.28.1", optional = true } uuid = { workspace = true } +tsify-next = { workspace = true, optional = true } +wasm-bindgen = { workspace = true, optional = true } [dev-dependencies] tokio = { workspace = true, features = ["rt"] } diff --git a/crates/bitwarden-vault/src/cipher/attachment.rs b/crates/bitwarden-vault/src/cipher/attachment.rs index d1a058c0..bf589879 100644 --- a/crates/bitwarden-vault/src/cipher/attachment.rs +++ b/crates/bitwarden-vault/src/cipher/attachment.rs @@ -208,6 +208,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: false, @@ -258,6 +259,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: false, @@ -312,6 +314,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: false, diff --git a/crates/bitwarden-vault/src/cipher/cipher.rs b/crates/bitwarden-vault/src/cipher/cipher.rs index 8ac4bfe7..846d332c 100644 --- a/crates/bitwarden-vault/src/cipher/cipher.rs +++ b/crates/bitwarden-vault/src/cipher/cipher.rs @@ -14,7 +14,7 @@ use uuid::Uuid; use super::{ attachment, card, field, identity, local_data::{LocalData, LocalDataView}, - secure_note, + secure_note, ssh_key, }; use crate::{ password_history, Fido2CredentialFullView, Fido2CredentialView, Login, LoginView, @@ -41,6 +41,7 @@ pub enum CipherType { SecureNote = 2, Card = 3, Identity = 4, + SshKey = 5, } #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema, PartialEq)] @@ -72,6 +73,7 @@ pub struct Cipher { pub identity: Option, pub card: Option, pub secure_note: Option, + pub ssh_key: Option, pub favorite: bool, pub reprompt: CipherRepromptType, @@ -109,6 +111,7 @@ pub struct CipherView { pub identity: Option, pub card: Option, pub secure_note: Option, + pub ssh_key: Option, pub favorite: bool, pub reprompt: CipherRepromptType, @@ -137,6 +140,7 @@ pub enum CipherListViewType { SecureNote, Card, Identity, + SshKey, } #[derive(Serialize, Deserialize, Debug, JsonSchema, PartialEq)] @@ -211,6 +215,7 @@ impl KeyEncryptable for CipherView { identity: self.identity.encrypt_with_key(key)?, card: self.card.encrypt_with_key(key)?, secure_note: self.secure_note.encrypt_with_key(key)?, + ssh_key: self.ssh_key.encrypt_with_key(key)?, favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, @@ -245,6 +250,7 @@ impl KeyDecryptable for Cipher { 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(), + ssh_key: self.ssh_key.decrypt_with_key(key).ok().flatten(), favorite: self.favorite, reprompt: self.reprompt, organization_use_totp: self.organization_use_totp, @@ -329,6 +335,18 @@ impl Cipher { .transpose()?, ) } + CipherType::SshKey => { + let Some(ssh_key) = &self.ssh_key else { + return Ok(String::new()); + }; + + ssh_key + .fingerprint + .as_ref() + .map(|c| c.decrypt_with_key(key)) + .transpose()? + .unwrap_or_default() + } }) } } @@ -553,6 +571,7 @@ impl KeyDecryptable for Cipher { CipherType::SecureNote => CipherListViewType::SecureNote, CipherType::Card => CipherListViewType::Card, CipherType::Identity => CipherListViewType::Identity, + CipherType::SshKey => CipherListViewType::SshKey, }, favorite: self.favorite, reprompt: self.reprompt, @@ -614,6 +633,8 @@ impl TryFrom for Cipher { 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()?, + // TODO: add ssh_key when api bindings have been updated + ssh_key: None, favorite: cipher.favorite.unwrap_or(false), reprompt: cipher .reprompt @@ -650,6 +671,7 @@ impl From for CipherType { bitwarden_api_api::models::CipherType::SecureNote => CipherType::SecureNote, bitwarden_api_api::models::CipherType::Card => CipherType::Card, bitwarden_api_api::models::CipherType::Identity => CipherType::Identity, + // TODO: add ssh_key when api bindings have been updated } } } @@ -669,6 +691,7 @@ mod tests { use std::collections::HashMap; use attachment::AttachmentView; + use ssh_key::SshKey; use super::*; use crate::Fido2Credential; @@ -695,6 +718,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: true, @@ -753,6 +777,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: false, @@ -1159,4 +1184,48 @@ mod tests { let subtitle = build_subtitle_identity(first_name, last_name); assert_eq!(subtitle, ""); } + + #[test] + fn test_subtitle_ssh_key() { + let key = "hvBMMb1t79YssFZkpetYsM3deyVuQv4r88Uj9gvYe0+G8EwxvW3v1iywVmSl61iwzd17JW5C/ivzxSP2C9h7Tw==".to_string(); + let key = SymmetricCryptoKey::try_from(key).unwrap(); + let original_subtitle = "SHA256:1JjFjvPRkj1Gbf2qRP1dgHiIzEuNAEvp+92x99jw3K0".to_string(); + let fingerprint_encrypted = original_subtitle.to_owned().encrypt_with_key(&key).unwrap(); + let ssh_key_cipher = Cipher { + id: Some("090c19ea-a61a-4df6-8963-262b97bc6266".parse().unwrap()), + organization_id: None, + folder_id: None, + collection_ids: vec![], + r#type: CipherType::SshKey, + key: None, + name: "My test ssh key" + .to_string() + .encrypt_with_key(&key) + .unwrap(), + notes: None, + login: None, + identity: None, + card: None, + secure_note: None, + ssh_key: Some(SshKey { + private_key: None, + public_key: None, + fingerprint: Some(fingerprint_encrypted), + }), + 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: "2024-01-01T00:00:00.000Z".parse().unwrap(), + deleted_date: None, + revision_date: "2024-01-01T00:00:00.000Z".parse().unwrap(), + }; + let subtitle = ssh_key_cipher.get_decrypted_subtitle(&key).unwrap(); + assert_eq!(subtitle, original_subtitle); + } } diff --git a/crates/bitwarden-vault/src/cipher/mod.rs b/crates/bitwarden-vault/src/cipher/mod.rs index 67513d52..a4a6088d 100644 --- a/crates/bitwarden-vault/src/cipher/mod.rs +++ b/crates/bitwarden-vault/src/cipher/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod linked_id; pub(crate) mod local_data; pub(crate) mod login; pub(crate) mod secure_note; +pub(crate) mod ssh_key; pub use attachment::{ Attachment, AttachmentEncryptResult, AttachmentFile, AttachmentFileView, AttachmentView, diff --git a/crates/bitwarden-vault/src/cipher/ssh_key.rs b/crates/bitwarden-vault/src/cipher/ssh_key.rs new file mode 100644 index 00000000..6d4977c8 --- /dev/null +++ b/crates/bitwarden-vault/src/cipher/ssh_key.rs @@ -0,0 +1,49 @@ +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct SshKey { + /// SSH private key (ed25519/rsa) in unencrypted openssh private key format [OpenSSH private key](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key) + pub private_key: Option, + /// SSH public key (ed25519/rsa) according to [RFC4253](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6) + pub public_key: Option, + /// SSH fingerprint using SHA256 in the format: `SHA256:BASE64_ENCODED_FINGERPRINT` + pub fingerprint: Option, +} + +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +pub struct SshKeyView { + /// SSH private key (ed25519/rsa) in unencrypted openssh private key format [OpenSSH private key](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key) + pub private_key: Option, + /// SSH public key (ed25519/rsa) according to [RFC4253](https://datatracker.ietf.org/doc/html/rfc4253#section-6.6) + pub public_key: Option, + /// SSH fingerprint using SHA256 in the format: `SHA256:BASE64_ENCODED_FINGERPRINT` + pub fingerprint: Option, +} + +impl KeyEncryptable for SshKeyView { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + Ok(SshKey { + private_key: self.private_key.encrypt_with_key(key)?, + public_key: self.public_key.encrypt_with_key(key)?, + fingerprint: self.fingerprint.encrypt_with_key(key)?, + }) + } +} + +impl KeyDecryptable for SshKey { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + Ok(SshKeyView { + private_key: self.private_key.decrypt_with_key(key).ok().flatten(), + public_key: self.public_key.decrypt_with_key(key).ok().flatten(), + fingerprint: self.fingerprint.decrypt_with_key(key).ok().flatten(), + }) + } +} diff --git a/crates/bitwarden-vault/src/folder.rs b/crates/bitwarden-vault/src/folder.rs index c5ab1401..f57b8ee1 100644 --- a/crates/bitwarden-vault/src/folder.rs +++ b/crates/bitwarden-vault/src/folder.rs @@ -7,12 +7,15 @@ use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; +#[cfg(feature = "wasm")] +use {tsify_next::Tsify, wasm_bindgen::prelude::*}; use crate::VaultParseError; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct Folder { id: Option, name: EncString, @@ -22,6 +25,7 @@ pub struct Folder { #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "uniffi", derive(uniffi::Record))] +#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] pub struct FolderView { pub id: Option, pub name: String, diff --git a/crates/bitwarden-vault/src/mobile/client_ciphers.rs b/crates/bitwarden-vault/src/mobile/client_ciphers.rs index 345f04df..063fb4bc 100644 --- a/crates/bitwarden-vault/src/mobile/client_ciphers.rs +++ b/crates/bitwarden-vault/src/mobile/client_ciphers.rs @@ -118,6 +118,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: true, @@ -159,6 +160,7 @@ mod tests { identity: None, card: None, secure_note: None, + ssh_key: None, favorite: false, reprompt: CipherRepromptType::None, organization_use_totp: true, diff --git a/crates/bitwarden-vault/src/totp.rs b/crates/bitwarden-vault/src/totp.rs index 8aee3e69..d6167a1a 100644 --- a/crates/bitwarden-vault/src/totp.rs +++ b/crates/bitwarden-vault/src/totp.rs @@ -157,17 +157,19 @@ impl FromStr for Totp { /// - OTP Auth URI /// - Steam URI fn from_str(key: &str) -> Result { + let key = key.to_lowercase(); + let params = if key.starts_with("otpauth://") { - let url = Url::parse(key).map_err(|_| TotpError::InvalidOtpauth)?; + let url = Url::parse(&key).map_err(|_| TotpError::InvalidOtpauth)?; 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), + .and_then(|v| match v.as_ref() { + "sha1" => Some(Algorithm::Sha1), + "sha256" => Some(Algorithm::Sha256), + "sha512" => Some(Algorithm::Sha512), _ => None, }) .unwrap_or(DEFAULT_ALGORITHM), @@ -200,7 +202,7 @@ impl FromStr for Totp { algorithm: DEFAULT_ALGORITHM, digits: DEFAULT_DIGITS, period: DEFAULT_PERIOD, - secret: decode_b32(key), + secret: decode_b32(&key), } }; @@ -285,6 +287,7 @@ mod tests { ("PIUD1IS!EQYA=", "829846"), // sanitized // Steam ("steam://HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", "7W6CJ"), + ("StEam://HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", "7W6CJ"), ("steam://ABCD123", "N26DF"), // Various weird lengths ("ddfdf", "932653"), @@ -321,6 +324,20 @@ mod tests { assert_eq!(response.period, 30); } + #[test] + fn test_generate_otpauth_uppercase() { + 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(); @@ -335,6 +352,21 @@ mod tests { assert_eq!(response.period, 60); } + #[test] + fn test_generate_otpauth_algorithm_sha256() { + let key = + "otpauth://totp/test-account?secret=WQIQ25BRKZYCJVYP&algorithm=SHA256".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, "842615".to_string()); + assert_eq!(response.period, 30); + } + #[test] fn test_generate_totp_cipher_view() { let view = CipherListView { diff --git a/crates/bitwarden-wasm-internal/Cargo.toml b/crates/bitwarden-wasm-internal/Cargo.toml index cd2c0484..33f8128e 100644 --- a/crates/bitwarden-wasm-internal/Cargo.toml +++ b/crates/bitwarden-wasm-internal/Cargo.toml @@ -15,13 +15,16 @@ keywords.workspace = true crate-type = ["cdylib"] [dependencies] -bitwarden-core = { workspace = true, features = ["wasm"] } +bitwarden-core = { workspace = true, features = ["wasm", "internal"] } +bitwarden-crypto = { workspace = true, features = ["wasm"] } +bitwarden-vault = { workspace = true, features = ["wasm"] } console_error_panic_hook = "0.1.7" console_log = { version = "1.0.0", features = ["color"] } js-sys = "0.3.68" log = "0.4.20" serde_json = ">=1.0.96, <2.0" -wasm-bindgen = { version = "0.2.91", features = ["serde-serialize"] } +# When upgrading wasm-bindgen, make sure to update the version in the workflows! +wasm-bindgen = { version = "=0.2.95", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4.41" [lints] diff --git a/crates/bitwarden-wasm-internal/src/client.rs b/crates/bitwarden-wasm-internal/src/client.rs index 8f2fa80d..0a5ce27d 100644 --- a/crates/bitwarden-wasm-internal/src/client.rs +++ b/crates/bitwarden-wasm-internal/src/client.rs @@ -5,6 +5,8 @@ use bitwarden_core::{Client, ClientSettings}; use log::{set_max_level, Level}; use wasm_bindgen::prelude::*; +use crate::{vault::ClientVault, ClientCrypto}; + #[wasm_bindgen] pub enum LogLevel { Trace, @@ -27,7 +29,7 @@ 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 #[wasm_bindgen] -pub struct BitwardenClient(Rc); +pub struct BitwardenClient(pub(crate) Rc); #[wasm_bindgen] impl BitwardenClient { @@ -47,6 +49,10 @@ impl BitwardenClient { msg } + pub fn throw(&self, msg: String) -> Result<(), crate::error::GenericError> { + Err(crate::error::GenericError(msg)) + } + /// Test method, calls http endpoint pub async fn http_get(&self, url: String) -> Result { let client = self.0.internal.get_http_client(); @@ -54,4 +60,12 @@ impl BitwardenClient { res.text().await.map_err(|e| e.to_string()) } + + pub fn crypto(&self) -> ClientCrypto { + ClientCrypto::new(self.0.clone()) + } + + pub fn vault(&self) -> ClientVault { + ClientVault::new(self.0.clone()) + } } diff --git a/crates/bitwarden-wasm-internal/src/crypto.rs b/crates/bitwarden-wasm-internal/src/crypto.rs new file mode 100644 index 00000000..f1b58196 --- /dev/null +++ b/crates/bitwarden-wasm-internal/src/crypto.rs @@ -0,0 +1,33 @@ +use std::rc::Rc; + +use bitwarden_core::{ + mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, + Client, +}; +use wasm_bindgen::prelude::*; + +use crate::error::Result; + +#[wasm_bindgen] +pub struct ClientCrypto(Rc); + +impl ClientCrypto { + pub fn new(client: Rc) -> Self { + Self(client) + } +} + +#[wasm_bindgen] +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.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.crypto().initialize_org_crypto(req).await?) + } +} diff --git a/crates/bitwarden-wasm-internal/src/custom_types.rs b/crates/bitwarden-wasm-internal/src/custom_types.rs new file mode 100644 index 00000000..8d20bf85 --- /dev/null +++ b/crates/bitwarden-wasm-internal/src/custom_types.rs @@ -0,0 +1,22 @@ +/// This file contains custom TypeScript for types defined by external crates. +/// Everything in the string below is appended to the generated TypeScript definition file. +#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)] +const TS_CUSTOM_TYPES: &'static str = r#" +export type Uuid = string; + +/** + * RFC3339 compliant date-time string. + * @typeParam T - Not used in JavaScript. + */ +export type DateTime = string; + +/** + * UTC date-time string. Not used in JavaScript. + */ +export type Utc = unknown; + +/** + * An integer that is known not to equal zero. + */ +export type NonZeroU32 = number; +"#; diff --git a/crates/bitwarden-wasm-internal/src/error.rs b/crates/bitwarden-wasm-internal/src/error.rs new file mode 100644 index 00000000..237ee494 --- /dev/null +++ b/crates/bitwarden-wasm-internal/src/error.rs @@ -0,0 +1,28 @@ +use wasm_bindgen::prelude::*; + +// Importing an error class defined in JavaScript instead of defining it in Rust +// allows us to extend the `Error` class. It also provides much better console output. +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_name = Error)] + type JsError; + + #[wasm_bindgen(constructor, js_class = Error)] + fn new(message: String) -> JsError; +} + +pub type Result = std::result::Result; + +pub struct GenericError(pub String); + +impl From for GenericError { + fn from(error: T) -> Self { + GenericError(error.to_string()) + } +} + +impl From for JsValue { + fn from(error: GenericError) -> Self { + JsError::new(error.0).into() + } +} diff --git a/crates/bitwarden-wasm-internal/src/lib.rs b/crates/bitwarden-wasm-internal/src/lib.rs index b79c47fc..6367ff31 100644 --- a/crates/bitwarden-wasm-internal/src/lib.rs +++ b/crates/bitwarden-wasm-internal/src/lib.rs @@ -1 +1,9 @@ mod client; +mod crypto; +mod custom_types; +mod error; +mod vault; + +pub use client::BitwardenClient; +pub use crypto::ClientCrypto; +pub use vault::{folders::ClientFolders, ClientVault}; diff --git a/crates/bitwarden-wasm-internal/src/vault/folders.rs b/crates/bitwarden-wasm-internal/src/vault/folders.rs new file mode 100644 index 00000000..65289269 --- /dev/null +++ b/crates/bitwarden-wasm-internal/src/vault/folders.rs @@ -0,0 +1,24 @@ +use std::rc::Rc; + +use bitwarden_core::Client; +use bitwarden_vault::{ClientVaultExt, Folder, FolderView}; +use wasm_bindgen::prelude::*; + +use crate::error::Result; + +#[wasm_bindgen] +pub struct ClientFolders(Rc); + +impl ClientFolders { + pub fn new(client: Rc) -> Self { + Self(client) + } +} + +#[wasm_bindgen] +impl ClientFolders { + /// Decrypt folder + pub fn decrypt(&self, folder: Folder) -> Result { + Ok(self.0.vault().folders().decrypt(folder)?) + } +} diff --git a/crates/bitwarden-wasm-internal/src/vault/mod.rs b/crates/bitwarden-wasm-internal/src/vault/mod.rs new file mode 100644 index 00000000..11db0e13 --- /dev/null +++ b/crates/bitwarden-wasm-internal/src/vault/mod.rs @@ -0,0 +1,24 @@ +pub mod folders; + +use std::rc::Rc; + +use bitwarden_core::Client; +use wasm_bindgen::prelude::*; + +use crate::ClientFolders; + +#[wasm_bindgen] +pub struct ClientVault(Rc); + +impl ClientVault { + pub fn new(client: Rc) -> Self { + Self(client) + } +} + +#[wasm_bindgen] +impl ClientVault { + pub fn folders(&self) -> ClientFolders { + ClientFolders::new(self.0.clone()) + } +} diff --git a/languages/js/sdk-internal/.gitignore b/languages/js/sdk-internal/.gitignore index ef69b9de..99cddcd2 100644 --- a/languages/js/sdk-internal/.gitignore +++ b/languages/js/sdk-internal/.gitignore @@ -1,3 +1,4 @@ +**/snippets/**/*.js bitwarden_wasm_internal_bg.js bitwarden_wasm_internal_bg.wasm bitwarden_wasm_internal_bg.wasm.d.ts