goldwarden/agent/bitwarden/sync.go

116 lines
2.8 KiB
Go
Raw Normal View History

2023-07-17 04:23:26 +03:00
package bitwarden
import (
"context"
2023-07-17 07:00:26 +03:00
"encoding/json"
2023-07-17 04:23:26 +03:00
"fmt"
2023-07-17 07:00:26 +03:00
"os"
"time"
2023-07-17 04:23:26 +03:00
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/bitwarden/models"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/notify"
2023-07-17 04:23:26 +03:00
"github.com/quexten/goldwarden/agent/vault"
2023-08-21 19:37:34 +03:00
"github.com/quexten/goldwarden/logging"
2023-07-17 04:23:26 +03:00
)
2023-08-21 19:37:34 +03:00
var log = logging.GetLogger("Goldwarden", "Bitwarden API")
2023-07-17 04:23:26 +03:00
2023-07-17 07:00:26 +03:00
const path = "/.cache/goldwarden-vault.json"
2023-07-17 04:23:26 +03:00
func Sync(ctx context.Context, config *config.Config) (models.SyncData, error) {
var sync models.SyncData
if err := authenticatedHTTPGet(ctx, config.ConfigFile.ApiUrl+"/sync", &sync); err != nil {
return models.SyncData{}, fmt.Errorf("could not sync: %v", err)
}
2023-07-17 07:00:26 +03:00
home, _ := os.UserHomeDir()
WriteVault(sync, home+path)
2023-07-17 04:23:26 +03:00
return sync, nil
}
2023-07-17 07:00:26 +03:00
func DoFullSync(ctx context.Context, vault *vault.Vault, config *config.Config, userSymmetricKey *crypto.SymmetricEncryptionKey, allowCache bool) error {
2023-07-17 04:23:26 +03:00
log.Info("Performing full sync...")
sync, err := Sync(ctx, config)
if err != nil {
2023-12-22 12:44:49 +03:00
log.Error("Could not sync: %v", err)
2024-01-19 07:14:25 +03:00
notify.Notify("Goldwarden", "Could not sync", "", 0, func() {})
2023-07-17 07:00:26 +03:00
if allowCache {
home, _ := os.UserHomeDir()
sync, err = ReadVault(home + path)
2023-12-22 14:01:21 +03:00
if err != nil {
return err
}
2023-07-17 07:00:26 +03:00
} else {
return err
}
2023-12-22 12:44:49 +03:00
} else {
log.Info("Sync successful, initializing keyring and vault...")
2023-07-17 04:23:26 +03:00
}
var orgKeys map[string]string = make(map[string]string)
2023-12-22 14:01:21 +03:00
log.Info("Reading %d org keys...", len(sync.Profile.Organizations))
for _, org := range sync.Profile.Organizations {
orgId := org.Id.String()
orgKeys[orgId] = org.Key
}
if userSymmetricKey != nil {
2023-12-22 12:44:49 +03:00
log.Info("Initializing keyring from user symmetric key...")
crypto.InitKeyringFromUserSymmetricKey(vault.Keyring, *userSymmetricKey, sync.Profile.PrivateKey, orgKeys)
2023-07-17 04:23:26 +03:00
}
2023-12-22 12:44:49 +03:00
log.Info("Clearing vault...")
2023-07-17 04:23:26 +03:00
vault.Clear()
2023-12-28 16:58:31 +03:00
vault.SetLastSynced(time.Now().Unix())
2023-12-22 12:44:49 +03:00
log.Info("Adding %d ciphers to vault...", len(sync.Ciphers))
2023-07-17 04:23:26 +03:00
for _, cipher := range sync.Ciphers {
switch cipher.Type {
case models.CipherLogin:
vault.AddOrUpdateLogin(cipher)
case models.CipherNote:
vault.AddOrUpdateSecureNote(cipher)
}
}
return nil
}
2023-07-17 07:00:26 +03:00
func WriteVault(data models.SyncData, path string) error {
dataJson, err := json.Marshal(data)
if err != nil {
return err
}
// write to disk
os.Remove(path)
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(dataJson)
if err != nil {
return err
}
return nil
}
func ReadVault(path string) (models.SyncData, error) {
file, err := os.Open(path)
if err != nil {
return models.SyncData{}, err
}
defer file.Close()
decoder := json.NewDecoder(file)
data := models.SyncData{}
err = decoder.Decode(&data)
if err != nil {
return models.SyncData{}, err
}
return data, nil
}