From 5a8fa6eb6ee492b8a21db1c384dab854cdcc40d7 Mon Sep 17 00:00:00 2001 From: Maxime Lagresle Date: Wed, 2 Oct 2024 07:50:31 +0200 Subject: [PATCH 1/3] prevent argon2 from crashing provider on error --- .../crypto/keybuilder/prelogin_key.go | 21 ++++++++++-- .../crypto/keybuilder/prelogin_key_test.go | 32 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 internal/bitwarden/crypto/keybuilder/prelogin_key_test.go diff --git a/internal/bitwarden/crypto/keybuilder/prelogin_key.go b/internal/bitwarden/crypto/keybuilder/prelogin_key.go index 3fee255..9db693c 100644 --- a/internal/bitwarden/crypto/keybuilder/prelogin_key.go +++ b/internal/bitwarden/crypto/keybuilder/prelogin_key.go @@ -15,14 +15,31 @@ func BuildPreloginKey(masterPassword, email string, kdfConfig models.KdfConfigur } func buildKey(masterPassword, salt string, kdfConfig models.KdfConfiguration) (*symmetrickey.Key, error) { + var rawKey []byte switch kdfConfig.KdfType { case models.KdfTypePBKDF2_SHA256: - return symmetrickey.NewFromRawBytes(pbkdf2.Key([]byte(masterPassword), []byte(salt), kdfConfig.KdfIterations, 32, sha256.New)) + rawKey = pbkdf2.Key([]byte(masterPassword), []byte(salt), kdfConfig.KdfIterations, 32, sha256.New) case models.KdfTypeArgon2: hashedSalt := sha256.New() hashedSalt.Write([]byte(salt)) - return symmetrickey.NewFromRawBytes(argon2.IDKey([]byte(masterPassword), hashedSalt.Sum(nil), uint32(kdfConfig.KdfIterations), uint32(kdfConfig.KdfMemory*1024), uint8(kdfConfig.KdfParallelism), 32)) + + var err error + err = func() (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("argon2.IDKey() panicked: %v", r) + } + }() + + rawKey = argon2.IDKey([]byte(masterPassword), hashedSalt.Sum(nil), uint32(kdfConfig.KdfIterations), uint32(kdfConfig.KdfMemory*1024), uint8(kdfConfig.KdfParallelism), 32) + return + }() + if err != nil { + return nil, err + } default: return nil, fmt.Errorf("unsupported KDF: '%d'", kdfConfig.KdfType) } + + return symmetrickey.NewFromRawBytes(rawKey) } diff --git a/internal/bitwarden/crypto/keybuilder/prelogin_key_test.go b/internal/bitwarden/crypto/keybuilder/prelogin_key_test.go new file mode 100644 index 0000000..ecd979c --- /dev/null +++ b/internal/bitwarden/crypto/keybuilder/prelogin_key_test.go @@ -0,0 +1,32 @@ +package keybuilder + +import ( + "testing" + + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/models" + "github.com/stretchr/testify/assert" +) + +func TestArgon2(t *testing.T) { + key, err := buildKey("test1234", "somesalt", models.KdfConfiguration{ + KdfType: models.KdfTypeArgon2, + KdfIterations: 3, + KdfMemory: 64, + KdfParallelism: 4, + }) + + assert.NoError(t, err) + assert.Equal(t, "Key: CAgX8/OUnQXSAzipUdqaQ9CFCflNf2lowXvfbpzNmXU=\nEncryptionKey: CAgX8/OUnQXSAzipUdqaQ9CFCflNf2lowXvfbpzNmXU=\nMacKey: \n", key.Summary()) +} + +func TestArgon2WithTooLittleParallelism(t *testing.T) { + key, err := buildKey("test1234", "somesalt", models.KdfConfiguration{ + KdfType: models.KdfTypeArgon2, + KdfIterations: 3, + KdfMemory: 64, + KdfParallelism: 0, + }) + + assert.Errorf(t, err, "panicked: argon2: parallelism degree too low") + assert.Nil(t, key) +} From 2a205caf1a63c545e56f916a18bd992662f10d30 Mon Sep 17 00:00:00 2001 From: Maxime Lagresle Date: Wed, 2 Oct 2024 09:29:53 +0200 Subject: [PATCH 2/3] level-up testing infrastructure --- .../embedded/fixtures/create_accounts_test.go | 115 +++ .../embedded/fixtures/disk_transport.go | 70 ++ .../embedded/fixtures/mocked_client.go | 51 ++ .../test-kdf0_GET_api_accounts_profile.json | 22 + .../fixtures/test-kdf0_GET_api_sync.json | 105 +++ .../fixtures/test-kdf0_POST_api_ciphers.json | 37 + ...-kdf0_POST_identity_accounts_prelogin.json | 6 + ...test-kdf0_POST_identity_connect_token.json | 23 + .../test-kdf1_GET_api_accounts_profile.json | 22 + .../fixtures/test-kdf1_GET_api_sync.json | 105 +++ .../fixtures/test-kdf1_POST_api_ciphers.json | 37 + ...-kdf1_POST_identity_accounts_prelogin.json | 6 + ...test-kdf1_POST_identity_connect_token.json | 23 + .../embedded/fixtures/test_accounts.go | 47 ++ .../bitwarden/embedded/vault_base_test.go | 97 +-- .../embedded/vault_mocked_webapi_test.go | 753 ------------------ internal/bitwarden/embedded/vault_webapi.go | 20 +- .../bitwarden/embedded/vault_webapi_test.go | 60 +- internal/bitwarden/webapi/models.go | 2 + 19 files changed, 762 insertions(+), 839 deletions(-) create mode 100644 internal/bitwarden/embedded/fixtures/create_accounts_test.go create mode 100644 internal/bitwarden/embedded/fixtures/disk_transport.go create mode 100644 internal/bitwarden/embedded/fixtures/mocked_client.go create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_accounts_profile.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_accounts_prelogin.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_accounts_profile.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_accounts_prelogin.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json create mode 100644 internal/bitwarden/embedded/fixtures/test_accounts.go delete mode 100644 internal/bitwarden/embedded/vault_mocked_webapi_test.go diff --git a/internal/bitwarden/embedded/fixtures/create_accounts_test.go b/internal/bitwarden/embedded/fixtures/create_accounts_test.go new file mode 100644 index 0000000..899ce0b --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/create_accounts_test.go @@ -0,0 +1,115 @@ +package fixtures + +import ( + "context" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "net/http" + "strings" + "testing" + + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/crypto" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/crypto/keybuilder" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/embedded" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/models" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/webapi" +) + +// This is only used to generate test data +func TestCreateTestAccounts(t *testing.T) { + t.Skip() + createTestAccount(t, Pdkdf2Email, models.KdfConfiguration{ + KdfType: models.KdfTypePBKDF2_SHA256, + KdfIterations: 600000, + }) + createTestAccount(t, Argon2Email, models.KdfConfiguration{ + KdfType: models.KdfTypeArgon2, + KdfIterations: 3, + KdfMemory: 64, + KdfParallelism: 4, + }) +} + +func createTestAccount(t *testing.T, accountEmail string, kdfConfig models.KdfConfiguration) { + ctx := context.Background() + + mockName := strings.Split(accountEmail, "@")[0] + + preloginKey, err := keybuilder.BuildPreloginKey(TestPassword, accountEmail, kdfConfig) + if err != nil { + t.Fatal(err) + } + + hashedPassword := crypto.HashPassword(TestPassword, *preloginKey, false) + + block, _ := pem.Decode([]byte(RsaPrivateKey)) + if block == nil { + t.Fatal(err) + } + + privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + t.Fatal(err) + } + + encryptionKeyBytes, err := base64.StdEncoding.DecodeString(EncryptionKey) + if err != nil { + t.Fatal(err) + } + + newEncryptionKey, encryptedEncryptionKey, err := keybuilder.EncryptEncryptionKey(*preloginKey, encryptionKeyBytes) + if err != nil { + t.Fatal(err) + } + + publicKey, encryptedPrivateKey, err := keybuilder.EncryptRSAKeyPair(*newEncryptionKey, privateKey) + if err != nil { + t.Fatal(err) + } + + signupRequest := webapi.SignupRequest{ + Email: accountEmail, + Name: accountEmail, + MasterPasswordHash: hashedPassword, + Key: encryptedEncryptionKey, + Kdf: kdfConfig.KdfType, + KdfIterations: kdfConfig.KdfIterations, + KdfMemory: kdfConfig.KdfMemory, + KdfParallelism: kdfConfig.KdfParallelism, + Keys: webapi.KeyPair{ + PublicKey: publicKey, + EncryptedPrivateKey: encryptedPrivateKey, + }, + } + + client := webapi.NewClient(ServerURL) + err = client.RegisterUser(ctx, signupRequest) + if err != nil && !strings.Contains(err.Error(), "Registration not allowed or user already exists") { + t.Fatal(err) + } + + httpClient := http.Client{ + Transport: &diskTransport{ + Prefix: mockName, + }, + } + vault := embedded.NewWebAPIVault(ServerURL, embedded.WithHttpOptions(webapi.WithCustomClient(httpClient))) + + err = vault.LoginWithPassword(ctx, accountEmail, TestPassword) + if err != nil { + t.Fatal(err) + } + + _, err = vault.CreateObject(ctx, models.Object{ + Object: models.ObjectTypeItem, + Type: models.ItemTypeLogin, + Name: "Item in own Vault", + Login: models.Login{ + Username: "my-username", + }, + }) + if err != nil { + t.Fatal(err) + } +} diff --git a/internal/bitwarden/embedded/fixtures/disk_transport.go b/internal/bitwarden/embedded/fixtures/disk_transport.go new file mode 100644 index 0000000..ff49dc2 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/disk_transport.go @@ -0,0 +1,70 @@ +package fixtures + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "strings" +) + +type diskTransport struct { + Transport http.RoundTripper + Prefix string +} + +func (d *diskTransport) RoundTrip(req *http.Request) (*http.Response, error) { + transport := d.Transport + if transport == nil { + transport = http.DefaultTransport + } + + resp, err := transport.RoundTrip(req) + if err != nil { + return nil, err + } + + if err := d.saveResponseToFile(req, resp); err != nil { + return nil, fmt.Errorf("error saving response to file: %w", err) + } + + return resp, nil +} + +func (d *diskTransport) saveResponseToFile(req *http.Request, resp *http.Response) error { + filename := fmt.Sprintf("%s_%s%s.json", d.Prefix, req.Method, sanitizeFilename(resp.Request.URL.EscapedPath())) + + data, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + resp.Body = io.NopCloser(bytes.NewReader(data)) + + var jsonData map[string]interface{} + if err := json.Unmarshal(data, &jsonData); err != nil { + return err + } + + prettyData, err := json.MarshalIndent(jsonData, "", " ") + if err != nil { + return err + } + + return os.WriteFile(filename, prettyData, 0644) +} + +func sanitizeFilename(url string) string { + replacer := []string{ + ":", "_", + "/", "_", + "\\", "_", + "?", "_", + "&", "_", + "=", "_", + "%", "_", + } + replacerMap := strings.NewReplacer(replacer...) + return replacerMap.Replace(url) +} diff --git a/internal/bitwarden/embedded/fixtures/mocked_client.go b/internal/bitwarden/embedded/fixtures/mocked_client.go new file mode 100644 index 0000000..f6a3004 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/mocked_client.go @@ -0,0 +1,51 @@ +package fixtures + +import ( + "fmt" + "net/http" + "os" + "strings" + "testing" + + "github.com/jarcoal/httpmock" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/webapi" +) + +const ( + mockedServerUrl = "http://127.0.0.1:8081" +) + +func MockedClient(t *testing.T, name string) webapi.Client { + client := http.Client{Transport: httpmock.DefaultTransport} + + files, err := os.ReadDir("fixtures") + if err != nil { + t.Fatal(err) + } + + t.Logf("Found %d responders", len(files)) + for _, file := range files { + if !strings.HasSuffix(file.Name(), ".json") || !strings.HasPrefix(file.Name(), fmt.Sprintf("%s_", name)) { + continue + } + + data, err := os.ReadFile(fmt.Sprintf("%s/%s", "fixtures", file.Name())) + if err != nil { + t.Fatal(err) + } + + tmp := strings.Split(file.Name(), "_") + name = tmp[0] + method := strings.ToUpper(tmp[1]) + mockUrl := strings.Join(tmp[2:], "/") + + mockUrl, _ = strings.CutSuffix(mockUrl, ".json") + mockUrl = fmt.Sprintf("%s/%s", mockedServerUrl, mockUrl) + t.Logf("Registering responder for %s %s", method, mockUrl) + + httpmock.RegisterResponder(method, mockUrl, + httpmock.NewStringResponder(200, string(data))) + } + + return webapi.NewClient(mockedServerUrl, webapi.WithCustomClient(client), webapi.DisableRetries()) +} diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_accounts_profile.json b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_accounts_profile.json new file mode 100644 index 0000000..0159448 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_accounts_profile.json @@ -0,0 +1,22 @@ +{ + "_status": 0, + "avatarColor": null, + "culture": "en-US", + "email": "test-kdf0@laverse.net", + "emailVerified": true, + "forcePasswordReset": false, + "id": "aaf15bd1-4f51-4ba0-ade8-9dc2ec0fd2c3", + "key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=", + "masterPasswordHint": null, + "name": "test-kdf0@laverse.net", + "object": "profile", + "organizations": [], + "premium": true, + "premiumFromOrganization": false, + "privateKey": "2.11j1IvphccY0UkZov7ZbmQ==|4J34a16NM+krEXyDUkHVUNL2sSA7dph4EBCLWoDkmDoljqMZh5IxA7M51yZTNB6/uqGgJZJX0uU+B4RSn2s2JoFG/VizMmgSIJkTIr6WuA7taEzyIFRi7sY980W02pnLeb8fGV8EXrZk1Bj0UzAFukNGoeS2CHWbm0bZKRvDxl5Vw40V3Lt6GzHTb6X+4k4Ovg0UKgm2mqMWzxxjmCfy+G1R0vlsAtqg14n2ax5f3Jn4ajGDvT2BQia9EFYFkie/SfqgsYbtvou4DvyCTEWh0j9Cre1QIJQ9AZ4AHAzGwIKFhpN7sWjsfw6yTGmvxAfflCMFzCdleBBiuCefaAKNe5Uf1QASC9TzIiHknl2+sK9lOFZ+XZJ41HCU2sMvNBu1EHuBPNRIHodCEHdXHyRqBaC+vgWO6RcTWU4K5ZctBKmElAYst7FFCuzM+liUcGp3I1a7wxOJTPraxeFw8z69rYFiNMOng/HkV/G/VUQXzWalC5gtjaR35dMp35Mf1lMlGnWhy/qdLr0NVdl69qUDKt+kCG9+kiXO7Eq5PTbV+tj4AxBzxE1DroAh0jTPFLb7p1205+OQqqrCEq6tzpGHKTFLoyHZCVoxdQvxgFNX6+fNi3+MfbDfLle7msQAwOuaUl6rxcb2JjdgRQQUd4/GQbvKeLjFRIr7OtcVHWm3251jqRLBgFJcQ235SFgdjLnKATqN4BRe0WLyYOMuMQEmfQXaebjzMo7L2JMJeOar9QutuV+Acle7kJZZU4N1XPiUmborUksAcrmLGXvQITn1QLmadou0jX/oov+lkrKDIFTJC5MIutVBNmExS6FqW978viF1ZNgRQxG5OULHoT5tgfyjrl2u74VFf0ttbLC/JSsi1k8me2LA2vi2Sx7DNOzd6fLx0f8+mYmz2VTRw6fnoFh99d8HktPUNyKcGNZyZpsfkkhFSFV/U88tZ9gROWayLbRXS6g801Mi0tBg0RJp/Flo9ZX9Y3qKVWLCDZT6t3l1NR2npkGmi16yqslXSs9hadIvd6lxyYqyW6cskuJjsacHPOCyvz1xZFH6txtzmb46UrKUU7Cjo/09Kmtb740rXzhH/0nPuvJUjlk0UN77LqzvnvVWAe2IJVEjsbhTspLw3Z1fmCQxMKvc3yPA36/KP2uk/wOlHmBnuX/eebQmI22PFOzskl1d0ScNItJsw5D6fkEhybxEY3oPWYG5y+Oitqj1dQy/TNKXeJHMP+MC1PxzvaE3jq/+cb0IwVBnMVblbaHCJM6JAllV/p3Z6/Ho3Ps4hDHRflKZjP2HyB5wvvTtYhX5XpDoA8s9e6TpDXYnoE+XLN4Thzu30GL3WBeI7koYuNEpRhD5++oT2CElpEqo0v/TFKGSmnV+qohWTL8I4WnHSZeKDLC5alqIMYgRkN6qUlVJLzILOFzeJcL9zeXsAeHemd3VZWe0OYiJRxVwBCYGHk6W7WA4pZ+Wq/C0JHaxNJhr9gx0kyFlMPBkwN/LEyUP+PxsqIuW+09f70qZdGE1r9bNjUSKmb53I6nqxwQhIwvpZZDGAOZjaxrfC8PE9rOOTkM3v6zsSWgjl4EJMPwJubHJb63w5hvW2DwS4h3t7lduTab9ykKInvfBsaWxLuBhJuX+fesGTM0KGXs=|BXz0QzgtArYQXICHbYvGqOeFVi9YGZRP0MASNlVwzzY=", + "providerOrganizations": [], + "providers": [], + "securityStamp": "aa485463-c258-40b5-b2cf-bf22bf705258", + "twoFactorEnabled": false, + "usesKeyConnector": false +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json new file mode 100644 index 0000000..d6e2dd3 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json @@ -0,0 +1,105 @@ +{ + "ciphers": [ + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:16.863582Z", + "data": { + "fields": [], + "name": "2.6HNbskeer21sXcklJgZK6Q==|KqSH44qdXZneXAs7NK0LoA==|asYAGFnE0PUVggadvgGG/Bh32jE6crENOKMzl2MMEVo=", + "notes": null, + "passwordHistory": [], + "uri": null + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "93178306-8fd2-47fa-b815-4133c1f25d27", + "identity": null, + "key": "2.6izFBksanMQtXXRVrziOwg==|o1U9wBUdfTvrbkgoOHpuavIH76nE0mchNM/5rCLwicUOfoMIWz14kO0KyTBNbx8dOfCb9ZpccVwkCkbTVRF1tgHtkGU0YMMViF3Hj26a70k=|ikUSL2klWn271RWEOxxhvZUAFbjrJMKI1/HRmSm0xkI=", + "login": { + "uri": null + }, + "name": "2.6HNbskeer21sXcklJgZK6Q==|KqSH44qdXZneXAs7NK0LoA==|asYAGFnE0PUVggadvgGG/Bh32jE6crENOKMzl2MMEVo=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:16.863968Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:54.495716Z", + "data": { + "fields": [], + "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "f1d8b375-8b6a-4bb5-9659-520c2864c2e0", + "identity": null, + "key": "2.H87CevHa/yLkUvgJfpha5g==|IrEdZ2aHOG0P/xCvymr++yzWsMwupJ7Rq0mN9kqTYTc2bsBlpi7/bqva1RhhBRoMuwFnMTx/cX4bMWHZKJbpjV9CENI475Q3JgJScjY/ceQ=|jMosP2JYP9PqRhEODetF2ZNuGkEgLuIR+6jy1ILosk0=", + "login": { + "uri": null, + "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + }, + "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:54.495998Z", + "secureNote": null, + "type": 1, + "viewPassword": true + } + ], + "collections": [], + "domains": null, + "folders": [], + "object": "sync", + "policies": [], + "profile": { + "_status": 0, + "avatarColor": null, + "culture": "en-US", + "email": "test-kdf0@laverse.net", + "emailVerified": true, + "forcePasswordReset": false, + "id": "aaf15bd1-4f51-4ba0-ade8-9dc2ec0fd2c3", + "key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=", + "masterPasswordHint": null, + "name": "test-kdf0@laverse.net", + "object": "profile", + "organizations": [], + "premium": true, + "premiumFromOrganization": false, + "privateKey": "2.11j1IvphccY0UkZov7ZbmQ==|4J34a16NM+krEXyDUkHVUNL2sSA7dph4EBCLWoDkmDoljqMZh5IxA7M51yZTNB6/uqGgJZJX0uU+B4RSn2s2JoFG/VizMmgSIJkTIr6WuA7taEzyIFRi7sY980W02pnLeb8fGV8EXrZk1Bj0UzAFukNGoeS2CHWbm0bZKRvDxl5Vw40V3Lt6GzHTb6X+4k4Ovg0UKgm2mqMWzxxjmCfy+G1R0vlsAtqg14n2ax5f3Jn4ajGDvT2BQia9EFYFkie/SfqgsYbtvou4DvyCTEWh0j9Cre1QIJQ9AZ4AHAzGwIKFhpN7sWjsfw6yTGmvxAfflCMFzCdleBBiuCefaAKNe5Uf1QASC9TzIiHknl2+sK9lOFZ+XZJ41HCU2sMvNBu1EHuBPNRIHodCEHdXHyRqBaC+vgWO6RcTWU4K5ZctBKmElAYst7FFCuzM+liUcGp3I1a7wxOJTPraxeFw8z69rYFiNMOng/HkV/G/VUQXzWalC5gtjaR35dMp35Mf1lMlGnWhy/qdLr0NVdl69qUDKt+kCG9+kiXO7Eq5PTbV+tj4AxBzxE1DroAh0jTPFLb7p1205+OQqqrCEq6tzpGHKTFLoyHZCVoxdQvxgFNX6+fNi3+MfbDfLle7msQAwOuaUl6rxcb2JjdgRQQUd4/GQbvKeLjFRIr7OtcVHWm3251jqRLBgFJcQ235SFgdjLnKATqN4BRe0WLyYOMuMQEmfQXaebjzMo7L2JMJeOar9QutuV+Acle7kJZZU4N1XPiUmborUksAcrmLGXvQITn1QLmadou0jX/oov+lkrKDIFTJC5MIutVBNmExS6FqW978viF1ZNgRQxG5OULHoT5tgfyjrl2u74VFf0ttbLC/JSsi1k8me2LA2vi2Sx7DNOzd6fLx0f8+mYmz2VTRw6fnoFh99d8HktPUNyKcGNZyZpsfkkhFSFV/U88tZ9gROWayLbRXS6g801Mi0tBg0RJp/Flo9ZX9Y3qKVWLCDZT6t3l1NR2npkGmi16yqslXSs9hadIvd6lxyYqyW6cskuJjsacHPOCyvz1xZFH6txtzmb46UrKUU7Cjo/09Kmtb740rXzhH/0nPuvJUjlk0UN77LqzvnvVWAe2IJVEjsbhTspLw3Z1fmCQxMKvc3yPA36/KP2uk/wOlHmBnuX/eebQmI22PFOzskl1d0ScNItJsw5D6fkEhybxEY3oPWYG5y+Oitqj1dQy/TNKXeJHMP+MC1PxzvaE3jq/+cb0IwVBnMVblbaHCJM6JAllV/p3Z6/Ho3Ps4hDHRflKZjP2HyB5wvvTtYhX5XpDoA8s9e6TpDXYnoE+XLN4Thzu30GL3WBeI7koYuNEpRhD5++oT2CElpEqo0v/TFKGSmnV+qohWTL8I4WnHSZeKDLC5alqIMYgRkN6qUlVJLzILOFzeJcL9zeXsAeHemd3VZWe0OYiJRxVwBCYGHk6W7WA4pZ+Wq/C0JHaxNJhr9gx0kyFlMPBkwN/LEyUP+PxsqIuW+09f70qZdGE1r9bNjUSKmb53I6nqxwQhIwvpZZDGAOZjaxrfC8PE9rOOTkM3v6zsSWgjl4EJMPwJubHJb63w5hvW2DwS4h3t7lduTab9ykKInvfBsaWxLuBhJuX+fesGTM0KGXs=|BXz0QzgtArYQXICHbYvGqOeFVi9YGZRP0MASNlVwzzY=", + "providerOrganizations": [], + "providers": [], + "securityStamp": "aa485463-c258-40b5-b2cf-bf22bf705258", + "twoFactorEnabled": false, + "usesKeyConnector": false + }, + "sends": [], + "unofficialServer": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json new file mode 100644 index 0000000..384747c --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json @@ -0,0 +1,37 @@ +{ + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:54.495716Z", + "data": { + "fields": [], + "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "f1d8b375-8b6a-4bb5-9659-520c2864c2e0", + "identity": null, + "key": "2.H87CevHa/yLkUvgJfpha5g==|IrEdZ2aHOG0P/xCvymr++yzWsMwupJ7Rq0mN9kqTYTc2bsBlpi7/bqva1RhhBRoMuwFnMTx/cX4bMWHZKJbpjV9CENI475Q3JgJScjY/ceQ=|jMosP2JYP9PqRhEODetF2ZNuGkEgLuIR+6jy1ILosk0=", + "login": { + "uri": null, + "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + }, + "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:54.495998Z", + "secureNote": null, + "type": 1, + "viewPassword": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_accounts_prelogin.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_accounts_prelogin.json new file mode 100644 index 0000000..8e09329 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_accounts_prelogin.json @@ -0,0 +1,6 @@ +{ + "kdf": 0, + "kdfIterations": 600000, + "kdfMemory": 0, + "kdfParallelism": 0 +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json new file mode 100644 index 0000000..86bce5f --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json @@ -0,0 +1,23 @@ +{ + "ForcePasswordReset": false, + "Kdf": 0, + "KdfIterations": 600000, + "KdfMemory": 0, + "KdfParallelism": 0, + "Key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=", + "MasterPasswordPolicy": { + "object": "masterPasswordPolicy" + }, + "PrivateKey": "2.11j1IvphccY0UkZov7ZbmQ==|4J34a16NM+krEXyDUkHVUNL2sSA7dph4EBCLWoDkmDoljqMZh5IxA7M51yZTNB6/uqGgJZJX0uU+B4RSn2s2JoFG/VizMmgSIJkTIr6WuA7taEzyIFRi7sY980W02pnLeb8fGV8EXrZk1Bj0UzAFukNGoeS2CHWbm0bZKRvDxl5Vw40V3Lt6GzHTb6X+4k4Ovg0UKgm2mqMWzxxjmCfy+G1R0vlsAtqg14n2ax5f3Jn4ajGDvT2BQia9EFYFkie/SfqgsYbtvou4DvyCTEWh0j9Cre1QIJQ9AZ4AHAzGwIKFhpN7sWjsfw6yTGmvxAfflCMFzCdleBBiuCefaAKNe5Uf1QASC9TzIiHknl2+sK9lOFZ+XZJ41HCU2sMvNBu1EHuBPNRIHodCEHdXHyRqBaC+vgWO6RcTWU4K5ZctBKmElAYst7FFCuzM+liUcGp3I1a7wxOJTPraxeFw8z69rYFiNMOng/HkV/G/VUQXzWalC5gtjaR35dMp35Mf1lMlGnWhy/qdLr0NVdl69qUDKt+kCG9+kiXO7Eq5PTbV+tj4AxBzxE1DroAh0jTPFLb7p1205+OQqqrCEq6tzpGHKTFLoyHZCVoxdQvxgFNX6+fNi3+MfbDfLle7msQAwOuaUl6rxcb2JjdgRQQUd4/GQbvKeLjFRIr7OtcVHWm3251jqRLBgFJcQ235SFgdjLnKATqN4BRe0WLyYOMuMQEmfQXaebjzMo7L2JMJeOar9QutuV+Acle7kJZZU4N1XPiUmborUksAcrmLGXvQITn1QLmadou0jX/oov+lkrKDIFTJC5MIutVBNmExS6FqW978viF1ZNgRQxG5OULHoT5tgfyjrl2u74VFf0ttbLC/JSsi1k8me2LA2vi2Sx7DNOzd6fLx0f8+mYmz2VTRw6fnoFh99d8HktPUNyKcGNZyZpsfkkhFSFV/U88tZ9gROWayLbRXS6g801Mi0tBg0RJp/Flo9ZX9Y3qKVWLCDZT6t3l1NR2npkGmi16yqslXSs9hadIvd6lxyYqyW6cskuJjsacHPOCyvz1xZFH6txtzmb46UrKUU7Cjo/09Kmtb740rXzhH/0nPuvJUjlk0UN77LqzvnvVWAe2IJVEjsbhTspLw3Z1fmCQxMKvc3yPA36/KP2uk/wOlHmBnuX/eebQmI22PFOzskl1d0ScNItJsw5D6fkEhybxEY3oPWYG5y+Oitqj1dQy/TNKXeJHMP+MC1PxzvaE3jq/+cb0IwVBnMVblbaHCJM6JAllV/p3Z6/Ho3Ps4hDHRflKZjP2HyB5wvvTtYhX5XpDoA8s9e6TpDXYnoE+XLN4Thzu30GL3WBeI7koYuNEpRhD5++oT2CElpEqo0v/TFKGSmnV+qohWTL8I4WnHSZeKDLC5alqIMYgRkN6qUlVJLzILOFzeJcL9zeXsAeHemd3VZWe0OYiJRxVwBCYGHk6W7WA4pZ+Wq/C0JHaxNJhr9gx0kyFlMPBkwN/LEyUP+PxsqIuW+09f70qZdGE1r9bNjUSKmb53I6nqxwQhIwvpZZDGAOZjaxrfC8PE9rOOTkM3v6zsSWgjl4EJMPwJubHJb63w5hvW2DwS4h3t7lduTab9ykKInvfBsaWxLuBhJuX+fesGTM0KGXs=|BXz0QzgtArYQXICHbYvGqOeFVi9YGZRP0MASNlVwzzY=", + "ResetMasterPassword": false, + "UserDecryptionOptions": { + "HasMasterPassword": true, + "Object": "userDecryptionOptions" + }, + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTM4MzQsImV4cCI6MTcyNzg2MTAzNCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6ImFhZjE1YmQxLTRmNTEtNGJhMC1hZGU4LTlkYzJlYzBmZDJjMyIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjBAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMEBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJhYTQ4NTQ2My1jMjU4LTQwYjUtYjJjZi1iZjIyYmY3MDUyNTgiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsiQXBwbGljYXRpb24iXX0.HBnh7fQehhK5cVslhxLLckkYhDtY4IFXTTqLMMcB5HzyQtFfFgyllxisQsqnLikGF7W4K-UN_L26h_pWKRzWdywxbNRKAs7Jc6NYeesSXJpsBrC1zqXKv5rWSyM59oqM3fp_owRqftv9ujvKqEn_c-UteVvtmL_ieS66H2tPp8zBT08FK23ra1EhvW9O6UA7Qx8YxrHCnvOIVJ16paiPSjYWBR_p7fz0sBzoz2ypGGQ6UpJJpW60UK4AAT7-DxJe68eRIwHpbLd7ZjR3x53Y9bBI7toZ3SemXP7guz6fWl_xqj7UteB3C1a9ISI7TFCkJUP7BVRNBJbYdRHEzFZxUg", + "expires_in": 7200, + "refresh_token": "q89oDzmqCjdl4cxLj9RCKjCA8oQtjxZc2vebEWIApputzfVSYjpWJ9Tq_yVNhK0Rd7RJKksg4ycfkMqyVgG2xw==", + "scope": "api offline_access", + "token_type": "Bearer", + "unofficialServer": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_accounts_profile.json b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_accounts_profile.json new file mode 100644 index 0000000..41ff584 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_accounts_profile.json @@ -0,0 +1,22 @@ +{ + "_status": 0, + "avatarColor": null, + "culture": "en-US", + "email": "test-kdf1@laverse.net", + "emailVerified": true, + "forcePasswordReset": false, + "id": "3f0abf17-e779-4312-a3dd-9c6266e95a9e", + "key": "2.Q+HxT8fkXKmM+irKC+1D6g==|hxmjLJ2RZUPM2uWk0gmPmNe0/OQrCbB49hKUIoqvXWbUaxricj62fATs81UZaKQoC5Re1LPyFsioRImDl1L+sv+EcBEhOx/0wqZ+JPNxXms=|t0G4kLfldPtNCg3wzXU81olAxgbe6sZHAMlQkjjJLck=", + "masterPasswordHint": null, + "name": "test-kdf1@laverse.net", + "object": "profile", + "organizations": [], + "premium": true, + "premiumFromOrganization": false, + "privateKey": "2.fRqWht1SVjfmdTOYbLxbvw==|6nMLdGVZmXlnSjmDyJC94ljd/OYtCTflhVew0+uB4smS2YfFdmkfely/ZMU5UyDyuTCMp5ynw0ERTm3whVmwNGZkYHYT1iuU8I+N5zSQyuNPqnTREGFVslwcMSqkgINYUNoTnJYr/YkLjqzBLt4R5AvFY9Pxq20c+u+3obGcXVW2I11cxF47HVQde9pks72EvOw8KAQs6nQxx8CS/hWLmpZCh/f9yZ0PtNoeik+NxsnSI9veaLvr9yUwqWyhpF1+EI+PMpYZzUopyue8c0aihEUe5Pthz5z1KU+JXMWAAvtg/6eYFi8fQqT8Y6BOZh07makHPYIePQ2O/vgAETldiSlWwmjczZCQ5OXE4wromnzxKBYu1/K2uFUuQ0CD+xsleZImAyYR1W2zVslLFb/ILUX0RSKuqA2MlZizRldTY4nZ7quOWfHP0YD6iRK3oGFf7FfYPAPlcPOPDKl1tEhel3a3M8R0mkyb2e2S6IoW0hfYE4V4J0+VEmdNu7LQqFleqpEPl7icG0Z0EpP3KIJ4OcnO3gbUyo83MOyq4TQMIl46BQt42R4NcoA4hedV/YblUwnri58ugKfURH4+iSjv/r+F2uoSzJu2vdVHka3lF30bwhemyEUhsOZtHaEXpasKHesMknTv4/e+FhAdE9hjplWQyXO7rATXH6F0nEbyCDfOkghZAiAboTjBcE1FoqXBdCSkn4uVzmeWIGJp7izqzM/8zLK2VPUAMtxJGh9+rcv27bLYsbHfcnvEhCyXEsxa0b3DSGijyeSQC2yBNqJen9/SHbsCGNDOLNNyzYUzfIepQ52Oy2LgJEZ57ODTUybPfX4tyW8b+NriSzkUsx9Lp6hh/UaF6f+hBcQ7/dWVoHTJFyUHB1eni0PfFot0dXusg4n7usaG4e4ZSDQprgPHCyg+c3IxauHQmh9/oq1C4/5KuXIB/vOtMq98xjwnZTRdiJxOS82UyqpnwYcGQ9W2RIqKt1GXo/R5rgPXXtgmssqClu7QKI4sHA5lzTs1ef5BHFW1zAYPmsFvovTdX8ckrSdAoeQHJlIb4WyCNB4swNhmMFeQpdgCAZsBAjr+GG6Ak0JxXa2eQBF3zs0f37ly0t3BV7cCuDYKKSol5q14zTQkSQNg+/7TmhtmJo9ducSNS8orQT5IYA+OJa28wGfXjKKaSu0WSH/Tr83984nOQfUdlUZ2rqiskzW7/KUK2nlUceBty+0npuvrzqKk4eDIlJvh6uqwbU0C6SU9MFa0u4nXzfDvDHOgzuz4mNyCYe9tWzU2qArH9dzYMdc1UVj8qlmrPm2WkuXeEEYO+4MBAEHIuQxs21EshpE+2kePRpE5XHn/NbuZhbZ3j7ZD8w7Pyp4PC+hVAg83P+fvWU5CRuA8Ee2wNE6TORtqjnzW40Uh4JcQCaGwOt7dnDVygOsD9NGQrcrY8rLnK1kFMLJmfJtJ8BAn4A18RscI8OuwBkpfoOe9QldDXYsSAJ40K/yE3Nk25Csb3sgoHttfy43CpIIYvNzrqajZA0IvP22eWiF/FeZKO7zm0Myw33ARyHFw2yiBLNys4xxVuL3YmpolHRzOaUqtWA3bNJTmKWiBXxlJvL8+OvbfY+TYXJdVBUVzaATG4CL546j5hduhZfDxJQk=|1kt/ukROVrAIqC47wt8TLQYVh9jeZaCUE3/hHo8hCNA=", + "providerOrganizations": [], + "providers": [], + "securityStamp": "e968bbd1-9f65-46ef-b14e-0d557b3b3b1a", + "twoFactorEnabled": false, + "usesKeyConnector": false +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json new file mode 100644 index 0000000..07707ed --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json @@ -0,0 +1,105 @@ +{ + "ciphers": [ + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:54.690520Z", + "data": { + "fields": [], + "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "30b00bfa-a32f-466a-9f23-dbc312455790", + "identity": null, + "key": "2.EFS7b18DYHnPgrK8tI0crw==|Ce+Dek2JYNCk05ijSYm78WS0+Y8odUeNDQsrAnkXllMAc4NG1FfCOhcfT2CHBlQD/YudriUvyhrTvWI/5GQIu9sCHRhEUYQE7o9yGOh/VmQ=|jescgRjRQqz+K6OSlVgNqjTJ6go3khELIm+TKfxE4gQ=", + "login": { + "uri": null, + "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + }, + "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:54.690612Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:17.064590Z", + "data": { + "fields": [], + "name": "2.8tFviaCvO0/RdXRL8Bwcvw==|4YEIMVO98ONXqMMoovcESA==|8VobBn1s2PbKyxGYlfgYnyK/Rc4qVE+6+/pTMW7TQUY=", + "notes": null, + "passwordHistory": [], + "uri": null + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "cd9bcb8f-eed0-4aff-a390-f16c5ffa4ea0", + "identity": null, + "key": "2.qJVeKQS1d5AtvLO8dfyfZg==|V9eBSkFK/EWL2J0+EnHqwcOJaqOWwB/bvuckHk5G2GIBvbPbgGNRLJn9dNIs4XPcUBYRAlRHPClJ+9jdwOPmytqv9AyVJeBZb1Bzm/EuDmk=|bjbYDj0+0TQW0MYdrJfMWhvNx5pBLE6ZfdhJpVRQw00=", + "login": { + "uri": null + }, + "name": "2.8tFviaCvO0/RdXRL8Bwcvw==|4YEIMVO98ONXqMMoovcESA==|8VobBn1s2PbKyxGYlfgYnyK/Rc4qVE+6+/pTMW7TQUY=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:17.064674Z", + "secureNote": null, + "type": 1, + "viewPassword": true + } + ], + "collections": [], + "domains": null, + "folders": [], + "object": "sync", + "policies": [], + "profile": { + "_status": 0, + "avatarColor": null, + "culture": "en-US", + "email": "test-kdf1@laverse.net", + "emailVerified": true, + "forcePasswordReset": false, + "id": "3f0abf17-e779-4312-a3dd-9c6266e95a9e", + "key": "2.Q+HxT8fkXKmM+irKC+1D6g==|hxmjLJ2RZUPM2uWk0gmPmNe0/OQrCbB49hKUIoqvXWbUaxricj62fATs81UZaKQoC5Re1LPyFsioRImDl1L+sv+EcBEhOx/0wqZ+JPNxXms=|t0G4kLfldPtNCg3wzXU81olAxgbe6sZHAMlQkjjJLck=", + "masterPasswordHint": null, + "name": "test-kdf1@laverse.net", + "object": "profile", + "organizations": [], + "premium": true, + "premiumFromOrganization": false, + "privateKey": "2.fRqWht1SVjfmdTOYbLxbvw==|6nMLdGVZmXlnSjmDyJC94ljd/OYtCTflhVew0+uB4smS2YfFdmkfely/ZMU5UyDyuTCMp5ynw0ERTm3whVmwNGZkYHYT1iuU8I+N5zSQyuNPqnTREGFVslwcMSqkgINYUNoTnJYr/YkLjqzBLt4R5AvFY9Pxq20c+u+3obGcXVW2I11cxF47HVQde9pks72EvOw8KAQs6nQxx8CS/hWLmpZCh/f9yZ0PtNoeik+NxsnSI9veaLvr9yUwqWyhpF1+EI+PMpYZzUopyue8c0aihEUe5Pthz5z1KU+JXMWAAvtg/6eYFi8fQqT8Y6BOZh07makHPYIePQ2O/vgAETldiSlWwmjczZCQ5OXE4wromnzxKBYu1/K2uFUuQ0CD+xsleZImAyYR1W2zVslLFb/ILUX0RSKuqA2MlZizRldTY4nZ7quOWfHP0YD6iRK3oGFf7FfYPAPlcPOPDKl1tEhel3a3M8R0mkyb2e2S6IoW0hfYE4V4J0+VEmdNu7LQqFleqpEPl7icG0Z0EpP3KIJ4OcnO3gbUyo83MOyq4TQMIl46BQt42R4NcoA4hedV/YblUwnri58ugKfURH4+iSjv/r+F2uoSzJu2vdVHka3lF30bwhemyEUhsOZtHaEXpasKHesMknTv4/e+FhAdE9hjplWQyXO7rATXH6F0nEbyCDfOkghZAiAboTjBcE1FoqXBdCSkn4uVzmeWIGJp7izqzM/8zLK2VPUAMtxJGh9+rcv27bLYsbHfcnvEhCyXEsxa0b3DSGijyeSQC2yBNqJen9/SHbsCGNDOLNNyzYUzfIepQ52Oy2LgJEZ57ODTUybPfX4tyW8b+NriSzkUsx9Lp6hh/UaF6f+hBcQ7/dWVoHTJFyUHB1eni0PfFot0dXusg4n7usaG4e4ZSDQprgPHCyg+c3IxauHQmh9/oq1C4/5KuXIB/vOtMq98xjwnZTRdiJxOS82UyqpnwYcGQ9W2RIqKt1GXo/R5rgPXXtgmssqClu7QKI4sHA5lzTs1ef5BHFW1zAYPmsFvovTdX8ckrSdAoeQHJlIb4WyCNB4swNhmMFeQpdgCAZsBAjr+GG6Ak0JxXa2eQBF3zs0f37ly0t3BV7cCuDYKKSol5q14zTQkSQNg+/7TmhtmJo9ducSNS8orQT5IYA+OJa28wGfXjKKaSu0WSH/Tr83984nOQfUdlUZ2rqiskzW7/KUK2nlUceBty+0npuvrzqKk4eDIlJvh6uqwbU0C6SU9MFa0u4nXzfDvDHOgzuz4mNyCYe9tWzU2qArH9dzYMdc1UVj8qlmrPm2WkuXeEEYO+4MBAEHIuQxs21EshpE+2kePRpE5XHn/NbuZhbZ3j7ZD8w7Pyp4PC+hVAg83P+fvWU5CRuA8Ee2wNE6TORtqjnzW40Uh4JcQCaGwOt7dnDVygOsD9NGQrcrY8rLnK1kFMLJmfJtJ8BAn4A18RscI8OuwBkpfoOe9QldDXYsSAJ40K/yE3Nk25Csb3sgoHttfy43CpIIYvNzrqajZA0IvP22eWiF/FeZKO7zm0Myw33ARyHFw2yiBLNys4xxVuL3YmpolHRzOaUqtWA3bNJTmKWiBXxlJvL8+OvbfY+TYXJdVBUVzaATG4CL546j5hduhZfDxJQk=|1kt/ukROVrAIqC47wt8TLQYVh9jeZaCUE3/hHo8hCNA=", + "providerOrganizations": [], + "providers": [], + "securityStamp": "e968bbd1-9f65-46ef-b14e-0d557b3b3b1a", + "twoFactorEnabled": false, + "usesKeyConnector": false + }, + "sends": [], + "unofficialServer": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json new file mode 100644 index 0000000..fda609c --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json @@ -0,0 +1,37 @@ +{ + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:23:54.690520Z", + "data": { + "fields": [], + "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "30b00bfa-a32f-466a-9f23-dbc312455790", + "identity": null, + "key": "2.EFS7b18DYHnPgrK8tI0crw==|Ce+Dek2JYNCk05ijSYm78WS0+Y8odUeNDQsrAnkXllMAc4NG1FfCOhcfT2CHBlQD/YudriUvyhrTvWI/5GQIu9sCHRhEUYQE7o9yGOh/VmQ=|jescgRjRQqz+K6OSlVgNqjTJ6go3khELIm+TKfxE4gQ=", + "login": { + "uri": null, + "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + }, + "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:23:54.690612Z", + "secureNote": null, + "type": 1, + "viewPassword": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_accounts_prelogin.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_accounts_prelogin.json new file mode 100644 index 0000000..fa0e343 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_accounts_prelogin.json @@ -0,0 +1,6 @@ +{ + "kdf": 1, + "kdfIterations": 3, + "kdfMemory": 64, + "kdfParallelism": 4 +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json new file mode 100644 index 0000000..469ed03 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json @@ -0,0 +1,23 @@ +{ + "ForcePasswordReset": false, + "Kdf": 1, + "KdfIterations": 3, + "KdfMemory": 64, + "KdfParallelism": 4, + "Key": "2.Q+HxT8fkXKmM+irKC+1D6g==|hxmjLJ2RZUPM2uWk0gmPmNe0/OQrCbB49hKUIoqvXWbUaxricj62fATs81UZaKQoC5Re1LPyFsioRImDl1L+sv+EcBEhOx/0wqZ+JPNxXms=|t0G4kLfldPtNCg3wzXU81olAxgbe6sZHAMlQkjjJLck=", + "MasterPasswordPolicy": { + "object": "masterPasswordPolicy" + }, + "PrivateKey": "2.fRqWht1SVjfmdTOYbLxbvw==|6nMLdGVZmXlnSjmDyJC94ljd/OYtCTflhVew0+uB4smS2YfFdmkfely/ZMU5UyDyuTCMp5ynw0ERTm3whVmwNGZkYHYT1iuU8I+N5zSQyuNPqnTREGFVslwcMSqkgINYUNoTnJYr/YkLjqzBLt4R5AvFY9Pxq20c+u+3obGcXVW2I11cxF47HVQde9pks72EvOw8KAQs6nQxx8CS/hWLmpZCh/f9yZ0PtNoeik+NxsnSI9veaLvr9yUwqWyhpF1+EI+PMpYZzUopyue8c0aihEUe5Pthz5z1KU+JXMWAAvtg/6eYFi8fQqT8Y6BOZh07makHPYIePQ2O/vgAETldiSlWwmjczZCQ5OXE4wromnzxKBYu1/K2uFUuQ0CD+xsleZImAyYR1W2zVslLFb/ILUX0RSKuqA2MlZizRldTY4nZ7quOWfHP0YD6iRK3oGFf7FfYPAPlcPOPDKl1tEhel3a3M8R0mkyb2e2S6IoW0hfYE4V4J0+VEmdNu7LQqFleqpEPl7icG0Z0EpP3KIJ4OcnO3gbUyo83MOyq4TQMIl46BQt42R4NcoA4hedV/YblUwnri58ugKfURH4+iSjv/r+F2uoSzJu2vdVHka3lF30bwhemyEUhsOZtHaEXpasKHesMknTv4/e+FhAdE9hjplWQyXO7rATXH6F0nEbyCDfOkghZAiAboTjBcE1FoqXBdCSkn4uVzmeWIGJp7izqzM/8zLK2VPUAMtxJGh9+rcv27bLYsbHfcnvEhCyXEsxa0b3DSGijyeSQC2yBNqJen9/SHbsCGNDOLNNyzYUzfIepQ52Oy2LgJEZ57ODTUybPfX4tyW8b+NriSzkUsx9Lp6hh/UaF6f+hBcQ7/dWVoHTJFyUHB1eni0PfFot0dXusg4n7usaG4e4ZSDQprgPHCyg+c3IxauHQmh9/oq1C4/5KuXIB/vOtMq98xjwnZTRdiJxOS82UyqpnwYcGQ9W2RIqKt1GXo/R5rgPXXtgmssqClu7QKI4sHA5lzTs1ef5BHFW1zAYPmsFvovTdX8ckrSdAoeQHJlIb4WyCNB4swNhmMFeQpdgCAZsBAjr+GG6Ak0JxXa2eQBF3zs0f37ly0t3BV7cCuDYKKSol5q14zTQkSQNg+/7TmhtmJo9ducSNS8orQT5IYA+OJa28wGfXjKKaSu0WSH/Tr83984nOQfUdlUZ2rqiskzW7/KUK2nlUceBty+0npuvrzqKk4eDIlJvh6uqwbU0C6SU9MFa0u4nXzfDvDHOgzuz4mNyCYe9tWzU2qArH9dzYMdc1UVj8qlmrPm2WkuXeEEYO+4MBAEHIuQxs21EshpE+2kePRpE5XHn/NbuZhbZ3j7ZD8w7Pyp4PC+hVAg83P+fvWU5CRuA8Ee2wNE6TORtqjnzW40Uh4JcQCaGwOt7dnDVygOsD9NGQrcrY8rLnK1kFMLJmfJtJ8BAn4A18RscI8OuwBkpfoOe9QldDXYsSAJ40K/yE3Nk25Csb3sgoHttfy43CpIIYvNzrqajZA0IvP22eWiF/FeZKO7zm0Myw33ARyHFw2yiBLNys4xxVuL3YmpolHRzOaUqtWA3bNJTmKWiBXxlJvL8+OvbfY+TYXJdVBUVzaATG4CL546j5hduhZfDxJQk=|1kt/ukROVrAIqC47wt8TLQYVh9jeZaCUE3/hHo8hCNA=", + "ResetMasterPassword": false, + "UserDecryptionOptions": { + "HasMasterPassword": true, + "Object": "userDecryptionOptions" + }, + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTM4MzQsImV4cCI6MTcyNzg2MTAzNCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6IjNmMGFiZjE3LWU3NzktNDMxMi1hM2RkLTljNjI2NmU5NWE5ZSIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjFAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMUBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJlOTY4YmJkMS05ZjY1LTQ2ZWYtYjE0ZS0wZDU1N2IzYjNiMWEiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsiQXBwbGljYXRpb24iXX0.gbUXx7PzaRxB6DkMwHiVWHpFw_RC2Ztow3FpKct1mXI1gc3drMWqA8sQJtLu2wnslaD2pTYECcBejLFpgU2z4Z-homCbWxL9kr5O_3GkR_4RId9iVVY2P-TY-wX4GRY7IpQCPzGLUSL1cqSjlLx4cLIr6nmEiySQj2kvnR7ce3xqcb0rMeZMm72lC9UySP_VdlYE6nYEvNGVhstLfLSx44SBIhRzSGXYtezgyE-RBEcH1uv8WzUimfnhb_KoyAmxu9RaYffzFF-J6PFHswQt7tbbl5CYK_jpNvptaBBcyesuM_QpwuJNAyDovncDgHfFwMzNpuwW86i-wfEpWsnoNQ", + "expires_in": 7200, + "refresh_token": "jRlQnvOEIPacYzAFp5gmFEDVfBFE0gqYpdgok-PZtS1Vs5JNIf84KCKrAOi-SUtwL-snjCRnnychciR2k3C3Ng==", + "scope": "api offline_access", + "token_type": "Bearer", + "unofficialServer": true +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test_accounts.go b/internal/bitwarden/embedded/fixtures/test_accounts.go new file mode 100644 index 0000000..4a13f78 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test_accounts.go @@ -0,0 +1,47 @@ +package fixtures + +const ( + ServerURL = "http://127.0.0.1:8080" + + RsaPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAlRbtt5Vyku3dUIkPR0Y3v94qvZReuwAijIwHQGQOuKw6lKVV +HL29rZ93TwCG2P5a+GKH2+2fIbT/wTMTK4K1ElxQZ/2yLN9Hfu2d/ITNTsfTzPXv +F3fao3Q0JmD7DNJS2bJqng3so28aFddOZ03H55m9T6+0ZJqrMdgE5Z1V/4I7LFF6 +JxGGZ4mg99OvfQ5K8GOBM6SCI6h5eMXM5EkSM9vol9sRxvVLZmvNKH3UP9riyQwt +dcD5IxmY1y34Bg4b+a8tYaP7v90xF73uKs+287yNPLhWE9i+/gXwvApVxENG9SCP +lSrAEHd1NZPfsZhHoG+LXhyCZu2COttZess44QIDAQABAoIBAAIXgN54+qMpJ+2M +yGsdvGj3vCy9+vSyWi8Tr3icdXMrKfTVgMUlvEurcOI/Mcp+v55MF3JF0kwylh3N +pSwbV3DBHN5Hp5xu8HmtahsoWRnXo98Z4oOB7U5gAj5kBmkMtKhB/fJW+UzF/C/b +I2906Tw59Uy2XIsROzvjMeGPnddh1LbvXUb9nAmhi7napdwCUbeqvatu56GyiXxV +03DTwhbfuU+nMi/M556WPEkPbJoG4bF82WqQ+6+a1NfE2wg//cc5CzXQehC6jGx6 +Pi+uNUtPhMSyTnJgpvg+Ob2r/LTiL0zic00ka29xUsi7EwXKUR2ih8JTkSPaTR06 +3ezrg3ECgYEAzi/MnXfWp49jRgb4bHE9Cy63hehgaBvIcEyhFKOz5OD6nI4Lg/3z +SNDQo9YhwMqschqQLHVEtjxDT0V/RHdX4icTF+zSCl/T79EtM/R1nMT0MSIXV7IE +NtPbnqXOjrbe3vgjLvBst/cWpGHiML+znCqukHOevSn7yUlg4b1aMVECgYEAuRvL +YnbNlps/nql1EW9DUKOEV7kBvehwGzYpFfZ7pRscl6RyISTipGMOzJmOSfscYwqR +HrFpTNMNxjnyXOuv4OTC7bCIUJc6N8AZ4jm4452ibxpzktlO8Im+TbsD6mZDT8zB +d+8o/8ST9j1zy43Sb+f5vxfB6fC9vUXpBW0+KpECgYEAzQKT9cJxSVv1/mvx2Ilj +g9nompmqOfnd+2MGCuqWdS4JoV5PLudzXeRaf3zrRLGAc1fcIIhdUMFsv8Y/O8la +NcBaaMCNO8l6hoo64tzfkIf4sV3PTd/v9sACL6V3U0mbIqIhAYwG3YguGDZHW+dQ +ZCfAOFrt6/Jxqvtt/CZ1JnECgYBOxmdNZeWj/Dmc2dy6KLFq9ctyUYdOPEbJLcla +UWTZJKqMVi1DsaDJ+GXp6EdHcJfqBisv9qwrR34LJ8nehWZ5vKC/6mp4cYMTCqt5 +PLtUEld4FLeufNA9SUE1bysBa7ellCuZUKwP/KZDGm/W5mnxubTs/71EQ3FbxQ6f +gpf8IQKBgGHK8j8rvxtszoQKUY+XpWFrP0x5pDLiAkmQ0bmF2KRIahq3anla6n3i +/LL5BrUdMjEnvAb+RASq+41rceq4rLcz0pA2yOWNjhbCAPFdU5MQMkJ4/zqHtzvd +GqwE00g9gizQ6CmsaNNJh7y6gNg0TBU2EGqTaQMz37fheAEt3NSt +-----END RSA PRIVATE KEY----- +` + + EncryptionKey = "Vr+KA/il3QX4z7EqFnhQ3U8TtETlQPKkXHCE2PiR75wwzDVRutR4rib/jMtgZ1S/gPyOEXbwKFju2oJq3njVLg==" + TestPassword = "test12341234" + + Pdkdf2Email = "test-kdf0@laverse.net" + Pdkdf2Mocks = "test-kdf0" + Pdkdf2ProtectedSymmetricKey = "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=" + Pdkdf2ProtectedRSAPrivateKey = "2.11j1IvphccY0UkZov7ZbmQ==|4J34a16NM+krEXyDUkHVUNL2sSA7dph4EBCLWoDkmDoljqMZh5IxA7M51yZTNB6/uqGgJZJX0uU+B4RSn2s2JoFG/VizMmgSIJkTIr6WuA7taEzyIFRi7sY980W02pnLeb8fGV8EXrZk1Bj0UzAFukNGoeS2CHWbm0bZKRvDxl5Vw40V3Lt6GzHTb6X+4k4Ovg0UKgm2mqMWzxxjmCfy+G1R0vlsAtqg14n2ax5f3Jn4ajGDvT2BQia9EFYFkie/SfqgsYbtvou4DvyCTEWh0j9Cre1QIJQ9AZ4AHAzGwIKFhpN7sWjsfw6yTGmvxAfflCMFzCdleBBiuCefaAKNe5Uf1QASC9TzIiHknl2+sK9lOFZ+XZJ41HCU2sMvNBu1EHuBPNRIHodCEHdXHyRqBaC+vgWO6RcTWU4K5ZctBKmElAYst7FFCuzM+liUcGp3I1a7wxOJTPraxeFw8z69rYFiNMOng/HkV/G/VUQXzWalC5gtjaR35dMp35Mf1lMlGnWhy/qdLr0NVdl69qUDKt+kCG9+kiXO7Eq5PTbV+tj4AxBzxE1DroAh0jTPFLb7p1205+OQqqrCEq6tzpGHKTFLoyHZCVoxdQvxgFNX6+fNi3+MfbDfLle7msQAwOuaUl6rxcb2JjdgRQQUd4/GQbvKeLjFRIr7OtcVHWm3251jqRLBgFJcQ235SFgdjLnKATqN4BRe0WLyYOMuMQEmfQXaebjzMo7L2JMJeOar9QutuV+Acle7kJZZU4N1XPiUmborUksAcrmLGXvQITn1QLmadou0jX/oov+lkrKDIFTJC5MIutVBNmExS6FqW978viF1ZNgRQxG5OULHoT5tgfyjrl2u74VFf0ttbLC/JSsi1k8me2LA2vi2Sx7DNOzd6fLx0f8+mYmz2VTRw6fnoFh99d8HktPUNyKcGNZyZpsfkkhFSFV/U88tZ9gROWayLbRXS6g801Mi0tBg0RJp/Flo9ZX9Y3qKVWLCDZT6t3l1NR2npkGmi16yqslXSs9hadIvd6lxyYqyW6cskuJjsacHPOCyvz1xZFH6txtzmb46UrKUU7Cjo/09Kmtb740rXzhH/0nPuvJUjlk0UN77LqzvnvVWAe2IJVEjsbhTspLw3Z1fmCQxMKvc3yPA36/KP2uk/wOlHmBnuX/eebQmI22PFOzskl1d0ScNItJsw5D6fkEhybxEY3oPWYG5y+Oitqj1dQy/TNKXeJHMP+MC1PxzvaE3jq/+cb0IwVBnMVblbaHCJM6JAllV/p3Z6/Ho3Ps4hDHRflKZjP2HyB5wvvTtYhX5XpDoA8s9e6TpDXYnoE+XLN4Thzu30GL3WBeI7koYuNEpRhD5++oT2CElpEqo0v/TFKGSmnV+qohWTL8I4WnHSZeKDLC5alqIMYgRkN6qUlVJLzILOFzeJcL9zeXsAeHemd3VZWe0OYiJRxVwBCYGHk6W7WA4pZ+Wq/C0JHaxNJhr9gx0kyFlMPBkwN/LEyUP+PxsqIuW+09f70qZdGE1r9bNjUSKmb53I6nqxwQhIwvpZZDGAOZjaxrfC8PE9rOOTkM3v6zsSWgjl4EJMPwJubHJb63w5hvW2DwS4h3t7lduTab9ykKInvfBsaWxLuBhJuX+fesGTM0KGXs=|BXz0QzgtArYQXICHbYvGqOeFVi9YGZRP0MASNlVwzzY=" + + Argon2Email = "test-kdf1@laverse.net" + Argon2Mocks = "test-kdf1" + Argon2ProtectedSymmetricKey = "2.Q+HxT8fkXKmM+irKC+1D6g==|hxmjLJ2RZUPM2uWk0gmPmNe0/OQrCbB49hKUIoqvXWbUaxricj62fATs81UZaKQoC5Re1LPyFsioRImDl1L+sv+EcBEhOx/0wqZ+JPNxXms=|t0G4kLfldPtNCg3wzXU81olAxgbe6sZHAMlQkjjJLck=" + Argon2ProtectedRSAPrivateKey = "2.fRqWht1SVjfmdTOYbLxbvw==|6nMLdGVZmXlnSjmDyJC94ljd/OYtCTflhVew0+uB4smS2YfFdmkfely/ZMU5UyDyuTCMp5ynw0ERTm3whVmwNGZkYHYT1iuU8I+N5zSQyuNPqnTREGFVslwcMSqkgINYUNoTnJYr/YkLjqzBLt4R5AvFY9Pxq20c+u+3obGcXVW2I11cxF47HVQde9pks72EvOw8KAQs6nQxx8CS/hWLmpZCh/f9yZ0PtNoeik+NxsnSI9veaLvr9yUwqWyhpF1+EI+PMpYZzUopyue8c0aihEUe5Pthz5z1KU+JXMWAAvtg/6eYFi8fQqT8Y6BOZh07makHPYIePQ2O/vgAETldiSlWwmjczZCQ5OXE4wromnzxKBYu1/K2uFUuQ0CD+xsleZImAyYR1W2zVslLFb/ILUX0RSKuqA2MlZizRldTY4nZ7quOWfHP0YD6iRK3oGFf7FfYPAPlcPOPDKl1tEhel3a3M8R0mkyb2e2S6IoW0hfYE4V4J0+VEmdNu7LQqFleqpEPl7icG0Z0EpP3KIJ4OcnO3gbUyo83MOyq4TQMIl46BQt42R4NcoA4hedV/YblUwnri58ugKfURH4+iSjv/r+F2uoSzJu2vdVHka3lF30bwhemyEUhsOZtHaEXpasKHesMknTv4/e+FhAdE9hjplWQyXO7rATXH6F0nEbyCDfOkghZAiAboTjBcE1FoqXBdCSkn4uVzmeWIGJp7izqzM/8zLK2VPUAMtxJGh9+rcv27bLYsbHfcnvEhCyXEsxa0b3DSGijyeSQC2yBNqJen9/SHbsCGNDOLNNyzYUzfIepQ52Oy2LgJEZ57ODTUybPfX4tyW8b+NriSzkUsx9Lp6hh/UaF6f+hBcQ7/dWVoHTJFyUHB1eni0PfFot0dXusg4n7usaG4e4ZSDQprgPHCyg+c3IxauHQmh9/oq1C4/5KuXIB/vOtMq98xjwnZTRdiJxOS82UyqpnwYcGQ9W2RIqKt1GXo/R5rgPXXtgmssqClu7QKI4sHA5lzTs1ef5BHFW1zAYPmsFvovTdX8ckrSdAoeQHJlIb4WyCNB4swNhmMFeQpdgCAZsBAjr+GG6Ak0JxXa2eQBF3zs0f37ly0t3BV7cCuDYKKSol5q14zTQkSQNg+/7TmhtmJo9ducSNS8orQT5IYA+OJa28wGfXjKKaSu0WSH/Tr83984nOQfUdlUZ2rqiskzW7/KUK2nlUceBty+0npuvrzqKk4eDIlJvh6uqwbU0C6SU9MFa0u4nXzfDvDHOgzuz4mNyCYe9tWzU2qArH9dzYMdc1UVj8qlmrPm2WkuXeEEYO+4MBAEHIuQxs21EshpE+2kePRpE5XHn/NbuZhbZ3j7ZD8w7Pyp4PC+hVAg83P+fvWU5CRuA8Ee2wNE6TORtqjnzW40Uh4JcQCaGwOt7dnDVygOsD9NGQrcrY8rLnK1kFMLJmfJtJ8BAn4A18RscI8OuwBkpfoOe9QldDXYsSAJ40K/yE3Nk25Csb3sgoHttfy43CpIIYvNzrqajZA0IvP22eWiF/FeZKO7zm0Myw33ARyHFw2yiBLNys4xxVuL3YmpolHRzOaUqtWA3bNJTmKWiBXxlJvL8+OvbfY+TYXJdVBUVzaATG4CL546j5hduhZfDxJQk=|1kt/ukROVrAIqC47wt8TLQYVh9jeZaCUE3/hHo8hCNA=" +) diff --git a/internal/bitwarden/embedded/vault_base_test.go b/internal/bitwarden/embedded/vault_base_test.go index 8f814a1..fb3e75d 100644 --- a/internal/bitwarden/embedded/vault_base_test.go +++ b/internal/bitwarden/embedded/vault_base_test.go @@ -9,61 +9,64 @@ import ( "time" "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/crypto/symmetrickey" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/embedded/fixtures" "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/models" "github.com/stretchr/testify/assert" ) +const ( + orgKey = "4.JW3mktbL7vpTVRweZdQBAirJuAEhSRn37zcXZjDjI47weFKkeZkvPxZWCqFYC/P5qCJwEYMbv7lTETkWDg6paevVfhJ35buGcTQdEbQxAJebzPahEcUstj11l4Y9T5RaDiAJR8+drrGJ3fKV3v3hymKz2o9fUfK1epuLFll2nnWSOjCcuRe/+zz5VwIVx4WJAPJHmiS6eofbj/DTIQCzG4JkR0UzT66ouLcgmPL1nGOqVI7KxRpL5yVj75UkjniHkWAcB7lfAxWXw2GhDJ/2L685uA3820ItTbxjCwLQOvjBttgrbURmkeP9BD+KkO4V6vb8bbTWNSvggXKk2h1CMw==" + orgUuid = "81cc1652-dc80-472d-909f-9539d057068b" +) + var ( - testAccount = Account{ + testAccountPbkdf2 = Account{ AccountUUID: "e8dababd-242e-4900-becf-e88bc021dda8", - Email: "test@laverse.net", + Email: fixtures.Pdkdf2Email, VaultFormat: "API", KdfConfig: models.KdfConfiguration{ KdfType: models.KdfTypePBKDF2_SHA256, KdfIterations: 600000, }, - ProtectedSymmetricKey: "2.lkAJiJtCKPHFPrZ96+j2Xg==|5XJtrKUndcGy28thFukrmgMcLp+BOVdkF+KcuOnfshq9AN1PFhna9Es96CVARCnjTcWuHuqvgnGmcOHTrf8fyfLv63VBsjLgLZk8rCXJoKE=|9dwgx4/13AD+elE2vE7vlSQoe8LbCGGlui345YrKvXY=", - ProtectedRSAPrivateKey: "2.D2aLa8ne/DAkeSzctQISVw==|/xoGM5i5JGJTH/vohUuwTFrTx3hd/gt3kBD/FQdeLMtYjl1u96sh0ECmoERqGHeSfXj+iAb9kpTIOKG8LwmkZGUJBI90Mw0M7ODmf7E8eQ+aGF+bGqTSMQ1wtpunEyFVodlg92YN8Ddlb2V9J4uN8ykpHYNDmQiYLZ8bl6vCODRGPyzLvx5M8DbITVL5PhsjKDLLrVV8lFCgCcAL5YLfkghYhFELyX15zXA/KYEnwggDka3hG5+HHFOVZSeyk7Gi6M4TX2wADbTXz1/Wsho8oxFUrtNiOB3ZiY2cx9UWttpzMXoGfi2gJcP1db/nTfWenOLlzw6Od4VyRzsXsfyGwbqBqDnNFkjLvhjVw4JO+psF//xAMDs14101Tf2wFkB6toQ+zdnDphXUeKmiVPQ7gMnQlOWN5tWvjjmYOO4Y63sGpP24cDOdEScIdebZRSA8uOhTzadfKfOiH5zVYZzXs33FQ0li4nBrsj5xYa6PP4D1P7gqjxClPdguwkdLoZ7JvgIlyRIwEcORi5Ich8RWF/kqRBwk0QSzK1mTlHHU5xtSgi4MLNVx4qTYNaJVBtwL9d2MD9LeNn4Z2PL4A7qnszHqsERiQQDxNEgMxMBHDgSXqQbtQxRvsI6oY+yNbN7uVWw4o8AC3f5GBdxzIqcN1mgEM5ix5aDt15w3MhP2FHtf2neKI68TnL8WnT1fT8BVlbECIiUqK0tfq5aTjdSh3gCS15jvZ1H60h+K8+O/nDfquzVjY7UsTGwA+UtS8/JGiaUhc0VhxJo8P1V2VSCiu51d5q3De1vDg5R2VEgBmTchZyTIodC+3+7ACTOwkNCCdIJN7xKOcIGFA7QOuyJtBeXT4Rd9UGMHSL054IB/315WVDiwrP9W1aP0nHzFs+qAXbH5o1E+AmfMDyoHopjGgbUw22r837kHzf5Qe8QhRYPzQvDowfCPhdoy23cbN1VsNavNwTC9hcG5oYMwkK66xP3MEM9UfGD22pwxe7M8U4BRdLCCHbi95eklXE6Mg6DpWsAdMgokQbOvnlwgKfrlbltqXUE/vUQI8TB3AE1Nkt0ST4quTriMuuyiHdeeZV4UkV9jWt/5bTCfdrCYuGZP7g4shbfNcP7u1Zrdxv+EuUwGIOOTrNV5awmBnL3iHE5ya2MnqmRyfWiPIT5majZCk06yxj4XzyIPOpjYKFt0MOgLvG1GllmdtRqg7tMVvc5ZFo5KWIxLsIJD12UjA1GYYoFdX4+wsNbPjfnlE6D2PrtWUICnBFJzYpfyrKTe01k8G8hyyz+tVzBRfz8EA2ew1+hlVcAgSPCcBzhDgqPe+RSPi7ZSd66be1gDhGAftWFM8Z0MrMklXi2DyjjaKBNsZZD8qTcLcobm8nqHUQtnr5JCbmgP3rau8NY/fxeFHsvSiZQoB1aI/y+Sz/R4r+T9cg8hjmS/FUHDO+m6a6nuWNFwz8wIluM557oOTl+A9UGFF50Gpzmf97VdQjM3ZREazQ7la6AobzS3BHI6FNdxN9LTyMpYo+WODv52/VwU3ODH7wf5bz2OHZhk2NG5R7pSH7qg8jM+/MtJkFumENV0qMecozIkP6e4CyI9ua4YwI9n7G5OgKYMG1aj2PRSny2JSLS8aHF1TkRL8SD0nZFCox0=|muEtiwIuZxhuuLv0nouEdxHU2CO+I7JXKZuYHWiv/OE=", + ProtectedSymmetricKey: fixtures.Pdkdf2ProtectedSymmetricKey, + ProtectedRSAPrivateKey: fixtures.Pdkdf2ProtectedRSAPrivateKey, } - rsaPrivateKey = `-----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAlRbtt5Vyku3dUIkPR0Y3v94qvZReuwAijIwHQGQOuKw6lKVV -HL29rZ93TwCG2P5a+GKH2+2fIbT/wTMTK4K1ElxQZ/2yLN9Hfu2d/ITNTsfTzPXv -F3fao3Q0JmD7DNJS2bJqng3so28aFddOZ03H55m9T6+0ZJqrMdgE5Z1V/4I7LFF6 -JxGGZ4mg99OvfQ5K8GOBM6SCI6h5eMXM5EkSM9vol9sRxvVLZmvNKH3UP9riyQwt -dcD5IxmY1y34Bg4b+a8tYaP7v90xF73uKs+287yNPLhWE9i+/gXwvApVxENG9SCP -lSrAEHd1NZPfsZhHoG+LXhyCZu2COttZess44QIDAQABAoIBAAIXgN54+qMpJ+2M -yGsdvGj3vCy9+vSyWi8Tr3icdXMrKfTVgMUlvEurcOI/Mcp+v55MF3JF0kwylh3N -pSwbV3DBHN5Hp5xu8HmtahsoWRnXo98Z4oOB7U5gAj5kBmkMtKhB/fJW+UzF/C/b -I2906Tw59Uy2XIsROzvjMeGPnddh1LbvXUb9nAmhi7napdwCUbeqvatu56GyiXxV -03DTwhbfuU+nMi/M556WPEkPbJoG4bF82WqQ+6+a1NfE2wg//cc5CzXQehC6jGx6 -Pi+uNUtPhMSyTnJgpvg+Ob2r/LTiL0zic00ka29xUsi7EwXKUR2ih8JTkSPaTR06 -3ezrg3ECgYEAzi/MnXfWp49jRgb4bHE9Cy63hehgaBvIcEyhFKOz5OD6nI4Lg/3z -SNDQo9YhwMqschqQLHVEtjxDT0V/RHdX4icTF+zSCl/T79EtM/R1nMT0MSIXV7IE -NtPbnqXOjrbe3vgjLvBst/cWpGHiML+znCqukHOevSn7yUlg4b1aMVECgYEAuRvL -YnbNlps/nql1EW9DUKOEV7kBvehwGzYpFfZ7pRscl6RyISTipGMOzJmOSfscYwqR -HrFpTNMNxjnyXOuv4OTC7bCIUJc6N8AZ4jm4452ibxpzktlO8Im+TbsD6mZDT8zB -d+8o/8ST9j1zy43Sb+f5vxfB6fC9vUXpBW0+KpECgYEAzQKT9cJxSVv1/mvx2Ilj -g9nompmqOfnd+2MGCuqWdS4JoV5PLudzXeRaf3zrRLGAc1fcIIhdUMFsv8Y/O8la -NcBaaMCNO8l6hoo64tzfkIf4sV3PTd/v9sACL6V3U0mbIqIhAYwG3YguGDZHW+dQ -ZCfAOFrt6/Jxqvtt/CZ1JnECgYBOxmdNZeWj/Dmc2dy6KLFq9ctyUYdOPEbJLcla -UWTZJKqMVi1DsaDJ+GXp6EdHcJfqBisv9qwrR34LJ8nehWZ5vKC/6mp4cYMTCqt5 -PLtUEld4FLeufNA9SUE1bysBa7ellCuZUKwP/KZDGm/W5mnxubTs/71EQ3FbxQ6f -gpf8IQKBgGHK8j8rvxtszoQKUY+XpWFrP0x5pDLiAkmQ0bmF2KRIahq3anla6n3i -/LL5BrUdMjEnvAb+RASq+41rceq4rLcz0pA2yOWNjhbCAPFdU5MQMkJ4/zqHtzvd -GqwE00g9gizQ6CmsaNNJh7y6gNg0TBU2EGqTaQMz37fheAEt3NSt ------END RSA PRIVATE KEY----- -` - - encryptionKey = "Vr+KA/il3QX4z7EqFnhQ3U8TtETlQPKkXHCE2PiR75wwzDVRutR4rib/jMtgZ1S/gPyOEXbwKFju2oJq3njVLg==" - orgKey = "4.JW3mktbL7vpTVRweZdQBAirJuAEhSRn37zcXZjDjI47weFKkeZkvPxZWCqFYC/P5qCJwEYMbv7lTETkWDg6paevVfhJ35buGcTQdEbQxAJebzPahEcUstj11l4Y9T5RaDiAJR8+drrGJ3fKV3v3hymKz2o9fUfK1epuLFll2nnWSOjCcuRe/+zz5VwIVx4WJAPJHmiS6eofbj/DTIQCzG4JkR0UzT66ouLcgmPL1nGOqVI7KxRpL5yVj75UkjniHkWAcB7lfAxWXw2GhDJ/2L685uA3820ItTbxjCwLQOvjBttgrbURmkeP9BD+KkO4V6vb8bbTWNSvggXKk2h1CMw==" - testPassword = "test12341234" + testAccountArgon2 = Account{ + AccountUUID: "e8dababd-242e-4900-becf-e88bc021dda8", + Email: fixtures.Argon2Email, + VaultFormat: "API", + KdfConfig: models.KdfConfiguration{ + KdfType: models.KdfTypeArgon2, + KdfIterations: 3, + KdfMemory: 64, + KdfParallelism: 4, + }, + ProtectedSymmetricKey: fixtures.Argon2ProtectedSymmetricKey, + ProtectedRSAPrivateKey: fixtures.Argon2ProtectedRSAPrivateKey, + } ) -func TestDecryptAccountSecret(t *testing.T) { - accountSecrets, err := decryptAccountSecrets(testAccount, testPassword) +func TestDecryptAccountSecretPbkdf2(t *testing.T) { + accountSecrets, err := decryptAccountSecrets(testAccountPbkdf2, fixtures.TestPassword) + assert.NoError(t, err) + assert.Equal(t, "jHZYmFOOr0KGorSsmWeuGMHWJDqRrz7uwZNBJkZaupM=", accountSecrets.MasterPasswordHash) + + pemdata := pem.EncodeToMemory( + &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: x509.MarshalPKCS1PrivateKey(accountSecrets.RSAPrivateKey), + }, + ) + + assert.Equal(t, fixtures.RsaPrivateKey, strings.Replace(string(pemdata), "\\n", "\n", -1)) + assert.Contains(t, accountSecrets.MainKey.Summary(), fixtures.EncryptionKey) +} + +func TestDecryptAccountSecretArgon2(t *testing.T) { + accountSecrets, err := decryptAccountSecrets(testAccountArgon2, fixtures.TestPassword) assert.NoError(t, err) - assert.Equal(t, "qOOJSiS6KGqePb+ZxBPD9G37cZjFfViArWiHCd0koK4=", accountSecrets.MasterPasswordHash) + assert.Equal(t, "3fBImY0XFvRrUSP/fe6mqUc1bjhWBuvHYJvlwnxS0i4=", accountSecrets.MasterPasswordHash) pemdata := pem.EncodeToMemory( &pem.Block{ @@ -72,18 +75,18 @@ func TestDecryptAccountSecret(t *testing.T) { }, ) - assert.Equal(t, rsaPrivateKey, strings.Replace(string(pemdata), "\\n", "\n", -1)) - assert.Contains(t, accountSecrets.MainKey.Summary(), encryptionKey) + assert.Equal(t, fixtures.RsaPrivateKey, strings.Replace(string(pemdata), "\\n", "\n", -1)) + assert.Contains(t, accountSecrets.MainKey.Summary(), fixtures.EncryptionKey) } func TestDecryptAccountSecretWrongPassword(t *testing.T) { - _, err := decryptAccountSecrets(testAccount, "wrong-password") + _, err := decryptAccountSecrets(testAccountPbkdf2, "wrong-password") assert.Error(t, err, "decryption should fail with wrong password") assert.ErrorIs(t, err, models.ErrWrongMasterPassword) } func TestEncryptItem(t *testing.T) { - accountSecrets := testAccountSecrets(t) + accountSecrets := computeTestAccountSecrets(t) objectToEncrypt := testFullyFilledObject() objectToEncrypt.OrganizationID = "81cc1652-dc80-472d-909f-9539d057068b" @@ -333,8 +336,8 @@ func testFullyFilledLogin() models.Login { } } -func testAccountSecrets(t *testing.T) *AccountSecrets { - accountSecrets, err := decryptAccountSecrets(testAccount, testPassword) +func computeTestAccountSecrets(t *testing.T) *AccountSecrets { + accountSecrets, err := decryptAccountSecrets(testAccountPbkdf2, fixtures.TestPassword) if err != nil { t.Fatal(err) } @@ -345,8 +348,8 @@ func testAccountSecrets(t *testing.T) *AccountSecrets { } accountSecrets.OrganizationSecrets = map[string]OrganizationSecret{ - "81cc1652-dc80-472d-909f-9539d057068b": { - OrganizationUUID: "81cc1652-dc80-472d-909f-9539d057068b", + orgUuid: { + OrganizationUUID: orgUuid, Key: *key, }, } diff --git a/internal/bitwarden/embedded/vault_mocked_webapi_test.go b/internal/bitwarden/embedded/vault_mocked_webapi_test.go deleted file mode 100644 index 4eb4d4d..0000000 --- a/internal/bitwarden/embedded/vault_mocked_webapi_test.go +++ /dev/null @@ -1,753 +0,0 @@ -package embedded - -import ( - "context" - "crypto/x509" - "encoding/base64" - "encoding/pem" - "net/http" - "testing" - - "github.com/jarcoal/httpmock" - "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/crypto" - "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/crypto/keybuilder" - "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/webapi" -) - -func NewMockedWebAPIVault(t *testing.T, client webapi.Client) webAPIVault { - vault := NewWebAPIVault("http://127.0.0.1:8081/").(*webAPIVault) - vault.client = client - return *vault -} - -func mockedClient() webapi.Client { - client := http.Client{Transport: httpmock.DefaultTransport} - httpmock.RegisterResponder("POST", "http://127.0.0.1:8081/identity/accounts/prelogin", - httpmock.NewStringResponder(200, `{"kdf":0,"kdfIterations":600000,"kdfMemory":null,"kdfParallelism":null}`)) - - // Regexp match (could use httpmock.RegisterRegexpResponder instead) - httpmock.RegisterResponder("POST", `http://127.0.0.1:8081/identity/connect/token`, - httpmock.NewStringResponder(200, `{"ForcePasswordReset":false,"Kdf":0,"KdfIterations":600000,"KdfMemory":null,"KdfParallelism":null,"Key":"2.lkAJiJtCKPHFPrZ96+j2Xg==|5XJtrKUndcGy28thFukrmgMcLp+BOVdkF+KcuOnfshq9AN1PFhna9Es96CVARCnjTcWuHuqvgnGmcOHTrf8fyfLv63VBsjLgLZk8rCXJoKE=|9dwgx4/13AD+elE2vE7vlSQoe8LbCGGlui345YrKvXY=","MasterPasswordPolicy":{"object":"masterPasswordPolicy"},"PrivateKey":"2.D2aLa8ne/DAkeSzctQISVw==|/xoGM5i5JGJTH/vohUuwTFrTx3hd/gt3kBD/FQdeLMtYjl1u96sh0ECmoERqGHeSfXj+iAb9kpTIOKG8LwmkZGUJBI90Mw0M7ODmf7E8eQ+aGF+bGqTSMQ1wtpunEyFVodlg92YN8Ddlb2V9J4uN8ykpHYNDmQiYLZ8bl6vCODRGPyzLvx5M8DbITVL5PhsjKDLLrVV8lFCgCcAL5YLfkghYhFELyX15zXA/KYEnwggDka3hG5+HHFOVZSeyk7Gi6M4TX2wADbTXz1/Wsho8oxFUrtNiOB3ZiY2cx9UWttpzMXoGfi2gJcP1db/nTfWenOLlzw6Od4VyRzsXsfyGwbqBqDnNFkjLvhjVw4JO+psF//xAMDs14101Tf2wFkB6toQ+zdnDphXUeKmiVPQ7gMnQlOWN5tWvjjmYOO4Y63sGpP24cDOdEScIdebZRSA8uOhTzadfKfOiH5zVYZzXs33FQ0li4nBrsj5xYa6PP4D1P7gqjxClPdguwkdLoZ7JvgIlyRIwEcORi5Ich8RWF/kqRBwk0QSzK1mTlHHU5xtSgi4MLNVx4qTYNaJVBtwL9d2MD9LeNn4Z2PL4A7qnszHqsERiQQDxNEgMxMBHDgSXqQbtQxRvsI6oY+yNbN7uVWw4o8AC3f5GBdxzIqcN1mgEM5ix5aDt15w3MhP2FHtf2neKI68TnL8WnT1fT8BVlbECIiUqK0tfq5aTjdSh3gCS15jvZ1H60h+K8+O/nDfquzVjY7UsTGwA+UtS8/JGiaUhc0VhxJo8P1V2VSCiu51d5q3De1vDg5R2VEgBmTchZyTIodC+3+7ACTOwkNCCdIJN7xKOcIGFA7QOuyJtBeXT4Rd9UGMHSL054IB/315WVDiwrP9W1aP0nHzFs+qAXbH5o1E+AmfMDyoHopjGgbUw22r837kHzf5Qe8QhRYPzQvDowfCPhdoy23cbN1VsNavNwTC9hcG5oYMwkK66xP3MEM9UfGD22pwxe7M8U4BRdLCCHbi95eklXE6Mg6DpWsAdMgokQbOvnlwgKfrlbltqXUE/vUQI8TB3AE1Nkt0ST4quTriMuuyiHdeeZV4UkV9jWt/5bTCfdrCYuGZP7g4shbfNcP7u1Zrdxv+EuUwGIOOTrNV5awmBnL3iHE5ya2MnqmRyfWiPIT5majZCk06yxj4XzyIPOpjYKFt0MOgLvG1GllmdtRqg7tMVvc5ZFo5KWIxLsIJD12UjA1GYYoFdX4+wsNbPjfnlE6D2PrtWUICnBFJzYpfyrKTe01k8G8hyyz+tVzBRfz8EA2ew1+hlVcAgSPCcBzhDgqPe+RSPi7ZSd66be1gDhGAftWFM8Z0MrMklXi2DyjjaKBNsZZD8qTcLcobm8nqHUQtnr5JCbmgP3rau8NY/fxeFHsvSiZQoB1aI/y+Sz/R4r+T9cg8hjmS/FUHDO+m6a6nuWNFwz8wIluM557oOTl+A9UGFF50Gpzmf97VdQjM3ZREazQ7la6AobzS3BHI6FNdxN9LTyMpYo+WODv52/VwU3ODH7wf5bz2OHZhk2NG5R7pSH7qg8jM+/MtJkFumENV0qMecozIkP6e4CyI9ua4YwI9n7G5OgKYMG1aj2PRSny2JSLS8aHF1TkRL8SD0nZFCox0=|muEtiwIuZxhuuLv0nouEdxHU2CO+I7JXKZuYHWiv/OE=","ResetMasterPassword":false,"UserDecryptionOptions":{"HasMasterPassword":true,"Object":"userDecryptionOptions"},"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc1MTI0NjIsImV4cCI6MTcyNzUxOTY2MiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6ImU4ZGFiYWJkLTI0MmUtNDkwMC1iZWNmLWU4OGJjMDIxZGRhOCIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJUZXN0IExhdmVyc2UiLCJlbWFpbCI6InRlc3RAbGF2ZXJzZS5uZXQiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwic3N0YW1wIjoiNDAzM2NmMzUtYmM1ZC00ZWNkLTk1MWMtZGJlNTQ5ZjI3NzQwIiwiZGV2aWNlIjoiNWQ5MGI0NzAtNWQxZC00NTJkLTkzNWMtYjczMGMxNzdhOGQ2Iiwic2NvcGUiOlsiYXBpIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbIkFwcGxpY2F0aW9uIl19.hKXO3p4am134f74wx5WqmuRCT__1CcqiZ5YkU5q8FvXNY-oe_pOrU7gxpf9TDBIOQVTjVkE09dgzEKco_qMnRTT7cvQ95o3k82gNDNgyi0Yjqtv5eS8K7m7MrSOUqe6LwZwpKy3G8vDnu1O2kiN-So44cCBKQzqOrR4oimmYIMt8IWqU2qa8ZaFe1E70nv5NjUxiE_NkT2FF6M8MA7z_aEkcBeleknlKRL-gaqYqAPWhKF_msW9e3SKvm_83wt1JRwr60T4aKXbl7rB4UrSqs_lqhdb3i1Ul5_TYQXbg4yfETgT8Uh37kXtnK_8MlxNBpA8pEAnp_29Odync3T7naQ","expires_in":7200,"refresh_token":"6wCk9N0MG-abyrmBUn5m1ACq-oRnhj6mbjCeuOz_HPyPERfK8DPeTJVf3c6KtP-bIbL6mErO-ggMs_MNS2GlIg==","scope":"api offline_access","token_type":"Bearer","unofficialServer":true}`)) - - httpmock.RegisterResponder("GET", `http://127.0.0.1:8081/api/sync?excludeDomains=true`, - httpmock.NewStringResponder(200, `{ - "ciphers": [ - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-09-22T11:13:40.346903Z", - "data": { - "autofillOnPageLoad": null, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "password": null, - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "folderId": null, - "id": "24d1c150-5dfd-4008-964c-01317d1f6b23", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": null, - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:13:40.347356Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }, - { - "attachments": null, - "card": null, - "collectionIds": ["8d1a5611-5fd6-4728-a6f8-22bc03b50640"], - "creationDate": "2024-09-22T11:15:49.885670Z", - "data": { - "autofillOnPageLoad": null, - "fields": [], - "name": "2.kOK8qkac+p+c8mNjhkuO/w==|nP1hQA1/8rJt97NmWSarfchRF+XWAUflsYzq9X2lBPU=|J7AmiEiDRCWvlLjYBrwXxCgCLw4EQiXmvlKnJw0mTb8=", - "notes": null, - "password": "2.uiCrgwCc32t6jIaUcMiinw==|JJVfmpcdrekNqJLfJOVaGw==|1zpwpqlATK+6/av/6JfOoHJaOgtpNJA6LDqEqsR2C/A=", - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.6WVjMRz5qtfVkGJ40Ne+Fw==|LtPQSeBvHIEgmzTtpdq4lw==|BV/F2ZhCD1nsr/4RoETwpMnu8PPVYirxrDQXcF6gpg4=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [], - "folderId": null, - "id": "94b0e53d-a194-493f-ad25-e6ca9b9abb75", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": "2.uiCrgwCc32t6jIaUcMiinw==|JJVfmpcdrekNqJLfJOVaGw==|1zpwpqlATK+6/av/6JfOoHJaOgtpNJA6LDqEqsR2C/A=", - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.6WVjMRz5qtfVkGJ40Ne+Fw==|LtPQSeBvHIEgmzTtpdq4lw==|BV/F2ZhCD1nsr/4RoETwpMnu8PPVYirxrDQXcF6gpg4=" - }, - "name": "2.kOK8qkac+p+c8mNjhkuO/w==|nP1hQA1/8rJt97NmWSarfchRF+XWAUflsYzq9X2lBPU=|J7AmiEiDRCWvlLjYBrwXxCgCLw4EQiXmvlKnJw0mTb8=", - "notes": null, - "object": "cipherDetails", - "organizationId": "81cc1652-dc80-472d-909f-9539d057068b", - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:15:49.887811Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }, - { - "attachments": null, - "card": null, - "collectionIds": ["15e18629-849f-4629-895b-54600c542a70"], - "creationDate": "2024-09-22T11:14:53.442012Z", - "data": { - "autofillOnPageLoad": null, - "fields": [], - "name": "2.sOEzwZwic+bzHlaUpnl43Q==|Hr5DUOPmBJiz1oT8o2uJNLKFhY8rcmsx8EGqxuoJC9tNBCv6WwJOotrr2bDoPPP/|ZgcnsODyuV2Zd+Nl7MGoAPj383d/fr8LCEIvidYFJYk=", - "notes": null, - "password": "2.Nw6WShTt6PTNzRvnLYp2oQ==|x2mPKtOtqPpJEbCPH4EBBw==|Ij7Gq+CCXpJgoZISsATzsZb7v7paSj8mryWKyU0t/VY=", - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.K7I2dQ8x82rPK2buV1dzUQ==|VdjhkLm2wlURH03+GnLTFw==|AtpKj+TYgu+/YSqPn2jkFzePKvz71JtCgn+w0MXuhoI=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [], - "folderId": null, - "id": "adaef652-16e0-439a-9d67-07671ddc2a51", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": "2.Nw6WShTt6PTNzRvnLYp2oQ==|x2mPKtOtqPpJEbCPH4EBBw==|Ij7Gq+CCXpJgoZISsATzsZb7v7paSj8mryWKyU0t/VY=", - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.K7I2dQ8x82rPK2buV1dzUQ==|VdjhkLm2wlURH03+GnLTFw==|AtpKj+TYgu+/YSqPn2jkFzePKvz71JtCgn+w0MXuhoI=" - }, - "name": "2.sOEzwZwic+bzHlaUpnl43Q==|Hr5DUOPmBJiz1oT8o2uJNLKFhY8rcmsx8EGqxuoJC9tNBCv6WwJOotrr2bDoPPP/|ZgcnsODyuV2Zd+Nl7MGoAPj383d/fr8LCEIvidYFJYk=", - "notes": null, - "object": "cipherDetails", - "organizationId": "81cc1652-dc80-472d-909f-9539d057068b", - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:14:53.443032Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }, - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-09-26T14:26:27.436093Z", - "data": { - "autofillOnPageLoad": null, - "fields": [ - { - "linkedId": null, - "name": null, - "type": 2, - "value": "2.5ndrC0WqMJO6fH/2xv3AMw==|zY1/7UgW/MQUutZBixlyOA==|M4/tHU/s5w6ZygyXVUxpiEtAlFtoa9PlL5DY+S8K6gY=" - } - ], - "name": "2.4lqddV7PV1Uxn0qFk0JQLA==|svoCTgXohcpPJZirBg1PcQ==|AFIutATBeBvoGpfvDMqaDGlQXBFvIBKTyZqJNt+UPnE=", - "notes": null, - "password": null, - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.DkVdwPK5E5RAn6BLwzHXIg==|484sbAo5PFn6D50K9AToYw==|wjCnCnR+JunkRnoRjC/jwcJizdHCuzJ2RRp1z2uuJBg=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [ - { - "linkedId": null, - "name": null, - "type": 2, - "value": "2.5ndrC0WqMJO6fH/2xv3AMw==|zY1/7UgW/MQUutZBixlyOA==|M4/tHU/s5w6ZygyXVUxpiEtAlFtoa9PlL5DY+S8K6gY=" - } - ], - "folderId": "3df04ed6-624d-45ae-b825-7ceb0cf6eb0e", - "id": "b4b2d9ad-1d86-41d7-a1f3-a249e9f96e8e", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": null, - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.DkVdwPK5E5RAn6BLwzHXIg==|484sbAo5PFn6D50K9AToYw==|wjCnCnR+JunkRnoRjC/jwcJizdHCuzJ2RRp1z2uuJBg=" - }, - "name": "2.4lqddV7PV1Uxn0qFk0JQLA==|svoCTgXohcpPJZirBg1PcQ==|AFIutATBeBvoGpfvDMqaDGlQXBFvIBKTyZqJNt+UPnE=", - "notes": null, - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-26T14:26:27.436534Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }, - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-09-22T11:14:14.671495Z", - "data": { - "autofillOnPageLoad": null, - "fields": [], - "name": "2.aavpFIxp7xouEaflFBr0ug==|JEyMdNkR/1TaJ5lU5w8FfR4+yfV+JP+XsJd8np7/gY4=|BaHDWGBVNTdd5KsR2VLPrHA0caVgxszWFEwgmtR5iHI=", - "notes": null, - "password": "2.qjgHReWyJ0X9KlP3qFtB8w==|cHxcCMM2OTTdI3mt85KveQ==|/EuUwk9AzkUQqsJzJ3Z2MEvM4tQ9Ma8WDoUAXtNLE4E=", - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.K69oGBEuH9GzhSkzi2zzIg==|bbeKWbkuSc1cVJm2xDae8Q==|y+Z07fAT+zmlq2gSLFC6uLEfYIq3IT7HqNFJqlWQOPM=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [], - "folderId": "e7098f5d-4d00-4bdf-8c66-56f9dca2129f", - "id": "b7441ea3-baf4-4f04-a445-0ad342eb56c4", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": "2.qjgHReWyJ0X9KlP3qFtB8w==|cHxcCMM2OTTdI3mt85KveQ==|/EuUwk9AzkUQqsJzJ3Z2MEvM4tQ9Ma8WDoUAXtNLE4E=", - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": "2.K69oGBEuH9GzhSkzi2zzIg==|bbeKWbkuSc1cVJm2xDae8Q==|y+Z07fAT+zmlq2gSLFC6uLEfYIq3IT7HqNFJqlWQOPM=" - }, - "name": "2.aavpFIxp7xouEaflFBr0ug==|JEyMdNkR/1TaJ5lU5w8FfR4+yfV+JP+XsJd8np7/gY4=|BaHDWGBVNTdd5KsR2VLPrHA0caVgxszWFEwgmtR5iHI=", - "notes": null, - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:14:14.672096Z", - "secureNote": null, - "type": 1, - "viewPassword": true - } - ], - "collections": [ - { - "externalId": null, - "hidePasswords": false, - "id": "15e18629-849f-4629-895b-54600c542a70", - "name": "2.X7RK7wBZl+1pqo4yvAontQ==|Q+RD7xRWtXPC/Ijbl+863VSyQ4oYmHGG5EzNDtNYWW0=|369crUvCUpo5bID5wu0Q60eQJJv5+eJLxbsuZKmtVYA=", - "object": "collectionDetails", - "organizationId": "81cc1652-dc80-472d-909f-9539d057068b", - "readOnly": false - }, - { - "externalId": null, - "hidePasswords": false, - "id": "8d1a5611-5fd6-4728-a6f8-22bc03b50640", - "name": "2.4KNb9dUNUqfe2iqFZxBZJQ==|lrcBRuOjIpMAiBMHYDNbpn6ZmUz/OzHuBTr68ta0a/I=|OtEMhyhekHnARLATP8IWKAWieTaNQpbgO7/syW1KLK4=", - "object": "collectionDetails", - "organizationId": "81cc1652-dc80-472d-909f-9539d057068b", - "readOnly": false - } - ], - "domains": null, - "folders": [ - { - "id": "e7098f5d-4d00-4bdf-8c66-56f9dca2129f", - "name": "2.FTcL7PAe36ZQh0zIXPotSg==|ALhJRf/j9Wa83jg/tWbFSndiZ9JvZs2BwmVXmCUWhKc=|AEpDm/0LhllnW/Qzx9oWNYuSMaLQuR62MFUQuAaqQvc=", - "object": "folder", - "revisionDate": "2024-09-22T11:13:55.612053Z" - }, - { - "id": "3df04ed6-624d-45ae-b825-7ceb0cf6eb0e", - "name": "2.cybmeku3f53n3//scS4HfQ==|QEOsVN2jUF3+11/a8iISuQ==|PV2zCoVqNCX9KzyIUassEOjZE/f6bF+Y6Ft1ypRJ9lw=", - "object": "folder", - "revisionDate": "2024-09-22T17:00:11.566430Z" - } - ], - "object": "sync", - "policies": [], - "profile": { - "_status": 0, - "avatarColor": null, - "culture": "en-US", - "email": "test@laverse.net", - "emailVerified": true, - "forcePasswordReset": false, - "id": "e8dababd-242e-4900-becf-e88bc021dda8", - "key": "2.lkAJiJtCKPHFPrZ96+j2Xg==|5XJtrKUndcGy28thFukrmgMcLp+BOVdkF+KcuOnfshq9AN1PFhna9Es96CVARCnjTcWuHuqvgnGmcOHTrf8fyfLv63VBsjLgLZk8rCXJoKE=|9dwgx4/13AD+elE2vE7vlSQoe8LbCGGlui345YrKvXY=", - "masterPasswordHint": null, - "name": "Test Laverse", - "object": "profile", - "organizations": [ - { - "accessSecretsManager": false, - "allowAdminAccessToAllCollectionItems": true, - "enabled": true, - "familySponsorshipAvailable": false, - "familySponsorshipFriendlyName": null, - "familySponsorshipLastSyncDate": null, - "familySponsorshipToDelete": null, - "familySponsorshipValidUntil": null, - "flexibleCollections": false, - "hasPublicAndPrivateKeys": true, - "id": "81cc1652-dc80-472d-909f-9539d057068b", - "identifier": null, - "key": "4.JW3mktbL7vpTVRweZdQBAirJuAEhSRn37zcXZjDjI47weFKkeZkvPxZWCqFYC/P5qCJwEYMbv7lTETkWDg6paevVfhJ35buGcTQdEbQxAJebzPahEcUstj11l4Y9T5RaDiAJR8+drrGJ3fKV3v3hymKz2o9fUfK1epuLFll2nnWSOjCcuRe/+zz5VwIVx4WJAPJHmiS6eofbj/DTIQCzG4JkR0UzT66ouLcgmPL1nGOqVI7KxRpL5yVj75UkjniHkWAcB7lfAxWXw2GhDJ/2L685uA3820ItTbxjCwLQOvjBttgrbURmkeP9BD+KkO4V6vb8bbTWNSvggXKk2h1CMw==", - "keyConnectorEnabled": false, - "keyConnectorUrl": null, - "limitCollectionCreationDeletion": true, - "maxAutoscaleSeats": null, - "maxCollections": null, - "maxStorageGb": 32767, - "name": "My Test Organization", - "object": "profileOrganization", - "organizationUserId": "9e755d16-b500-48ac-b24c-4105b7d08796", - "permissions": { - "accessEventLogs": false, - "accessImportExport": false, - "accessReports": false, - "createNewCollections": false, - "deleteAnyCollection": false, - "deleteAssignedCollections": false, - "editAnyCollection": false, - "editAssignedCollections": false, - "manageGroups": false, - "managePolicies": false, - "manageResetPassword": false, - "manageScim": false, - "manageSso": false, - "manageUsers": false - }, - "planProductType": 3, - "productTierType": 3, - "providerId": null, - "providerName": null, - "providerType": null, - "resetPasswordEnrolled": false, - "seats": null, - "selfHost": true, - "ssoBound": false, - "status": 2, - "type": 0, - "use2fa": true, - "useActivateAutofillPolicy": false, - "useApi": true, - "useCustomPermissions": false, - "useDirectory": false, - "useEvents": false, - "useGroups": false, - "useKeyConnector": false, - "usePasswordManager": true, - "usePolicies": true, - "useResetPassword": false, - "useScim": false, - "useSecretsManager": false, - "useSso": false, - "useTotp": true, - "userId": "e8dababd-242e-4900-becf-e88bc021dda8", - "usersGetPremium": true - } - ], - "premium": true, - "premiumFromOrganization": false, - "privateKey": "2.D2aLa8ne/DAkeSzctQISVw==|/xoGM5i5JGJTH/vohUuwTFrTx3hd/gt3kBD/FQdeLMtYjl1u96sh0ECmoERqGHeSfXj+iAb9kpTIOKG8LwmkZGUJBI90Mw0M7ODmf7E8eQ+aGF+bGqTSMQ1wtpunEyFVodlg92YN8Ddlb2V9J4uN8ykpHYNDmQiYLZ8bl6vCODRGPyzLvx5M8DbITVL5PhsjKDLLrVV8lFCgCcAL5YLfkghYhFELyX15zXA/KYEnwggDka3hG5+HHFOVZSeyk7Gi6M4TX2wADbTXz1/Wsho8oxFUrtNiOB3ZiY2cx9UWttpzMXoGfi2gJcP1db/nTfWenOLlzw6Od4VyRzsXsfyGwbqBqDnNFkjLvhjVw4JO+psF//xAMDs14101Tf2wFkB6toQ+zdnDphXUeKmiVPQ7gMnQlOWN5tWvjjmYOO4Y63sGpP24cDOdEScIdebZRSA8uOhTzadfKfOiH5zVYZzXs33FQ0li4nBrsj5xYa6PP4D1P7gqjxClPdguwkdLoZ7JvgIlyRIwEcORi5Ich8RWF/kqRBwk0QSzK1mTlHHU5xtSgi4MLNVx4qTYNaJVBtwL9d2MD9LeNn4Z2PL4A7qnszHqsERiQQDxNEgMxMBHDgSXqQbtQxRvsI6oY+yNbN7uVWw4o8AC3f5GBdxzIqcN1mgEM5ix5aDt15w3MhP2FHtf2neKI68TnL8WnT1fT8BVlbECIiUqK0tfq5aTjdSh3gCS15jvZ1H60h+K8+O/nDfquzVjY7UsTGwA+UtS8/JGiaUhc0VhxJo8P1V2VSCiu51d5q3De1vDg5R2VEgBmTchZyTIodC+3+7ACTOwkNCCdIJN7xKOcIGFA7QOuyJtBeXT4Rd9UGMHSL054IB/315WVDiwrP9W1aP0nHzFs+qAXbH5o1E+AmfMDyoHopjGgbUw22r837kHzf5Qe8QhRYPzQvDowfCPhdoy23cbN1VsNavNwTC9hcG5oYMwkK66xP3MEM9UfGD22pwxe7M8U4BRdLCCHbi95eklXE6Mg6DpWsAdMgokQbOvnlwgKfrlbltqXUE/vUQI8TB3AE1Nkt0ST4quTriMuuyiHdeeZV4UkV9jWt/5bTCfdrCYuGZP7g4shbfNcP7u1Zrdxv+EuUwGIOOTrNV5awmBnL3iHE5ya2MnqmRyfWiPIT5majZCk06yxj4XzyIPOpjYKFt0MOgLvG1GllmdtRqg7tMVvc5ZFo5KWIxLsIJD12UjA1GYYoFdX4+wsNbPjfnlE6D2PrtWUICnBFJzYpfyrKTe01k8G8hyyz+tVzBRfz8EA2ew1+hlVcAgSPCcBzhDgqPe+RSPi7ZSd66be1gDhGAftWFM8Z0MrMklXi2DyjjaKBNsZZD8qTcLcobm8nqHUQtnr5JCbmgP3rau8NY/fxeFHsvSiZQoB1aI/y+Sz/R4r+T9cg8hjmS/FUHDO+m6a6nuWNFwz8wIluM557oOTl+A9UGFF50Gpzmf97VdQjM3ZREazQ7la6AobzS3BHI6FNdxN9LTyMpYo+WODv52/VwU3ODH7wf5bz2OHZhk2NG5R7pSH7qg8jM+/MtJkFumENV0qMecozIkP6e4CyI9ua4YwI9n7G5OgKYMG1aj2PRSny2JSLS8aHF1TkRL8SD0nZFCox0=|muEtiwIuZxhuuLv0nouEdxHU2CO+I7JXKZuYHWiv/OE=", - "providerOrganizations": [], - "providers": [], - "securityStamp": "4033cf35-bc5d-4ecd-951c-dbe549f27740", - "twoFactorEnabled": false, - "usesKeyConnector": false - }, - "sends": [], - "unofficialServer": true -} -`)) - - httpmock.RegisterResponder("GET", `http://127.0.0.1:8081/api/accounts/profile`, - httpmock.NewStringResponder(200, `{"_status":0,"avatarColor":null,"culture":"en-US","email":"test@laverse.net","emailVerified":true,"forcePasswordReset":false,"id":"e8dababd-242e-4900-becf-e88bc021dda8","key":"2.lkAJiJtCKPHFPrZ96+j2Xg==|5XJtrKUndcGy28thFukrmgMcLp+BOVdkF+KcuOnfshq9AN1PFhna9Es96CVARCnjTcWuHuqvgnGmcOHTrf8fyfLv63VBsjLgLZk8rCXJoKE=|9dwgx4/13AD+elE2vE7vlSQoe8LbCGGlui345YrKvXY=","masterPasswordHint":null,"name":"Test Laverse","object":"profile","organizations":[{"accessSecretsManager":false,"allowAdminAccessToAllCollectionItems":true,"enabled":true,"familySponsorshipAvailable":false,"familySponsorshipFriendlyName":null,"familySponsorshipLastSyncDate":null,"familySponsorshipToDelete":null,"familySponsorshipValidUntil":null,"flexibleCollections":false,"hasPublicAndPrivateKeys":true,"id":"81cc1652-dc80-472d-909f-9539d057068b","identifier":null,"key":"4.JW3mktbL7vpTVRweZdQBAirJuAEhSRn37zcXZjDjI47weFKkeZkvPxZWCqFYC/P5qCJwEYMbv7lTETkWDg6paevVfhJ35buGcTQdEbQxAJebzPahEcUstj11l4Y9T5RaDiAJR8+drrGJ3fKV3v3hymKz2o9fUfK1epuLFll2nnWSOjCcuRe/+zz5VwIVx4WJAPJHmiS6eofbj/DTIQCzG4JkR0UzT66ouLcgmPL1nGOqVI7KxRpL5yVj75UkjniHkWAcB7lfAxWXw2GhDJ/2L685uA3820ItTbxjCwLQOvjBttgrbURmkeP9BD+KkO4V6vb8bbTWNSvggXKk2h1CMw==","keyConnectorEnabled":false,"keyConnectorUrl":null,"limitCollectionCreationDeletion":true,"maxAutoscaleSeats":null,"maxCollections":null,"maxStorageGb":32767,"name":"My Test Organization","object":"profileOrganization","organizationUserId":"9e755d16-b500-48ac-b24c-4105b7d08796","permissions":{"accessEventLogs":false,"accessImportExport":false,"accessReports":false,"createNewCollections":false,"deleteAnyCollection":false,"deleteAssignedCollections":false,"editAnyCollection":false,"editAssignedCollections":false,"manageGroups":false,"managePolicies":false,"manageResetPassword":false,"manageScim":false,"manageSso":false,"manageUsers":false},"planProductType":3,"productTierType":3,"providerId":null,"providerName":null,"providerType":null,"resetPasswordEnrolled":false,"seats":null,"selfHost":true,"ssoBound":false,"status":2,"type":0,"use2fa":true,"useActivateAutofillPolicy":false,"useApi":true,"useCustomPermissions":false,"useDirectory":false,"useEvents":false,"useGroups":false,"useKeyConnector":false,"usePasswordManager":true,"usePolicies":true,"useResetPassword":false,"useScim":false,"useSecretsManager":false,"useSso":false,"useTotp":true,"userId":"e8dababd-242e-4900-becf-e88bc021dda8","usersGetPremium":true}],"premium":true,"premiumFromOrganization":false,"privateKey":"2.D2aLa8ne/DAkeSzctQISVw==|/xoGM5i5JGJTH/vohUuwTFrTx3hd/gt3kBD/FQdeLMtYjl1u96sh0ECmoERqGHeSfXj+iAb9kpTIOKG8LwmkZGUJBI90Mw0M7ODmf7E8eQ+aGF+bGqTSMQ1wtpunEyFVodlg92YN8Ddlb2V9J4uN8ykpHYNDmQiYLZ8bl6vCODRGPyzLvx5M8DbITVL5PhsjKDLLrVV8lFCgCcAL5YLfkghYhFELyX15zXA/KYEnwggDka3hG5+HHFOVZSeyk7Gi6M4TX2wADbTXz1/Wsho8oxFUrtNiOB3ZiY2cx9UWttpzMXoGfi2gJcP1db/nTfWenOLlzw6Od4VyRzsXsfyGwbqBqDnNFkjLvhjVw4JO+psF//xAMDs14101Tf2wFkB6toQ+zdnDphXUeKmiVPQ7gMnQlOWN5tWvjjmYOO4Y63sGpP24cDOdEScIdebZRSA8uOhTzadfKfOiH5zVYZzXs33FQ0li4nBrsj5xYa6PP4D1P7gqjxClPdguwkdLoZ7JvgIlyRIwEcORi5Ich8RWF/kqRBwk0QSzK1mTlHHU5xtSgi4MLNVx4qTYNaJVBtwL9d2MD9LeNn4Z2PL4A7qnszHqsERiQQDxNEgMxMBHDgSXqQbtQxRvsI6oY+yNbN7uVWw4o8AC3f5GBdxzIqcN1mgEM5ix5aDt15w3MhP2FHtf2neKI68TnL8WnT1fT8BVlbECIiUqK0tfq5aTjdSh3gCS15jvZ1H60h+K8+O/nDfquzVjY7UsTGwA+UtS8/JGiaUhc0VhxJo8P1V2VSCiu51d5q3De1vDg5R2VEgBmTchZyTIodC+3+7ACTOwkNCCdIJN7xKOcIGFA7QOuyJtBeXT4Rd9UGMHSL054IB/315WVDiwrP9W1aP0nHzFs+qAXbH5o1E+AmfMDyoHopjGgbUw22r837kHzf5Qe8QhRYPzQvDowfCPhdoy23cbN1VsNavNwTC9hcG5oYMwkK66xP3MEM9UfGD22pwxe7M8U4BRdLCCHbi95eklXE6Mg6DpWsAdMgokQbOvnlwgKfrlbltqXUE/vUQI8TB3AE1Nkt0ST4quTriMuuyiHdeeZV4UkV9jWt/5bTCfdrCYuGZP7g4shbfNcP7u1Zrdxv+EuUwGIOOTrNV5awmBnL3iHE5ya2MnqmRyfWiPIT5majZCk06yxj4XzyIPOpjYKFt0MOgLvG1GllmdtRqg7tMVvc5ZFo5KWIxLsIJD12UjA1GYYoFdX4+wsNbPjfnlE6D2PrtWUICnBFJzYpfyrKTe01k8G8hyyz+tVzBRfz8EA2ew1+hlVcAgSPCcBzhDgqPe+RSPi7ZSd66be1gDhGAftWFM8Z0MrMklXi2DyjjaKBNsZZD8qTcLcobm8nqHUQtnr5JCbmgP3rau8NY/fxeFHsvSiZQoB1aI/y+Sz/R4r+T9cg8hjmS/FUHDO+m6a6nuWNFwz8wIluM557oOTl+A9UGFF50Gpzmf97VdQjM3ZREazQ7la6AobzS3BHI6FNdxN9LTyMpYo+WODv52/VwU3ODH7wf5bz2OHZhk2NG5R7pSH7qg8jM+/MtJkFumENV0qMecozIkP6e4CyI9ua4YwI9n7G5OgKYMG1aj2PRSny2JSLS8aHF1TkRL8SD0nZFCox0=|muEtiwIuZxhuuLv0nouEdxHU2CO+I7JXKZuYHWiv/OE=","providerOrganizations":[],"providers":[],"securityStamp":"4033cf35-bc5d-4ecd-951c-dbe549f27740","twoFactorEnabled":false,"usesKeyConnector":false}`)) - - // We're changing the revisionDate on purpose in the response to mimick Bitwarden official server's behavior - httpmock.RegisterResponder("POST", `http://127.0.0.1:8081/api/ciphers`, - httpmock.NewStringResponder(200, ` - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-09-22T11:13:40.346903Z", - "data": { - "autofillOnPageLoad": null, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "password": null, - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "folderId": null, - "id": "24d1c150-5dfd-4008-964c-01317d1f6b23", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": null, - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:13:40.345356Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }`)) - - return webapi.NewClient("http://127.0.0.1:8081/", webapi.WithCustomClient(client), webapi.DisableRetries()) -} - -func mockedClientArgon2() webapi.Client { - client := http.Client{Transport: httpmock.DefaultTransport} - httpmock.RegisterResponder("POST", "http://127.0.0.1:8081/identity/accounts/prelogin", - httpmock.NewStringResponder(200, `{"kdf":1,"kdfIterations":3,"kdfMemory":64,"kdfParallelism":4}`)) - - // Regexp match (could use httpmock.RegisterRegexpResponder instead) - httpmock.RegisterResponder("POST", `http://127.0.0.1:8081/identity/connect/token`, - httpmock.NewStringResponder(200, `{"ForcePasswordReset":false,"Kdf":1,"KdfIterations":3,"KdfMemory":64,"KdfParallelism":4,"Key":"2.VBpAJrIHYLv60UTYy5e7sA==|WWsozKnKPVvBYttXtlAzpmZPoffwlY3+8Wup9SBdGcO8T4Ybj808DubDhICTPMz9RliDSJ1OuaivBC0rh/7EcWV1s9KuRth5J3XFWJqmtXU=|l1ly+Uek1j4k2xQNT8iJ++GdwMTWRaSBP5mFvgJ+CGU=","MasterPasswordPolicy":{"object":"masterPasswordPolicy"},"PrivateKey":"2.0Xc+uV+6YVa+Zkg74C/MJA==|xTbZGy2r8/kHcXXy23YDHWDTHjasUUoHiWJ84rGEhuPD27GTF8DrFL+lbERo3+OH7MXvseAFygKArvSumlCQnMhT/dswJMH8ZEMuxQUZ8I7kg/7eNqxRndxyC8alZh3VM4FC7TsuVBe6BF4pbPQYX4etFL8yOHLpIhwkKcG7+IfQHQHwOXpsSiGpADQlk5er990snhAXwGpgROqoveO9klpNJXuEzJKMFMdoo9FCaRsJ4bB3BE/Y+8Ph7ek8mGyoUUqNFp8Z/T+XN+9kvxDFnVFtYp1p+sU8LpCSvaq3dAImQt6X7vAgfjbWVkTxB0HlBdMkjpg8BAK7qpscT5oH83SZqdNPRi9kkT9Y30xl0QvvJzXLcjqOS6je+i3vB1r4O8X3ZIj+th4cfZOfHKpzDLbGyAezxiiWwQ4xt0USQ9rLv+BU5YNDKnibmsIooKHuh8wV0qht8vr2CEVavXOmmBi/6bGIWJMOs2K52be5LJkYL+653dsKXBN4uahQDMdfs9vPUA7OoIFR9BZvQiGMDstFYVgJUulOkj2J4nieuTAmurQe6nS6U4v1swI7DIzdo8ZCJcAQfWYWk8IBwh6gQxSuPMg7+O2dntbPFkMP2KhoisUucoXNIDXmxwYAMeP01KMNSgFc6hL6WnLzyVcRlSLy7OC9qwTD6ZH6XA4D/MO9MINTTzw4+/pZvwTeuXMqB0HkcjTpWzTUi405uV6qh8CxYOaNEl6kNAMiuVNASToqYb/EBC0uGOybOzcNZOCiXmuiPVOstiz65KP1d3Dfl9al48hpxnDxFyFub5NDx8xADA3SzOlI9xMCsC/mcY0/fRlwoTDFCLzfdtPIdSn5N8/YySY10e/TXftKGV7bLvzGAlOntwoiWaLJbyHAnEXNUVFxJu5XVaVccXcxIKete42S291dCu4yk35KsIQU0jBaPB/hGXLJvvySl9/kARl0zIXJH+Pk0hlk+/IRH9HNZrru93WTgW9KjEeT2vaZ6UqULkkspIfoUrFxQfSyAxycDaqa4EHt1QJBKyC9+aWEOXNwtxkJTnhtvlqRPOGUpdkAyC5ebfdX2URZnd/2TR/PTviWaDKe/g51UWr8QepgwbJjkBeuZMSPCNHkcLdmwEZERisbZ7H50hDQhhK+qfmMOvkVrRRXKT2ICbQzchm5rDasdtMed7vIf3beS0ESIR8kZ1WmteI9dvWmagnXRlfsUZW0y0KWe9Ma/ISOa6QPb0Cc7T8LUg2lpREQpRTt119RX9Xugd2uZ+UzbGpqn9u5JY2+vddwv+zFL0g/Vu9h3kd02v+WTXeV8wLDJYkoc6XeTBzC0uQtNJt4oN7hWcMBrkYmnXxslIjGw/nE7eBnG02XWTCeTjADqXtz2j4xMFmzJod+4j4f6MQZBII9Sz5A2FfSbadUuukEYcFvkqLnjG/sMzcBQMIDP6vmy7VRnETahlNi7Pt+gRLHuhGN1BbScolW7a0YnWlI1T0MtKb4DBsjX9GfotxkG+ORg/i45YnG6KPQ6+jgXU3Xtf0tgjTqHVgc7TOCm9R2b4G24RSQXx3WaMP1slbSYsf/YmXIqdg/dVaCFrJdA1v2bDFymuPbA0P4Ey8c4ylInXGgK4yxS7nVC4qbbVtK5bWT3SRaBWw=|0r9TcWfl93tZln8+ZGrPwZTHBbrLiSuVXvoI+cQeSr0=","ResetMasterPassword":false,"UserDecryptionOptions":{"HasMasterPassword":true,"Object":"userDecryptionOptions"},"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4MDcxNDUsImV4cCI6MTcyNzgxNDM0NSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6ImM2NGExZjhkLTIyM2MtNDBmZC1hZGRlLWE5MGQ1OGRiYzI2YyIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LTIwMjM0MSIsImVtYWlsIjoidGVzdC0yMDIzNDEtYXJnb24yQGxhdmVyc2UubmV0IiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInNzdGFtcCI6IjZjYmY3Y2QxLWQyYTItNGM1YS05N2Q3LTkxMDQyMjg1YzQ5ZCIsImRldmljZSI6IiIsInNjb3BlIjpbImFwaSIsIm9mZmxpbmVfYWNjZXNzIl0sImFtciI6WyJBcHBsaWNhdGlvbiJdfQ.hJ5-aPuZFAovG_2q7im8xxO2GCjeHit7Hwhm-FKQsu-j7OJdY8F_2jSy7azPcrVasImboR99WvpydMYzbQLB3AlQ3OSPcqUUHJDlFqeDUIXzpi-NMb3CBkxyr8Q_fBojiWmRiwPY89oiOE6dXTvDxTEUIWpKv0xnd-iBBPwwx6vzfsSKKAIB1tbZM1Cy4aWgcbN0lC-cU-NGcIFI1UEVod9KzcuN65DouXfjB2d5NkAI-pic9pno42MF8strosezgWrbnvTk8h7CzT5BPj7ZCaqYVr_RKVciHAs3QwrFyFe_OZ4RoN_YikDApdbwQyIsJsIK_jNTraJzNMfo6bbZfA","expires_in":7200,"refresh_token":"JPxgcZSlj4KKfgZuyf8PnLF9KVXADYOYstA5hBreXGPwm7667dSeGPFtBYRWOyXRJxQryUr6BLEjXHBS_NqdIw==","scope":"api offline_access","token_type":"Bearer","unofficialServer":true}`)) - - httpmock.RegisterResponder("GET", `http://127.0.0.1:8081/api/sync?excludeDomains=true`, - httpmock.NewStringResponder(200, `{ - "ciphers": [ - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-10-01T18:25:26.092790Z", - "data": { - "autofillOnPageLoad": null, - "fields": [], - "name": "2.zD1jZaHjvJ0ZsD4OpfRHXg==|eekdaveWXtPM+Bo285ljIQ==|4pvvvQZzyX5HRCaY+jUrecLR0AlXx4oVf994NNTyHyE=", - "notes": null, - "password": null, - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": null - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [], - "folderId": null, - "id": "f01e68e9-3951-40ee-80ff-c4ff4517e159", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": null, - "passwordRevisionDate": null, - "totp": null, - "uri": null, - "uris": [], - "username": null - }, - "name": "2.zD1jZaHjvJ0ZsD4OpfRHXg==|eekdaveWXtPM+Bo285ljIQ==|4pvvvQZzyX5HRCaY+jUrecLR0AlXx4oVf994NNTyHyE=", - "notes": null, - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-10-01T18:25:26.093577Z", - "secureNote": null, - "type": 1, - "viewPassword": true - } - ], - "collections": [], - "domains": null, - "folders": [], - "object": "sync", - "policies": [], - "profile": { - "_status": 0, - "avatarColor": null, - "culture": "en-US", - "email": "test-202341-argon2@laverse.net", - "emailVerified": true, - "forcePasswordReset": false, - "id": "c64a1f8d-223c-40fd-adde-a90d58dbc26c", - "key": "2.VBpAJrIHYLv60UTYy5e7sA==|WWsozKnKPVvBYttXtlAzpmZPoffwlY3+8Wup9SBdGcO8T4Ybj808DubDhICTPMz9RliDSJ1OuaivBC0rh/7EcWV1s9KuRth5J3XFWJqmtXU=|l1ly+Uek1j4k2xQNT8iJ++GdwMTWRaSBP5mFvgJ+CGU=", - "masterPasswordHint": null, - "name": "test-202341", - "object": "profile", - "organizations": [], - "premium": true, - "premiumFromOrganization": false, - "privateKey": "2.0Xc+uV+6YVa+Zkg74C/MJA==|xTbZGy2r8/kHcXXy23YDHWDTHjasUUoHiWJ84rGEhuPD27GTF8DrFL+lbERo3+OH7MXvseAFygKArvSumlCQnMhT/dswJMH8ZEMuxQUZ8I7kg/7eNqxRndxyC8alZh3VM4FC7TsuVBe6BF4pbPQYX4etFL8yOHLpIhwkKcG7+IfQHQHwOXpsSiGpADQlk5er990snhAXwGpgROqoveO9klpNJXuEzJKMFMdoo9FCaRsJ4bB3BE/Y+8Ph7ek8mGyoUUqNFp8Z/T+XN+9kvxDFnVFtYp1p+sU8LpCSvaq3dAImQt6X7vAgfjbWVkTxB0HlBdMkjpg8BAK7qpscT5oH83SZqdNPRi9kkT9Y30xl0QvvJzXLcjqOS6je+i3vB1r4O8X3ZIj+th4cfZOfHKpzDLbGyAezxiiWwQ4xt0USQ9rLv+BU5YNDKnibmsIooKHuh8wV0qht8vr2CEVavXOmmBi/6bGIWJMOs2K52be5LJkYL+653dsKXBN4uahQDMdfs9vPUA7OoIFR9BZvQiGMDstFYVgJUulOkj2J4nieuTAmurQe6nS6U4v1swI7DIzdo8ZCJcAQfWYWk8IBwh6gQxSuPMg7+O2dntbPFkMP2KhoisUucoXNIDXmxwYAMeP01KMNSgFc6hL6WnLzyVcRlSLy7OC9qwTD6ZH6XA4D/MO9MINTTzw4+/pZvwTeuXMqB0HkcjTpWzTUi405uV6qh8CxYOaNEl6kNAMiuVNASToqYb/EBC0uGOybOzcNZOCiXmuiPVOstiz65KP1d3Dfl9al48hpxnDxFyFub5NDx8xADA3SzOlI9xMCsC/mcY0/fRlwoTDFCLzfdtPIdSn5N8/YySY10e/TXftKGV7bLvzGAlOntwoiWaLJbyHAnEXNUVFxJu5XVaVccXcxIKete42S291dCu4yk35KsIQU0jBaPB/hGXLJvvySl9/kARl0zIXJH+Pk0hlk+/IRH9HNZrru93WTgW9KjEeT2vaZ6UqULkkspIfoUrFxQfSyAxycDaqa4EHt1QJBKyC9+aWEOXNwtxkJTnhtvlqRPOGUpdkAyC5ebfdX2URZnd/2TR/PTviWaDKe/g51UWr8QepgwbJjkBeuZMSPCNHkcLdmwEZERisbZ7H50hDQhhK+qfmMOvkVrRRXKT2ICbQzchm5rDasdtMed7vIf3beS0ESIR8kZ1WmteI9dvWmagnXRlfsUZW0y0KWe9Ma/ISOa6QPb0Cc7T8LUg2lpREQpRTt119RX9Xugd2uZ+UzbGpqn9u5JY2+vddwv+zFL0g/Vu9h3kd02v+WTXeV8wLDJYkoc6XeTBzC0uQtNJt4oN7hWcMBrkYmnXxslIjGw/nE7eBnG02XWTCeTjADqXtz2j4xMFmzJod+4j4f6MQZBII9Sz5A2FfSbadUuukEYcFvkqLnjG/sMzcBQMIDP6vmy7VRnETahlNi7Pt+gRLHuhGN1BbScolW7a0YnWlI1T0MtKb4DBsjX9GfotxkG+ORg/i45YnG6KPQ6+jgXU3Xtf0tgjTqHVgc7TOCm9R2b4G24RSQXx3WaMP1slbSYsf/YmXIqdg/dVaCFrJdA1v2bDFymuPbA0P4Ey8c4ylInXGgK4yxS7nVC4qbbVtK5bWT3SRaBWw=|0r9TcWfl93tZln8+ZGrPwZTHBbrLiSuVXvoI+cQeSr0=", - "providerOrganizations": [], - "providers": [], - "securityStamp": "6cbf7cd1-d2a2-4c5a-97d7-91042285c49d", - "twoFactorEnabled": false, - "usesKeyConnector": false - }, - "sends": [], - "unofficialServer": true -} -`)) - - httpmock.RegisterResponder("GET", `http://127.0.0.1:8081/api/accounts/profile`, - httpmock.NewStringResponder(200, `{"_status":0,"avatarColor":null,"culture":"en-US","email":"test-202341-argon2@laverse.net","emailVerified":true,"forcePasswordReset":false,"id":"c64a1f8d-223c-40fd-adde-a90d58dbc26c","key":"2.VBpAJrIHYLv60UTYy5e7sA==|WWsozKnKPVvBYttXtlAzpmZPoffwlY3+8Wup9SBdGcO8T4Ybj808DubDhICTPMz9RliDSJ1OuaivBC0rh/7EcWV1s9KuRth5J3XFWJqmtXU=|l1ly+Uek1j4k2xQNT8iJ++GdwMTWRaSBP5mFvgJ+CGU=","masterPasswordHint":null,"name":"test-202341","object":"profile","organizations":[],"premium":true,"premiumFromOrganization":false,"privateKey":"2.0Xc+uV+6YVa+Zkg74C/MJA==|xTbZGy2r8/kHcXXy23YDHWDTHjasUUoHiWJ84rGEhuPD27GTF8DrFL+lbERo3+OH7MXvseAFygKArvSumlCQnMhT/dswJMH8ZEMuxQUZ8I7kg/7eNqxRndxyC8alZh3VM4FC7TsuVBe6BF4pbPQYX4etFL8yOHLpIhwkKcG7+IfQHQHwOXpsSiGpADQlk5er990snhAXwGpgROqoveO9klpNJXuEzJKMFMdoo9FCaRsJ4bB3BE/Y+8Ph7ek8mGyoUUqNFp8Z/T+XN+9kvxDFnVFtYp1p+sU8LpCSvaq3dAImQt6X7vAgfjbWVkTxB0HlBdMkjpg8BAK7qpscT5oH83SZqdNPRi9kkT9Y30xl0QvvJzXLcjqOS6je+i3vB1r4O8X3ZIj+th4cfZOfHKpzDLbGyAezxiiWwQ4xt0USQ9rLv+BU5YNDKnibmsIooKHuh8wV0qht8vr2CEVavXOmmBi/6bGIWJMOs2K52be5LJkYL+653dsKXBN4uahQDMdfs9vPUA7OoIFR9BZvQiGMDstFYVgJUulOkj2J4nieuTAmurQe6nS6U4v1swI7DIzdo8ZCJcAQfWYWk8IBwh6gQxSuPMg7+O2dntbPFkMP2KhoisUucoXNIDXmxwYAMeP01KMNSgFc6hL6WnLzyVcRlSLy7OC9qwTD6ZH6XA4D/MO9MINTTzw4+/pZvwTeuXMqB0HkcjTpWzTUi405uV6qh8CxYOaNEl6kNAMiuVNASToqYb/EBC0uGOybOzcNZOCiXmuiPVOstiz65KP1d3Dfl9al48hpxnDxFyFub5NDx8xADA3SzOlI9xMCsC/mcY0/fRlwoTDFCLzfdtPIdSn5N8/YySY10e/TXftKGV7bLvzGAlOntwoiWaLJbyHAnEXNUVFxJu5XVaVccXcxIKete42S291dCu4yk35KsIQU0jBaPB/hGXLJvvySl9/kARl0zIXJH+Pk0hlk+/IRH9HNZrru93WTgW9KjEeT2vaZ6UqULkkspIfoUrFxQfSyAxycDaqa4EHt1QJBKyC9+aWEOXNwtxkJTnhtvlqRPOGUpdkAyC5ebfdX2URZnd/2TR/PTviWaDKe/g51UWr8QepgwbJjkBeuZMSPCNHkcLdmwEZERisbZ7H50hDQhhK+qfmMOvkVrRRXKT2ICbQzchm5rDasdtMed7vIf3beS0ESIR8kZ1WmteI9dvWmagnXRlfsUZW0y0KWe9Ma/ISOa6QPb0Cc7T8LUg2lpREQpRTt119RX9Xugd2uZ+UzbGpqn9u5JY2+vddwv+zFL0g/Vu9h3kd02v+WTXeV8wLDJYkoc6XeTBzC0uQtNJt4oN7hWcMBrkYmnXxslIjGw/nE7eBnG02XWTCeTjADqXtz2j4xMFmzJod+4j4f6MQZBII9Sz5A2FfSbadUuukEYcFvkqLnjG/sMzcBQMIDP6vmy7VRnETahlNi7Pt+gRLHuhGN1BbScolW7a0YnWlI1T0MtKb4DBsjX9GfotxkG+ORg/i45YnG6KPQ6+jgXU3Xtf0tgjTqHVgc7TOCm9R2b4G24RSQXx3WaMP1slbSYsf/YmXIqdg/dVaCFrJdA1v2bDFymuPbA0P4Ey8c4ylInXGgK4yxS7nVC4qbbVtK5bWT3SRaBWw=|0r9TcWfl93tZln8+ZGrPwZTHBbrLiSuVXvoI+cQeSr0=","providerOrganizations":[],"providers":[],"securityStamp":"6cbf7cd1-d2a2-4c5a-97d7-91042285c49d","twoFactorEnabled":false,"usesKeyConnector":false}`)) - - // We're changing the revisionDate on purpose in the response to mimick Bitwarden official server's behavior - httpmock.RegisterResponder("POST", `http://127.0.0.1:8081/api/ciphers`, - httpmock.NewStringResponder(200, ` - { - "attachments": null, - "card": null, - "collectionIds": [], - "creationDate": "2024-09-22T11:13:40.346903Z", - "data": { - "autofillOnPageLoad": null, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "password": null, - "passwordHistory": [], - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "deletedDate": null, - "edit": true, - "favorite": false, - "fields": [ - { - "linkedId": null, - "name": "2.svtF3aK9R1MLHt2GwH7Ykw==|PqVDa02T0Vzx6ogTNz1Xyg==|g9/Gd5OOLkVtyVAk9vkRCY2reWTZjdY1D3XsVpBfQA4=", - "type": 0, - "value": "2.K49DvcymvaQ/+V/3soCb1Q==|r+b2dz0YqFeA8BrHii5a0DIjkwxdwlY+aEEH2d2NdC0=|KEJAjqImC0Jit9oaFN2rSZHyetxuD7jEjMt07HPFLvU=" - } - ], - "folderId": null, - "id": "24d1c150-5dfd-4008-964c-01317d1f6b23", - "identity": null, - "key": null, - "login": { - "autofillOnPageLoad": null, - "password": null, - "passwordRevisionDate": null, - "totp": "2.mScxVU7uCx3fiPXYlgzWVA==|yxqIjknG71Qdwxq1wyVufWyB1Hb6qWowPgGoZNV2d4s=|uY7hrn7Eow81A76/n4VUrJxSRtC9VDnUdaesO6y0ivY=", - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uris": [ - { - "match": null, - "uri": "2.7ihoxwsJH4HBkTzjFBwFIA==|5EkQHm4IRExHH/LAU6D/jw==|Hs6YgBIFuTQNnH9M3ejgUAVzsGjxAyaVPi1pl1NU9wg=", - "uriChecksum": "2.WfCD+h+rQ49rJDiTM7ycjw==|QgYnnlKzeymjRXmW15SC7bnWWvWaU1iki7rABdi0+RjPgRVGLluT/lQCKXkr5fXH|vaMZaBCKZySaycxVXjpDatKjrN6mBaq2ffRsygLTGzA=" - } - ], - "username": "2.9hmypXsnAjVxJ2e5kZQLKA==|8Jif+MQgdTuAlaCn7i/xig==|xy7zJh4qXutESyC02aKSYb/79EmfbGsYlxsYfKqneLA=" - }, - "name": "2.LjR8NxRtCB1noDILxNKmPQ==|s4e2AO4I3HqmPRRsbsYl0XYSuWu7+sn2K3+jNiFjsW0=|3NQW64/3RmPxe3hhUGeMTrSy9Ruh5hYRlJxIhhWhhSI=", - "notes": "2.ke3IFCPe50UCM2XdJDS/VQ==|ksO+dyEuRBgrpAelfhxNhw==|JrbMU58V5QyiTpdJXyWB1g2l8jPcqyeWDMqjOnaa9UA=", - "object": "cipherDetails", - "organizationId": null, - "organizationUseTotp": true, - "passwordHistory": [], - "reprompt": 0, - "revisionDate": "2024-09-22T11:13:40.345356Z", - "secureNote": null, - "type": 1, - "viewPassword": true - }`)) - - return webapi.NewClient("http://127.0.0.1:8081/", webapi.WithCustomClient(client), webapi.DisableRetries()) -} - -func createTestAccount(t *testing.T) { - ctx := context.Background() - preloginKey, err := keybuilder.BuildPreloginKey(testPassword, testAccount.Email, testAccount.KdfConfig) - if err != nil { - t.Fatal(err) - } - - hashedPassword := crypto.HashPassword(testPassword, *preloginKey, false) - - block, _ := pem.Decode([]byte(rsaPrivateKey)) - if block == nil { - t.Fatal(err) - } - - privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - t.Fatal(err) - } - - encryptionKeyBytes, err := base64.StdEncoding.DecodeString(encryptionKey) - if err != nil { - t.Fatal(err) - } - - newEncryptionKey, encryptedEncryptionKey, err := keybuilder.EncryptEncryptionKey(*preloginKey, encryptionKeyBytes) - if err != nil { - t.Fatal(err) - } - - publicKey, encryptedPrivateKey, err := keybuilder.EncryptRSAKeyPair(*newEncryptionKey, privateKey) - if err != nil { - t.Fatal(err) - } - - signupRequest := webapi.SignupRequest{ - Email: testAccount.Email, - Name: testAccount.Email, - MasterPasswordHash: hashedPassword, - Key: encryptedEncryptionKey, - KdfIterations: testAccount.KdfConfig.KdfIterations, - Keys: webapi.KeyPair{ - PublicKey: publicKey, - EncryptedPrivateKey: encryptedPrivateKey, - }, - } - - client := webapi.NewClient("http://127.0.0.1:8080") - err = client.RegisterUser(ctx, signupRequest) - if err != nil { - t.Fatal(err) - } -} diff --git a/internal/bitwarden/embedded/vault_webapi.go b/internal/bitwarden/embedded/vault_webapi.go index b8b91e5..c6d1116 100644 --- a/internal/bitwarden/embedded/vault_webapi.go +++ b/internal/bitwarden/embedded/vault_webapi.go @@ -471,12 +471,7 @@ func (v *webAPIVault) LoginWithAPIKey(ctx context.Context, password, clientId, c return fmt.Errorf("error login with api key: %w", err) } - kdfConfig := models.KdfConfiguration{ - KdfType: tokenResp.Kdf, - KdfIterations: tokenResp.KdfIterations, - } - - return v.continueLoginWithTokens(ctx, *tokenResp, password, kdfConfig) + return v.continueLoginWithTokens(ctx, *tokenResp, password) } func (v *webAPIVault) LoginWithPassword(ctx context.Context, username, password string) error { @@ -497,7 +492,7 @@ func (v *webAPIVault) LoginWithPassword(ctx context.Context, username, password return fmt.Errorf("error login with username/password: %w", err) } - return v.continueLoginWithTokens(ctx, *tokenResp, password, kdfConfig) + return v.continueLoginWithTokens(ctx, *tokenResp, password) } func (v *webAPIVault) RegisterUser(ctx context.Context, name, username, password string, kdfConfig models.KdfConfiguration) error { @@ -582,10 +577,15 @@ func (v *webAPIVault) Unlock(ctx context.Context, password string) error { return nil } -func (v *webAPIVault) continueLoginWithTokens(ctx context.Context, tokenResp webapi.TokenResponse, password string, kdfConfig models.KdfConfiguration) error { +func (v *webAPIVault) continueLoginWithTokens(ctx context.Context, tokenResp webapi.TokenResponse, password string) error { v.loginAccount = Account{ - VaultFormat: "API", - KdfConfig: kdfConfig, + VaultFormat: "API", + KdfConfig: models.KdfConfiguration{ + KdfType: tokenResp.Kdf, + KdfIterations: tokenResp.KdfIterations, + KdfMemory: tokenResp.KdfMemory, + KdfParallelism: tokenResp.KdfParallelism, + }, ProtectedRSAPrivateKey: tokenResp.PrivateKey, ProtectedSymmetricKey: tokenResp.Key, } diff --git a/internal/bitwarden/embedded/vault_webapi_test.go b/internal/bitwarden/embedded/vault_webapi_test.go index 6ae757c..4012729 100644 --- a/internal/bitwarden/embedded/vault_webapi_test.go +++ b/internal/bitwarden/embedded/vault_webapi_test.go @@ -5,60 +5,54 @@ import ( "testing" "github.com/jarcoal/httpmock" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/embedded/fixtures" "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/models" + "github.com/maxlaverse/terraform-provider-bitwarden/internal/bitwarden/webapi" "github.com/stretchr/testify/assert" ) -func TestLoginAsPasswordLoadsAccountInformation(t *testing.T) { - ctx := context.Background() - httpmock.Activate() - defer httpmock.DeactivateAndReset() +func TestLoginAsPasswordLoadsAccountInformationForPbkdf2(t *testing.T) { + vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Pdkdf2Mocks)) + defer reset() - vault := NewMockedWebAPIVault(t, mockedClient()) - - err := vault.LoginWithPassword(ctx, "test@laverse.net", testPassword) + ctx := context.Background() + err := vault.LoginWithPassword(ctx, fixtures.Pdkdf2Email, fixtures.TestPassword) if err != nil { t.Fatalf("vault unlock failed: %v", err) } assert.Equal(t, "API", vault.loginAccount.VaultFormat) - assert.Equal(t, "test@laverse.net", vault.loginAccount.Email) - assert.Equal(t, "e8dababd-242e-4900-becf-e88bc021dda8", vault.loginAccount.AccountUUID) + assert.Equal(t, fixtures.Pdkdf2Email, vault.loginAccount.Email) assert.Equal(t, models.KdfTypePBKDF2_SHA256, vault.loginAccount.KdfConfig.KdfType) assert.Equal(t, 600000, vault.loginAccount.KdfConfig.KdfIterations) - assert.Equal(t, "2.D2aLa8ne/DAkeSzctQISVw==|/xoGM5i5JGJTH/vohUuwTFrTx3hd/gt3kBD/FQdeLMtYjl1u96sh0ECmoERqGHeSfXj+iAb9kpTIOKG8LwmkZGUJBI90Mw0M7ODmf7E8eQ+aGF+bGqTSMQ1wtpunEyFVodlg92YN8Ddlb2V9J4uN8ykpHYNDmQiYLZ8bl6vCODRGPyzLvx5M8DbITVL5PhsjKDLLrVV8lFCgCcAL5YLfkghYhFELyX15zXA/KYEnwggDka3hG5+HHFOVZSeyk7Gi6M4TX2wADbTXz1/Wsho8oxFUrtNiOB3ZiY2cx9UWttpzMXoGfi2gJcP1db/nTfWenOLlzw6Od4VyRzsXsfyGwbqBqDnNFkjLvhjVw4JO+psF//xAMDs14101Tf2wFkB6toQ+zdnDphXUeKmiVPQ7gMnQlOWN5tWvjjmYOO4Y63sGpP24cDOdEScIdebZRSA8uOhTzadfKfOiH5zVYZzXs33FQ0li4nBrsj5xYa6PP4D1P7gqjxClPdguwkdLoZ7JvgIlyRIwEcORi5Ich8RWF/kqRBwk0QSzK1mTlHHU5xtSgi4MLNVx4qTYNaJVBtwL9d2MD9LeNn4Z2PL4A7qnszHqsERiQQDxNEgMxMBHDgSXqQbtQxRvsI6oY+yNbN7uVWw4o8AC3f5GBdxzIqcN1mgEM5ix5aDt15w3MhP2FHtf2neKI68TnL8WnT1fT8BVlbECIiUqK0tfq5aTjdSh3gCS15jvZ1H60h+K8+O/nDfquzVjY7UsTGwA+UtS8/JGiaUhc0VhxJo8P1V2VSCiu51d5q3De1vDg5R2VEgBmTchZyTIodC+3+7ACTOwkNCCdIJN7xKOcIGFA7QOuyJtBeXT4Rd9UGMHSL054IB/315WVDiwrP9W1aP0nHzFs+qAXbH5o1E+AmfMDyoHopjGgbUw22r837kHzf5Qe8QhRYPzQvDowfCPhdoy23cbN1VsNavNwTC9hcG5oYMwkK66xP3MEM9UfGD22pwxe7M8U4BRdLCCHbi95eklXE6Mg6DpWsAdMgokQbOvnlwgKfrlbltqXUE/vUQI8TB3AE1Nkt0ST4quTriMuuyiHdeeZV4UkV9jWt/5bTCfdrCYuGZP7g4shbfNcP7u1Zrdxv+EuUwGIOOTrNV5awmBnL3iHE5ya2MnqmRyfWiPIT5majZCk06yxj4XzyIPOpjYKFt0MOgLvG1GllmdtRqg7tMVvc5ZFo5KWIxLsIJD12UjA1GYYoFdX4+wsNbPjfnlE6D2PrtWUICnBFJzYpfyrKTe01k8G8hyyz+tVzBRfz8EA2ew1+hlVcAgSPCcBzhDgqPe+RSPi7ZSd66be1gDhGAftWFM8Z0MrMklXi2DyjjaKBNsZZD8qTcLcobm8nqHUQtnr5JCbmgP3rau8NY/fxeFHsvSiZQoB1aI/y+Sz/R4r+T9cg8hjmS/FUHDO+m6a6nuWNFwz8wIluM557oOTl+A9UGFF50Gpzmf97VdQjM3ZREazQ7la6AobzS3BHI6FNdxN9LTyMpYo+WODv52/VwU3ODH7wf5bz2OHZhk2NG5R7pSH7qg8jM+/MtJkFumENV0qMecozIkP6e4CyI9ua4YwI9n7G5OgKYMG1aj2PRSny2JSLS8aHF1TkRL8SD0nZFCox0=|muEtiwIuZxhuuLv0nouEdxHU2CO+I7JXKZuYHWiv/OE=", vault.loginAccount.ProtectedRSAPrivateKey) - assert.Equal(t, "2.lkAJiJtCKPHFPrZ96+j2Xg==|5XJtrKUndcGy28thFukrmgMcLp+BOVdkF+KcuOnfshq9AN1PFhna9Es96CVARCnjTcWuHuqvgnGmcOHTrf8fyfLv63VBsjLgLZk8rCXJoKE=|9dwgx4/13AD+elE2vE7vlSQoe8LbCGGlui345YrKvXY=", vault.loginAccount.ProtectedSymmetricKey) + assert.Equal(t, fixtures.Pdkdf2ProtectedRSAPrivateKey, vault.loginAccount.ProtectedRSAPrivateKey) + assert.Equal(t, fixtures.Pdkdf2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) } func TestLoginAsPasswordLoadsAccountInformationForArgon2(t *testing.T) { - ctx := context.Background() - httpmock.Activate() - defer httpmock.DeactivateAndReset() + vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Argon2Mocks)) + defer reset() - vault := NewMockedWebAPIVault(t, mockedClientArgon2()) - - err := vault.LoginWithPassword(ctx, "test-202341-argon2@laverse.net", "test1234") + ctx := context.Background() + err := vault.LoginWithPassword(ctx, fixtures.Argon2Email, fixtures.TestPassword) if err != nil { t.Fatalf("vault unlock failed: %v", err) } assert.Equal(t, "API", vault.loginAccount.VaultFormat) - assert.Equal(t, "test-202341-argon2@laverse.net", vault.loginAccount.Email) - assert.Equal(t, "c64a1f8d-223c-40fd-adde-a90d58dbc26c", vault.loginAccount.AccountUUID) + assert.Equal(t, fixtures.Argon2Email, vault.loginAccount.Email) assert.Equal(t, models.KdfTypeArgon2, vault.loginAccount.KdfConfig.KdfType) assert.Equal(t, 3, vault.loginAccount.KdfConfig.KdfIterations) - assert.Equal(t, "2.0Xc+uV+6YVa+Zkg74C/MJA==|xTbZGy2r8/kHcXXy23YDHWDTHjasUUoHiWJ84rGEhuPD27GTF8DrFL+lbERo3+OH7MXvseAFygKArvSumlCQnMhT/dswJMH8ZEMuxQUZ8I7kg/7eNqxRndxyC8alZh3VM4FC7TsuVBe6BF4pbPQYX4etFL8yOHLpIhwkKcG7+IfQHQHwOXpsSiGpADQlk5er990snhAXwGpgROqoveO9klpNJXuEzJKMFMdoo9FCaRsJ4bB3BE/Y+8Ph7ek8mGyoUUqNFp8Z/T+XN+9kvxDFnVFtYp1p+sU8LpCSvaq3dAImQt6X7vAgfjbWVkTxB0HlBdMkjpg8BAK7qpscT5oH83SZqdNPRi9kkT9Y30xl0QvvJzXLcjqOS6je+i3vB1r4O8X3ZIj+th4cfZOfHKpzDLbGyAezxiiWwQ4xt0USQ9rLv+BU5YNDKnibmsIooKHuh8wV0qht8vr2CEVavXOmmBi/6bGIWJMOs2K52be5LJkYL+653dsKXBN4uahQDMdfs9vPUA7OoIFR9BZvQiGMDstFYVgJUulOkj2J4nieuTAmurQe6nS6U4v1swI7DIzdo8ZCJcAQfWYWk8IBwh6gQxSuPMg7+O2dntbPFkMP2KhoisUucoXNIDXmxwYAMeP01KMNSgFc6hL6WnLzyVcRlSLy7OC9qwTD6ZH6XA4D/MO9MINTTzw4+/pZvwTeuXMqB0HkcjTpWzTUi405uV6qh8CxYOaNEl6kNAMiuVNASToqYb/EBC0uGOybOzcNZOCiXmuiPVOstiz65KP1d3Dfl9al48hpxnDxFyFub5NDx8xADA3SzOlI9xMCsC/mcY0/fRlwoTDFCLzfdtPIdSn5N8/YySY10e/TXftKGV7bLvzGAlOntwoiWaLJbyHAnEXNUVFxJu5XVaVccXcxIKete42S291dCu4yk35KsIQU0jBaPB/hGXLJvvySl9/kARl0zIXJH+Pk0hlk+/IRH9HNZrru93WTgW9KjEeT2vaZ6UqULkkspIfoUrFxQfSyAxycDaqa4EHt1QJBKyC9+aWEOXNwtxkJTnhtvlqRPOGUpdkAyC5ebfdX2URZnd/2TR/PTviWaDKe/g51UWr8QepgwbJjkBeuZMSPCNHkcLdmwEZERisbZ7H50hDQhhK+qfmMOvkVrRRXKT2ICbQzchm5rDasdtMed7vIf3beS0ESIR8kZ1WmteI9dvWmagnXRlfsUZW0y0KWe9Ma/ISOa6QPb0Cc7T8LUg2lpREQpRTt119RX9Xugd2uZ+UzbGpqn9u5JY2+vddwv+zFL0g/Vu9h3kd02v+WTXeV8wLDJYkoc6XeTBzC0uQtNJt4oN7hWcMBrkYmnXxslIjGw/nE7eBnG02XWTCeTjADqXtz2j4xMFmzJod+4j4f6MQZBII9Sz5A2FfSbadUuukEYcFvkqLnjG/sMzcBQMIDP6vmy7VRnETahlNi7Pt+gRLHuhGN1BbScolW7a0YnWlI1T0MtKb4DBsjX9GfotxkG+ORg/i45YnG6KPQ6+jgXU3Xtf0tgjTqHVgc7TOCm9R2b4G24RSQXx3WaMP1slbSYsf/YmXIqdg/dVaCFrJdA1v2bDFymuPbA0P4Ey8c4ylInXGgK4yxS7nVC4qbbVtK5bWT3SRaBWw=|0r9TcWfl93tZln8+ZGrPwZTHBbrLiSuVXvoI+cQeSr0=", vault.loginAccount.ProtectedRSAPrivateKey) - assert.Equal(t, "2.VBpAJrIHYLv60UTYy5e7sA==|WWsozKnKPVvBYttXtlAzpmZPoffwlY3+8Wup9SBdGcO8T4Ybj808DubDhICTPMz9RliDSJ1OuaivBC0rh/7EcWV1s9KuRth5J3XFWJqmtXU=|l1ly+Uek1j4k2xQNT8iJ++GdwMTWRaSBP5mFvgJ+CGU=", vault.loginAccount.ProtectedSymmetricKey) + assert.Equal(t, fixtures.Argon2ProtectedRSAPrivateKey, vault.loginAccount.ProtectedRSAPrivateKey) + assert.Equal(t, fixtures.Argon2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) } func TestObjectCreation(t *testing.T) { - ctx := context.Background() - httpmock.Activate() - defer httpmock.DeactivateAndReset() + vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Pdkdf2Mocks)) + defer reset() - vault := NewMockedWebAPIVault(t, mockedClient()) - - err := vault.LoginWithPassword(ctx, "test@laverse.net", testPassword) + ctx := context.Background() + err := vault.LoginWithPassword(ctx, fixtures.Pdkdf2Email, fixtures.TestPassword) if err != nil { t.Fatalf("vault unlock failed: %v", err) } @@ -73,6 +67,14 @@ func TestObjectCreation(t *testing.T) { return } - assert.Equal(t, obj.Name, "Item in own Vault") - assert.Equal(t, obj.Login.Username, "my-username") + assert.Equal(t, "Item in own Vault", obj.Name) + assert.Equal(t, "my-username", obj.Login.Username) +} + +func newMockedWebAPIVault(client webapi.Client) (webAPIVault, func()) { + httpmock.Activate() + + vault := NewWebAPIVault(fixtures.ServerURL).(*webAPIVault) + vault.client = client + return *vault, httpmock.DeactivateAndReset } diff --git a/internal/bitwarden/webapi/models.go b/internal/bitwarden/webapi/models.go index 45205bc..1d72a2a 100644 --- a/internal/bitwarden/webapi/models.go +++ b/internal/bitwarden/webapi/models.go @@ -71,6 +71,8 @@ type PreloginResponse struct { type TokenResponse struct { Kdf models.KdfType `json:"Kdf"` KdfIterations int `json:"KdfIterations"` + KdfMemory int `json:"kdfMemory"` + KdfParallelism int `json:"kdfParallelism"` Key string `json:"Key"` PrivateKey string `json:"PrivateKey"` ResetMasterPassword bool `json:"ResetMasterPassword"` From 7565b6344d1392dc1a3da8a5a4a5a8bde262cc1b Mon Sep 17 00:00:00 2001 From: Maxime Lagresle Date: Wed, 2 Oct 2024 09:48:16 +0200 Subject: [PATCH 3/3] more tests for login with API key --- .../embedded/fixtures/create_accounts_test.go | 10 +++ .../fixtures/test-kdf0_GET_api_sync.json | 74 +++++++++++++++++++ .../test-kdf0_POST_api_accounts_api-key.json | 5 ++ .../fixtures/test-kdf0_POST_api_ciphers.json | 16 ++-- ...test-kdf0_POST_identity_connect_token.json | 13 +--- .../fixtures/test-kdf1_GET_api_sync.json | 74 +++++++++++++++++++ .../test-kdf1_POST_api_accounts_api-key.json | 5 ++ .../fixtures/test-kdf1_POST_api_ciphers.json | 16 ++-- ...test-kdf1_POST_identity_connect_token.json | 13 +--- internal/bitwarden/embedded/vault_webapi.go | 15 ++++ .../bitwarden/embedded/vault_webapi_test.go | 36 +++++++++ internal/bitwarden/models/models.go | 6 ++ internal/bitwarden/webapi/client.go | 21 ++++++ internal/bitwarden/webapi/models.go | 6 ++ 14 files changed, 272 insertions(+), 38 deletions(-) create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_accounts_api-key.json create mode 100644 internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_accounts_api-key.json diff --git a/internal/bitwarden/embedded/fixtures/create_accounts_test.go b/internal/bitwarden/embedded/fixtures/create_accounts_test.go index 899ce0b..8b99a10 100644 --- a/internal/bitwarden/embedded/fixtures/create_accounts_test.go +++ b/internal/bitwarden/embedded/fixtures/create_accounts_test.go @@ -101,6 +101,16 @@ func createTestAccount(t *testing.T, accountEmail string, kdfConfig models.KdfCo t.Fatal(err) } + apiKey, err := vault.GetAPIKey(ctx, accountEmail, TestPassword) + if err != nil { + t.Fatal(err) + } + + err = vault.LoginWithAPIKey(ctx, TestPassword, apiKey.ClientID, apiKey.ClientSecret) + if err != nil { + t.Fatal(err) + } + _, err = vault.CreateObject(ctx, models.Object{ Object: models.ObjectTypeItem, Type: models.ItemTypeLogin, diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json index d6e2dd3..4350e21 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json @@ -1,5 +1,42 @@ { "ciphers": [ + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:42:36.462697Z", + "data": { + "fields": [], + "name": "2.JtYOMVeWZcP4enXUHfkAng==|F6nhgNFcKmIb//4YaFYqgnnJ0WZ078BHTkSUSGKMytY=|9gS6j3xzbIL3iBkPeA3fA3WaqcM7kmRE9LTXGFudxEc=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.Qx257ROoxcl4g410tpimeA==|lCmrwQQYF43LtGa7f1Gr0Q==|kkco4xdNJWRDWBJ1pDsnkyJzpAFi9EBf+VunlVenwiE=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "42ae27ca-64a6-4ddc-a488-1436bfc4883e", + "identity": null, + "key": "2.RyTOBsgtSyL0Omu4XnUakQ==|bF+NAs2MCuN1sEye0YR3uQqrgncZxNxrYODlEUL7W7XXbFxKaGVo0fpevMFo8Ov/c1Wb8KfIWyGHC1T/cezG0GMONMeyMreaUl3LbWmRKtA=|3BiW9s0qPt3bgPu7ok78hzPC8Gf9A2/rL/oU5KEODdw=", + "login": { + "uri": null, + "username": "2.Qx257ROoxcl4g410tpimeA==|lCmrwQQYF43LtGa7f1Gr0Q==|kkco4xdNJWRDWBJ1pDsnkyJzpAFi9EBf+VunlVenwiE=" + }, + "name": "2.JtYOMVeWZcP4enXUHfkAng==|F6nhgNFcKmIb//4YaFYqgnnJ0WZ078BHTkSUSGKMytY=|9gS6j3xzbIL3iBkPeA3fA3WaqcM7kmRE9LTXGFudxEc=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:42:36.462837Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, { "attachments": null, "card": null, @@ -35,6 +72,43 @@ "type": 1, "viewPassword": true }, + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:42:54.189187Z", + "data": { + "fields": [], + "name": "2.w4kzDaZLWBQLwFMffQUc4Q==|gwtAiY/86hyH/kh/diHlJBQ6wlQZc4xMrpHvkVzdGp8=|gqF2h3FN9S5hiDK1kASO8wBjNp8ognh8w25tsKfA+Go=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2./SO1TFQJ9BxFipSJIuhVeg==|VapfwOlRcxVnNj+5Tz8YLg==|0MJNPVx43qXBou7o84jccWRumDG+GQqkxexbhArGUFc=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "dced7812-e7a3-4163-b50c-74bee6126553", + "identity": null, + "key": "2.yoo9dZOltLBIDjLudHfx+A==|jNRvIbWF+7FjAq0DcB00oYiGOSKH9DdRk4y1pbLxvZzTaAL637831eiru9Prq6jUdjDdryvqxQFAOm8sRO40s+VVUBdI48ILc/WO+FUT7do=|QAgU5av2dp8zRmbWdxbullH//bo0IdNS8u3JAG+/eJE=", + "login": { + "uri": null, + "username": "2./SO1TFQJ9BxFipSJIuhVeg==|VapfwOlRcxVnNj+5Tz8YLg==|0MJNPVx43qXBou7o84jccWRumDG+GQqkxexbhArGUFc=" + }, + "name": "2.w4kzDaZLWBQLwFMffQUc4Q==|gwtAiY/86hyH/kh/diHlJBQ6wlQZc4xMrpHvkVzdGp8=|gqF2h3FN9S5hiDK1kASO8wBjNp8ognh8w25tsKfA+Go=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:42:54.189295Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, { "attachments": null, "card": null, diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_accounts_api-key.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_accounts_api-key.json new file mode 100644 index 0000000..36c8437 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_accounts_api-key.json @@ -0,0 +1,5 @@ +{ + "apiKey": "ZTXHHyPY6bNlNq1diDA2nM1GROboP3", + "object": "apiKey", + "revisionDate": "2024-10-02T07:42:36.462941Z" +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json index 384747c..c499f16 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_api_ciphers.json @@ -2,35 +2,35 @@ "attachments": null, "card": null, "collectionIds": [], - "creationDate": "2024-10-02T07:23:54.495716Z", + "creationDate": "2024-10-02T07:42:54.189187Z", "data": { "fields": [], - "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "name": "2.w4kzDaZLWBQLwFMffQUc4Q==|gwtAiY/86hyH/kh/diHlJBQ6wlQZc4xMrpHvkVzdGp8=|gqF2h3FN9S5hiDK1kASO8wBjNp8ognh8w25tsKfA+Go=", "notes": null, "passwordHistory": [], "uri": null, - "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + "username": "2./SO1TFQJ9BxFipSJIuhVeg==|VapfwOlRcxVnNj+5Tz8YLg==|0MJNPVx43qXBou7o84jccWRumDG+GQqkxexbhArGUFc=" }, "deletedDate": null, "edit": true, "favorite": false, "fields": [], "folderId": null, - "id": "f1d8b375-8b6a-4bb5-9659-520c2864c2e0", + "id": "dced7812-e7a3-4163-b50c-74bee6126553", "identity": null, - "key": "2.H87CevHa/yLkUvgJfpha5g==|IrEdZ2aHOG0P/xCvymr++yzWsMwupJ7Rq0mN9kqTYTc2bsBlpi7/bqva1RhhBRoMuwFnMTx/cX4bMWHZKJbpjV9CENI475Q3JgJScjY/ceQ=|jMosP2JYP9PqRhEODetF2ZNuGkEgLuIR+6jy1ILosk0=", + "key": "2.yoo9dZOltLBIDjLudHfx+A==|jNRvIbWF+7FjAq0DcB00oYiGOSKH9DdRk4y1pbLxvZzTaAL637831eiru9Prq6jUdjDdryvqxQFAOm8sRO40s+VVUBdI48ILc/WO+FUT7do=|QAgU5av2dp8zRmbWdxbullH//bo0IdNS8u3JAG+/eJE=", "login": { "uri": null, - "username": "2.2slHKGwhT9pYZNuZJZELtQ==|2S8vFbqTdE2O5jghb5fIPg==|wUYsi6TFyOdFL1nJG16nO3FMRH4QAtVyNb1vzchcIg8=" + "username": "2./SO1TFQJ9BxFipSJIuhVeg==|VapfwOlRcxVnNj+5Tz8YLg==|0MJNPVx43qXBou7o84jccWRumDG+GQqkxexbhArGUFc=" }, - "name": "2.1r73Ar0+UEKhQ6/HJlgy6w==|JJ9AyivpozzvKk5fdyHirGbsDQI1kwlVr6xZoAZt6dg=|5Xy/XeqN6YdLKC4dVCECydxJbBTonMq9tq6e0/Y0bGw=", + "name": "2.w4kzDaZLWBQLwFMffQUc4Q==|gwtAiY/86hyH/kh/diHlJBQ6wlQZc4xMrpHvkVzdGp8=|gqF2h3FN9S5hiDK1kASO8wBjNp8ognh8w25tsKfA+Go=", "notes": null, "object": "cipherDetails", "organizationId": null, "organizationUseTotp": true, "passwordHistory": [], "reprompt": 0, - "revisionDate": "2024-10-02T07:23:54.495998Z", + "revisionDate": "2024-10-02T07:42:54.189295Z", "secureNote": null, "type": 1, "viewPassword": true diff --git a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json index 86bce5f..53e60e7 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf0_POST_identity_connect_token.json @@ -1,23 +1,14 @@ { - "ForcePasswordReset": false, "Kdf": 0, "KdfIterations": 600000, "KdfMemory": 0, "KdfParallelism": 0, "Key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=", - "MasterPasswordPolicy": { - "object": "masterPasswordPolicy" - }, "PrivateKey": "2.11j1IvphccY0UkZov7ZbmQ==|4J34a16NM+krEXyDUkHVUNL2sSA7dph4EBCLWoDkmDoljqMZh5IxA7M51yZTNB6/uqGgJZJX0uU+B4RSn2s2JoFG/VizMmgSIJkTIr6WuA7taEzyIFRi7sY980W02pnLeb8fGV8EXrZk1Bj0UzAFukNGoeS2CHWbm0bZKRvDxl5Vw40V3Lt6GzHTb6X+4k4Ovg0UKgm2mqMWzxxjmCfy+G1R0vlsAtqg14n2ax5f3Jn4ajGDvT2BQia9EFYFkie/SfqgsYbtvou4DvyCTEWh0j9Cre1QIJQ9AZ4AHAzGwIKFhpN7sWjsfw6yTGmvxAfflCMFzCdleBBiuCefaAKNe5Uf1QASC9TzIiHknl2+sK9lOFZ+XZJ41HCU2sMvNBu1EHuBPNRIHodCEHdXHyRqBaC+vgWO6RcTWU4K5ZctBKmElAYst7FFCuzM+liUcGp3I1a7wxOJTPraxeFw8z69rYFiNMOng/HkV/G/VUQXzWalC5gtjaR35dMp35Mf1lMlGnWhy/qdLr0NVdl69qUDKt+kCG9+kiXO7Eq5PTbV+tj4AxBzxE1DroAh0jTPFLb7p1205+OQqqrCEq6tzpGHKTFLoyHZCVoxdQvxgFNX6+fNi3+MfbDfLle7msQAwOuaUl6rxcb2JjdgRQQUd4/GQbvKeLjFRIr7OtcVHWm3251jqRLBgFJcQ235SFgdjLnKATqN4BRe0WLyYOMuMQEmfQXaebjzMo7L2JMJeOar9QutuV+Acle7kJZZU4N1XPiUmborUksAcrmLGXvQITn1QLmadou0jX/oov+lkrKDIFTJC5MIutVBNmExS6FqW978viF1ZNgRQxG5OULHoT5tgfyjrl2u74VFf0ttbLC/JSsi1k8me2LA2vi2Sx7DNOzd6fLx0f8+mYmz2VTRw6fnoFh99d8HktPUNyKcGNZyZpsfkkhFSFV/U88tZ9gROWayLbRXS6g801Mi0tBg0RJp/Flo9ZX9Y3qKVWLCDZT6t3l1NR2npkGmi16yqslXSs9hadIvd6lxyYqyW6cskuJjsacHPOCyvz1xZFH6txtzmb46UrKUU7Cjo/09Kmtb740rXzhH/0nPuvJUjlk0UN77LqzvnvVWAe2IJVEjsbhTspLw3Z1fmCQxMKvc3yPA36/KP2uk/wOlHmBnuX/eebQmI22PFOzskl1d0ScNItJsw5D6fkEhybxEY3oPWYG5y+Oitqj1dQy/TNKXeJHMP+MC1PxzvaE3jq/+cb0IwVBnMVblbaHCJM6JAllV/p3Z6/Ho3Ps4hDHRflKZjP2HyB5wvvTtYhX5XpDoA8s9e6TpDXYnoE+XLN4Thzu30GL3WBeI7koYuNEpRhD5++oT2CElpEqo0v/TFKGSmnV+qohWTL8I4WnHSZeKDLC5alqIMYgRkN6qUlVJLzILOFzeJcL9zeXsAeHemd3VZWe0OYiJRxVwBCYGHk6W7WA4pZ+Wq/C0JHaxNJhr9gx0kyFlMPBkwN/LEyUP+PxsqIuW+09f70qZdGE1r9bNjUSKmb53I6nqxwQhIwvpZZDGAOZjaxrfC8PE9rOOTkM3v6zsSWgjl4EJMPwJubHJb63w5hvW2DwS4h3t7lduTab9ykKInvfBsaWxLuBhJuX+fesGTM0KGXs=|BXz0QzgtArYQXICHbYvGqOeFVi9YGZRP0MASNlVwzzY=", "ResetMasterPassword": false, - "UserDecryptionOptions": { - "HasMasterPassword": true, - "Object": "userDecryptionOptions" - }, - "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTM4MzQsImV4cCI6MTcyNzg2MTAzNCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6ImFhZjE1YmQxLTRmNTEtNGJhMC1hZGU4LTlkYzJlYzBmZDJjMyIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjBAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMEBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJhYTQ4NTQ2My1jMjU4LTQwYjUtYjJjZi1iZjIyYmY3MDUyNTgiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsiQXBwbGljYXRpb24iXX0.HBnh7fQehhK5cVslhxLLckkYhDtY4IFXTTqLMMcB5HzyQtFfFgyllxisQsqnLikGF7W4K-UN_L26h_pWKRzWdywxbNRKAs7Jc6NYeesSXJpsBrC1zqXKv5rWSyM59oqM3fp_owRqftv9ujvKqEn_c-UteVvtmL_ieS66H2tPp8zBT08FK23ra1EhvW9O6UA7Qx8YxrHCnvOIVJ16paiPSjYWBR_p7fz0sBzoz2ypGGQ6UpJJpW60UK4AAT7-DxJe68eRIwHpbLd7ZjR3x53Y9bBI7toZ3SemXP7guz6fWl_xqj7UteB3C1a9ISI7TFCkJUP7BVRNBJbYdRHEzFZxUg", + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTQ5NzQsImV4cCI6MTcyNzg2MjE3NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6ImFhZjE1YmQxLTRmNTEtNGJhMC1hZGU4LTlkYzJlYzBmZDJjMyIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjBAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMEBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJhYTQ4NTQ2My1jMjU4LTQwYjUtYjJjZi1iZjIyYmY3MDUyNTgiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiXSwiYW1yIjpbIkFwcGxpY2F0aW9uIl19.Wz8DpAJrjbCvmFHsYSUht_mPmfylqr7fK83Y7VRBFYY_noLikp3PAlX1DLdTKJhxMItzvD-Lx9L9EtAt1LpRTzYz3Z-977UloJ60lGAp8wBJNp3KgFI-rLzgET4HhuccDdnoIlMUybSmPn0VJ5zrjXIwq2oSxaEPSm9zSrUgI0p7c6feie10faE_6ixyWJFmuAw5U_k2dLLbx3mHqBNdBgyVGMNhrxjSEMmoEfqm-uKjPWF2Cu09NYMGpD_hHkmI4NKwee6LxHWFfaEFQeGZvDqZ-IPNBY0qGg7dc4kun1-6cnDWmPxUIaQemEQWj__STTo6WDpFcinyZQS4Fx7HGQ", "expires_in": 7200, - "refresh_token": "q89oDzmqCjdl4cxLj9RCKjCA8oQtjxZc2vebEWIApputzfVSYjpWJ9Tq_yVNhK0Rd7RJKksg4ycfkMqyVgG2xw==", - "scope": "api offline_access", + "scope": "api", "token_type": "Bearer", "unofficialServer": true } \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json index 07707ed..ee34cd9 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_GET_api_sync.json @@ -37,6 +37,80 @@ "type": 1, "viewPassword": true }, + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:42:54.536202Z", + "data": { + "fields": [], + "name": "2.lSAI94z++lxjXV7F60wD8A==|c02oRIWPKahtdY0/fRUUaWmEr5AvLGrycczUq66jg+0=|Oq9Qhqd1rFqD+hU+O+pkx94PgoJMfJf20mBHVY7DReQ=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2./yXF39ra7G1lu1+bi6YpMg==|7mFeZwcbWq5ZxTSywQx88A==|SkefRdevf6PMxJ73nyfQsRgPwmebcZOxBc3L2dCnanA=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "8c071b82-5c79-47b5-8153-b37186daa5a2", + "identity": null, + "key": "2.H/woeJP3IG0/0MUun7vcUQ==|661oI8gy9efZtIHvXYhNwmr3fz0gwLm4LZwMsJUc1Ek+Ooq7wKfc/yTg+TLDY6ScDebhxDD6SAlRbgoBTbcTiF5CYB8ax2wUmNBpSPKYEoY=|aHEWPgao+Wo3703r+yV5scPzZnEFkqOt3snsIzDUKv8=", + "login": { + "uri": null, + "username": "2./yXF39ra7G1lu1+bi6YpMg==|7mFeZwcbWq5ZxTSywQx88A==|SkefRdevf6PMxJ73nyfQsRgPwmebcZOxBc3L2dCnanA=" + }, + "name": "2.lSAI94z++lxjXV7F60wD8A==|c02oRIWPKahtdY0/fRUUaWmEr5AvLGrycczUq66jg+0=|Oq9Qhqd1rFqD+hU+O+pkx94PgoJMfJf20mBHVY7DReQ=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:42:54.536333Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, + { + "attachments": null, + "card": null, + "collectionIds": [], + "creationDate": "2024-10-02T07:42:36.834042Z", + "data": { + "fields": [], + "name": "2.b17ROLQsbMRSTrytcX5KSQ==|gEPPxcj3aUUYuK0PU3wjYlvrr+rvSbZf31JIkKJ6lrU=|XiUCDVYvRStdelDdfxe0eKvQE1ind0c+ABk/1cmaync=", + "notes": null, + "passwordHistory": [], + "uri": null, + "username": "2.VZy6ct00c8F40bBg5FhbsQ==|n+Lktw7gvd0Xr2JHpIIXGw==|HbbKTu0Ipvp+MN41t2PcdL73iWhLx0T7Tiu9piz1BXM=" + }, + "deletedDate": null, + "edit": true, + "favorite": false, + "fields": [], + "folderId": null, + "id": "9e51deed-db2f-4435-9b2e-ceed489d98f1", + "identity": null, + "key": "2.8cSTghkv0MsInRBfYs8Irg==|rFmXUMalI9nENKLQOwrI4ixcdqeAU7/KjZa0Ib+a0G5eGARNWPQ06C1RrA5Ao4rBw/Sy5hIteEAj3xXi6rSGzG5gON6oj5W1sm/OFnLJAYQ=|U+PgB4Tt1b+VWpI7kvDUz3p8KJPNuH6TV6/o9iNNtOw=", + "login": { + "uri": null, + "username": "2.VZy6ct00c8F40bBg5FhbsQ==|n+Lktw7gvd0Xr2JHpIIXGw==|HbbKTu0Ipvp+MN41t2PcdL73iWhLx0T7Tiu9piz1BXM=" + }, + "name": "2.b17ROLQsbMRSTrytcX5KSQ==|gEPPxcj3aUUYuK0PU3wjYlvrr+rvSbZf31JIkKJ6lrU=|XiUCDVYvRStdelDdfxe0eKvQE1ind0c+ABk/1cmaync=", + "notes": null, + "object": "cipherDetails", + "organizationId": null, + "organizationUseTotp": true, + "passwordHistory": [], + "reprompt": 0, + "revisionDate": "2024-10-02T07:42:36.834178Z", + "secureNote": null, + "type": 1, + "viewPassword": true + }, { "attachments": null, "card": null, diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_accounts_api-key.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_accounts_api-key.json new file mode 100644 index 0000000..e191c48 --- /dev/null +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_accounts_api-key.json @@ -0,0 +1,5 @@ +{ + "apiKey": "oQAvXGx5h3iw0wzzgRwySsGxn3PvvA", + "object": "apiKey", + "revisionDate": "2024-10-02T07:42:36.834275Z" +} \ No newline at end of file diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json index fda609c..d5d2201 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_api_ciphers.json @@ -2,35 +2,35 @@ "attachments": null, "card": null, "collectionIds": [], - "creationDate": "2024-10-02T07:23:54.690520Z", + "creationDate": "2024-10-02T07:42:54.536202Z", "data": { "fields": [], - "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "name": "2.lSAI94z++lxjXV7F60wD8A==|c02oRIWPKahtdY0/fRUUaWmEr5AvLGrycczUq66jg+0=|Oq9Qhqd1rFqD+hU+O+pkx94PgoJMfJf20mBHVY7DReQ=", "notes": null, "passwordHistory": [], "uri": null, - "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + "username": "2./yXF39ra7G1lu1+bi6YpMg==|7mFeZwcbWq5ZxTSywQx88A==|SkefRdevf6PMxJ73nyfQsRgPwmebcZOxBc3L2dCnanA=" }, "deletedDate": null, "edit": true, "favorite": false, "fields": [], "folderId": null, - "id": "30b00bfa-a32f-466a-9f23-dbc312455790", + "id": "8c071b82-5c79-47b5-8153-b37186daa5a2", "identity": null, - "key": "2.EFS7b18DYHnPgrK8tI0crw==|Ce+Dek2JYNCk05ijSYm78WS0+Y8odUeNDQsrAnkXllMAc4NG1FfCOhcfT2CHBlQD/YudriUvyhrTvWI/5GQIu9sCHRhEUYQE7o9yGOh/VmQ=|jescgRjRQqz+K6OSlVgNqjTJ6go3khELIm+TKfxE4gQ=", + "key": "2.H/woeJP3IG0/0MUun7vcUQ==|661oI8gy9efZtIHvXYhNwmr3fz0gwLm4LZwMsJUc1Ek+Ooq7wKfc/yTg+TLDY6ScDebhxDD6SAlRbgoBTbcTiF5CYB8ax2wUmNBpSPKYEoY=|aHEWPgao+Wo3703r+yV5scPzZnEFkqOt3snsIzDUKv8=", "login": { "uri": null, - "username": "2.C5tIDHGKYVFELsvnp9Gs4Q==|AjbBGTEPEzF7p3TDiaDihA==|NZZksTRi8OU2QtqaTx9RNnGUfa7tOb3N/i2rs08EWmU=" + "username": "2./yXF39ra7G1lu1+bi6YpMg==|7mFeZwcbWq5ZxTSywQx88A==|SkefRdevf6PMxJ73nyfQsRgPwmebcZOxBc3L2dCnanA=" }, - "name": "2.80lmt4GKwJjYlPijpkJOOw==|l0q9zQIDd6OJ5vcYnAeRDP3cFbQn9eOvE23nIJW+pJ0=|AT2gSy0ULDxad9nO5NfEYVacnFd5d1M3AYd3rT6PPX0=", + "name": "2.lSAI94z++lxjXV7F60wD8A==|c02oRIWPKahtdY0/fRUUaWmEr5AvLGrycczUq66jg+0=|Oq9Qhqd1rFqD+hU+O+pkx94PgoJMfJf20mBHVY7DReQ=", "notes": null, "object": "cipherDetails", "organizationId": null, "organizationUseTotp": true, "passwordHistory": [], "reprompt": 0, - "revisionDate": "2024-10-02T07:23:54.690612Z", + "revisionDate": "2024-10-02T07:42:54.536333Z", "secureNote": null, "type": 1, "viewPassword": true diff --git a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json index 469ed03..fe82f6b 100644 --- a/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json +++ b/internal/bitwarden/embedded/fixtures/test-kdf1_POST_identity_connect_token.json @@ -1,23 +1,14 @@ { - "ForcePasswordReset": false, "Kdf": 1, "KdfIterations": 3, "KdfMemory": 64, "KdfParallelism": 4, "Key": "2.Q+HxT8fkXKmM+irKC+1D6g==|hxmjLJ2RZUPM2uWk0gmPmNe0/OQrCbB49hKUIoqvXWbUaxricj62fATs81UZaKQoC5Re1LPyFsioRImDl1L+sv+EcBEhOx/0wqZ+JPNxXms=|t0G4kLfldPtNCg3wzXU81olAxgbe6sZHAMlQkjjJLck=", - "MasterPasswordPolicy": { - "object": "masterPasswordPolicy" - }, "PrivateKey": "2.fRqWht1SVjfmdTOYbLxbvw==|6nMLdGVZmXlnSjmDyJC94ljd/OYtCTflhVew0+uB4smS2YfFdmkfely/ZMU5UyDyuTCMp5ynw0ERTm3whVmwNGZkYHYT1iuU8I+N5zSQyuNPqnTREGFVslwcMSqkgINYUNoTnJYr/YkLjqzBLt4R5AvFY9Pxq20c+u+3obGcXVW2I11cxF47HVQde9pks72EvOw8KAQs6nQxx8CS/hWLmpZCh/f9yZ0PtNoeik+NxsnSI9veaLvr9yUwqWyhpF1+EI+PMpYZzUopyue8c0aihEUe5Pthz5z1KU+JXMWAAvtg/6eYFi8fQqT8Y6BOZh07makHPYIePQ2O/vgAETldiSlWwmjczZCQ5OXE4wromnzxKBYu1/K2uFUuQ0CD+xsleZImAyYR1W2zVslLFb/ILUX0RSKuqA2MlZizRldTY4nZ7quOWfHP0YD6iRK3oGFf7FfYPAPlcPOPDKl1tEhel3a3M8R0mkyb2e2S6IoW0hfYE4V4J0+VEmdNu7LQqFleqpEPl7icG0Z0EpP3KIJ4OcnO3gbUyo83MOyq4TQMIl46BQt42R4NcoA4hedV/YblUwnri58ugKfURH4+iSjv/r+F2uoSzJu2vdVHka3lF30bwhemyEUhsOZtHaEXpasKHesMknTv4/e+FhAdE9hjplWQyXO7rATXH6F0nEbyCDfOkghZAiAboTjBcE1FoqXBdCSkn4uVzmeWIGJp7izqzM/8zLK2VPUAMtxJGh9+rcv27bLYsbHfcnvEhCyXEsxa0b3DSGijyeSQC2yBNqJen9/SHbsCGNDOLNNyzYUzfIepQ52Oy2LgJEZ57ODTUybPfX4tyW8b+NriSzkUsx9Lp6hh/UaF6f+hBcQ7/dWVoHTJFyUHB1eni0PfFot0dXusg4n7usaG4e4ZSDQprgPHCyg+c3IxauHQmh9/oq1C4/5KuXIB/vOtMq98xjwnZTRdiJxOS82UyqpnwYcGQ9W2RIqKt1GXo/R5rgPXXtgmssqClu7QKI4sHA5lzTs1ef5BHFW1zAYPmsFvovTdX8ckrSdAoeQHJlIb4WyCNB4swNhmMFeQpdgCAZsBAjr+GG6Ak0JxXa2eQBF3zs0f37ly0t3BV7cCuDYKKSol5q14zTQkSQNg+/7TmhtmJo9ducSNS8orQT5IYA+OJa28wGfXjKKaSu0WSH/Tr83984nOQfUdlUZ2rqiskzW7/KUK2nlUceBty+0npuvrzqKk4eDIlJvh6uqwbU0C6SU9MFa0u4nXzfDvDHOgzuz4mNyCYe9tWzU2qArH9dzYMdc1UVj8qlmrPm2WkuXeEEYO+4MBAEHIuQxs21EshpE+2kePRpE5XHn/NbuZhbZ3j7ZD8w7Pyp4PC+hVAg83P+fvWU5CRuA8Ee2wNE6TORtqjnzW40Uh4JcQCaGwOt7dnDVygOsD9NGQrcrY8rLnK1kFMLJmfJtJ8BAn4A18RscI8OuwBkpfoOe9QldDXYsSAJ40K/yE3Nk25Csb3sgoHttfy43CpIIYvNzrqajZA0IvP22eWiF/FeZKO7zm0Myw33ARyHFw2yiBLNys4xxVuL3YmpolHRzOaUqtWA3bNJTmKWiBXxlJvL8+OvbfY+TYXJdVBUVzaATG4CL546j5hduhZfDxJQk=|1kt/ukROVrAIqC47wt8TLQYVh9jeZaCUE3/hHo8hCNA=", "ResetMasterPassword": false, - "UserDecryptionOptions": { - "HasMasterPassword": true, - "Object": "userDecryptionOptions" - }, - "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTM4MzQsImV4cCI6MTcyNzg2MTAzNCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6IjNmMGFiZjE3LWU3NzktNDMxMi1hM2RkLTljNjI2NmU5NWE5ZSIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjFAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMUBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJlOTY4YmJkMS05ZjY1LTQ2ZWYtYjE0ZS0wZDU1N2IzYjNiMWEiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhbXIiOlsiQXBwbGljYXRpb24iXX0.gbUXx7PzaRxB6DkMwHiVWHpFw_RC2Ztow3FpKct1mXI1gc3drMWqA8sQJtLu2wnslaD2pTYECcBejLFpgU2z4Z-homCbWxL9kr5O_3GkR_4RId9iVVY2P-TY-wX4GRY7IpQCPzGLUSL1cqSjlLx4cLIr6nmEiySQj2kvnR7ce3xqcb0rMeZMm72lC9UySP_VdlYE6nYEvNGVhstLfLSx44SBIhRzSGXYtezgyE-RBEcH1uv8WzUimfnhb_KoyAmxu9RaYffzFF-J6PFHswQt7tbbl5CYK_jpNvptaBBcyesuM_QpwuJNAyDovncDgHfFwMzNpuwW86i-wfEpWsnoNQ", + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE3Mjc4NTQ5NzQsImV4cCI6MTcyNzg2MjE3NCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdHxsb2dpbiIsInN1YiI6IjNmMGFiZjE3LWU3NzktNDMxMi1hM2RkLTljNjI2NmU5NWE5ZSIsInByZW1pdW0iOnRydWUsIm5hbWUiOiJ0ZXN0LWtkZjFAbGF2ZXJzZS5uZXQiLCJlbWFpbCI6InRlc3Qta2RmMUBsYXZlcnNlLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJlOTY4YmJkMS05ZjY1LTQ2ZWYtYjE0ZS0wZDU1N2IzYjNiMWEiLCJkZXZpY2UiOiIiLCJzY29wZSI6WyJhcGkiXSwiYW1yIjpbIkFwcGxpY2F0aW9uIl19.M4v3fwEttaX3HKV0AihjN5CfjdetaYFLrxQEgTkMEcEJsxJzIAIqzLqOttRI2GKqHdE8Bm8uyIXIppFQ0tPZ1A7l-pqLv6otm30xf9SAII5NfKDkLHWtRbZN5TSatPqlT44TSkUc0oVcEmYVPToWbaWOfs2u_-7d6y2QzMH8gmMtCoDM4X6mW_aY00I88iPrPzfoCCjUyFnvE8l6Q0Ni00MUWuVbGZOjWMPwLxjDaXRJKjxKRhFUKYiqDodaX_M11xoElqOsPYKXvwzqOMaIxhY52b5suxnRneLdbruuKEKyZisg7dELn3EBhPCWBwsLKSyDEC63JrX8DiL1Lypyfg", "expires_in": 7200, - "refresh_token": "jRlQnvOEIPacYzAFp5gmFEDVfBFE0gqYpdgok-PZtS1Vs5JNIf84KCKrAOi-SUtwL-snjCRnnychciR2k3C3Ng==", - "scope": "api offline_access", + "scope": "api", "token_type": "Bearer", "unofficialServer": true } \ No newline at end of file diff --git a/internal/bitwarden/embedded/vault_webapi.go b/internal/bitwarden/embedded/vault_webapi.go index c6d1116..7ea4ef6 100644 --- a/internal/bitwarden/embedded/vault_webapi.go +++ b/internal/bitwarden/embedded/vault_webapi.go @@ -25,6 +25,7 @@ type WebAPIVault interface { DeleteAttachment(ctx context.Context, itemId, attachmentId string) error DeleteObject(ctx context.Context, obj models.Object) error EditObject(ctx context.Context, obj models.Object) (*models.Object, error) + GetAPIKey(ctx context.Context, username, password string) (*models.ApiKey, error) GetAttachment(ctx context.Context, itemId, attachmentId string) ([]byte, error) LoginWithAPIKey(ctx context.Context, password, clientId, clientSecret string) error LoginWithPassword(ctx context.Context, username, password string) error @@ -416,6 +417,20 @@ func (v *webAPIVault) EditObject(ctx context.Context, obj models.Object) (*model return resObj, nil } +func (v *webAPIVault) GetAPIKey(ctx context.Context, username, password string) (*models.ApiKey, error) { + resp, err := v.client.GetAPIKey(ctx, username, password, v.loginAccount.KdfConfig) + if err != nil { + return nil, fmt.Errorf("error getting API key: %w", err) + } + + apiKey := &models.ApiKey{ + ClientID: fmt.Sprintf("user.%s", v.loginAccount.AccountUUID), + ClientSecret: resp.ApiKey, + } + + return apiKey, nil +} + func (v *webAPIVault) GetAttachment(ctx context.Context, itemId, attachmentId string) ([]byte, error) { if v.locked { return nil, models.ErrVaultLocked diff --git a/internal/bitwarden/embedded/vault_webapi_test.go b/internal/bitwarden/embedded/vault_webapi_test.go index 4012729..9f7752a 100644 --- a/internal/bitwarden/embedded/vault_webapi_test.go +++ b/internal/bitwarden/embedded/vault_webapi_test.go @@ -29,6 +29,24 @@ func TestLoginAsPasswordLoadsAccountInformationForPbkdf2(t *testing.T) { assert.Equal(t, fixtures.Pdkdf2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) } +func TestLoginAsAPILoadsAccountInformationForPbkdf2(t *testing.T) { + vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Pdkdf2Mocks)) + defer reset() + + ctx := context.Background() + err := vault.LoginWithAPIKey(ctx, fixtures.TestPassword, "user.aaf15bd1-4f51-4ba0-ade8-9dc2ec0fd2c3", "ZTXHHyPY6bNlNq1diDA2nM1GROboP3") + if err != nil { + t.Fatalf("vault unlock failed: %v", err) + } + + assert.Equal(t, "API", vault.loginAccount.VaultFormat) + assert.Equal(t, fixtures.Pdkdf2Email, vault.loginAccount.Email) + assert.Equal(t, models.KdfTypePBKDF2_SHA256, vault.loginAccount.KdfConfig.KdfType) + assert.Equal(t, 600000, vault.loginAccount.KdfConfig.KdfIterations) + assert.Equal(t, fixtures.Pdkdf2ProtectedRSAPrivateKey, vault.loginAccount.ProtectedRSAPrivateKey) + assert.Equal(t, fixtures.Pdkdf2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) +} + func TestLoginAsPasswordLoadsAccountInformationForArgon2(t *testing.T) { vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Argon2Mocks)) defer reset() @@ -47,6 +65,24 @@ func TestLoginAsPasswordLoadsAccountInformationForArgon2(t *testing.T) { assert.Equal(t, fixtures.Argon2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) } +func TestLoginAsAPILoadsAccountInformationForArgon2(t *testing.T) { + vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Argon2Mocks)) + defer reset() + + ctx := context.Background() + err := vault.LoginWithAPIKey(ctx, fixtures.TestPassword, "user.3f0abf17-e779-4312-a3dd-9c6266e95a9e", "oQAvXGx5h3iw0wzzgRwySsGxn3PvvA") + if err != nil { + t.Fatalf("vault unlock failed: %v", err) + } + + assert.Equal(t, "API", vault.loginAccount.VaultFormat) + assert.Equal(t, fixtures.Argon2Email, vault.loginAccount.Email) + assert.Equal(t, models.KdfTypeArgon2, vault.loginAccount.KdfConfig.KdfType) + assert.Equal(t, 3, vault.loginAccount.KdfConfig.KdfIterations) + assert.Equal(t, fixtures.Argon2ProtectedRSAPrivateKey, vault.loginAccount.ProtectedRSAPrivateKey) + assert.Equal(t, fixtures.Argon2ProtectedSymmetricKey, vault.loginAccount.ProtectedSymmetricKey) +} + func TestObjectCreation(t *testing.T) { vault, reset := newMockedWebAPIVault(fixtures.MockedClient(t, fixtures.Pdkdf2Mocks)) defer reset() diff --git a/internal/bitwarden/models/models.go b/internal/bitwarden/models/models.go index 63a1ff7..1fa6bd2 100644 --- a/internal/bitwarden/models/models.go +++ b/internal/bitwarden/models/models.go @@ -58,6 +58,7 @@ const ( ObjectTypeProfileOrganization ObjectType = "profileOrganization" // organization under profile ObjectCipherDetails ObjectType = "cipherDetails" // when creating attachment data ObjectAttachmentFileUpload ObjectType = "attachment-fileUpload" // when creating attachment data + ObjectApiKey ObjectType = "api-key" ) const ( @@ -95,6 +96,11 @@ type SecureNote struct { Type int `json:"type,omitempty"` } +type ApiKey struct { + ClientID string + ClientSecret string +} + type Object struct { Attachments []Attachment `json:"attachments,omitempty"` Card []byte `json:"-"` diff --git a/internal/bitwarden/webapi/client.go b/internal/bitwarden/webapi/client.go index 2286bda..74774e7 100644 --- a/internal/bitwarden/webapi/client.go +++ b/internal/bitwarden/webapi/client.go @@ -37,6 +37,7 @@ type Client interface { EditFolder(ctx context.Context, obj Folder) (*Folder, error) EditObject(context.Context, models.Object) (*models.Object, error) EditOrgCollection(ctx context.Context, orgId, objId string, obj OrganizationCreationRequest) (*Collection, error) + GetAPIKey(ctx context.Context, username, password string, kdfConfig models.KdfConfiguration) (*ApiKey, error) GetCollections(ctx context.Context, orgID string) ([]CollectionResponseItem, error) GetContentFromURL(ctx context.Context, url string) ([]byte, error) GetObjectAttachment(ctx context.Context, itemId, attachmentId string) (*models.Attachment, error) @@ -243,6 +244,26 @@ func (c *client) GetContentFromURL(ctx context.Context, url string) ([]byte, err return []byte(*resp), err } +func (c *client) GetAPIKey(ctx context.Context, username, password string, kdfConfig models.KdfConfiguration) (*ApiKey, error) { + type ApiKeyRequest struct { + MasterPasswordHash string `json:"masterPasswordHash"` + } + + preloginKey, err := keybuilder.BuildPreloginKey(password, username, kdfConfig) + if err != nil { + return nil, fmt.Errorf("error building prelogin key: %w", err) + } + + hashedPassword := crypto.HashPassword(password, *preloginKey, false) + obj := ApiKeyRequest{MasterPasswordHash: hashedPassword} + httpReq, err := c.prepareRequest(ctx, "POST", fmt.Sprintf("%s/api/accounts/api-key", c.serverURL), obj) + if err != nil { + return nil, fmt.Errorf("error preparing api key retrieval request: %w", err) + } + + return doRequest[ApiKey](ctx, c.httpClient, httpReq) +} + func (c *client) GetCollections(ctx context.Context, orgID string) ([]CollectionResponseItem, error) { httpReq, err := c.prepareRequest(ctx, "GET", fmt.Sprintf("%s/api/organizations/%s/collections", c.serverURL, orgID), nil) if err != nil { diff --git a/internal/bitwarden/webapi/models.go b/internal/bitwarden/webapi/models.go index 1d72a2a..23691b1 100644 --- a/internal/bitwarden/webapi/models.go +++ b/internal/bitwarden/webapi/models.go @@ -130,6 +130,12 @@ type SyncResponse struct { Profile Profile `json:"profile"` } +type ApiKey struct { + ApiKey string `json:"apiKey"` + Object models.ObjectType `json:"object"` + RevisionDate *time.Time `json:"revisionDate"` +} + type Folder struct { Id string `json:"id"` Name string `json:"name"`