Skip to content

Commit

Permalink
level-up testing infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
maxlaverse committed Oct 2, 2024
1 parent 5a8fa6e commit 2a205ca
Show file tree
Hide file tree
Showing 19 changed files with 762 additions and 839 deletions.
115 changes: 115 additions & 0 deletions internal/bitwarden/embedded/fixtures/create_accounts_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
70 changes: 70 additions & 0 deletions internal/bitwarden/embedded/fixtures/disk_transport.go
Original file line number Diff line number Diff line change
@@ -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)
}
51 changes: 51 additions & 0 deletions internal/bitwarden/embedded/fixtures/mocked_client.go
Original file line number Diff line number Diff line change
@@ -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())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"_status": 0,
"avatarColor": null,
"culture": "en-US",
"email": "[email protected]",
"emailVerified": true,
"forcePasswordReset": false,
"id": "aaf15bd1-4f51-4ba0-ade8-9dc2ec0fd2c3",
"key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=",
"masterPasswordHint": null,
"name": "[email protected]",
"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
}
105 changes: 105 additions & 0 deletions internal/bitwarden/embedded/fixtures/test-kdf0_GET_api_sync.json
Original file line number Diff line number Diff line change
@@ -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": "[email protected]",
"emailVerified": true,
"forcePasswordReset": false,
"id": "aaf15bd1-4f51-4ba0-ade8-9dc2ec0fd2c3",
"key": "2.fl6CmmK/o/THYg8Y3Z5fJw==|sEjr1DMSe+Hgg7DRU8Z2wqZiZWIySrY63E8ISwQ7Q9vpxUPDQPifTW9oW0ZjcnKE4Xl4fxP89LO5xce+y+yR1yAQpnVcm2wMBx0OXM1xaAU=|9wNu2sNXt7ECSXCYsDL1ctWw02GGT1y7Pkx2NxIyD0A=",
"masterPasswordHint": null,
"name": "[email protected]",
"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
}
Loading

0 comments on commit 2a205ca

Please sign in to comment.