Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use kms per client #556

Merged
merged 14 commits into from
Aug 8, 2022
39 changes: 29 additions & 10 deletions cmd/acra-keymaker/acra-keymaker.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ func main() {
switch *keystoreVersion {
case "v1":
store = openKeyStoreV1(*outputDir, *outputPublicKey, keyLoader)
if kmsOptions := kms.GetCLIParameters(); kmsOptions.KMSType != "" {
keyManager, _ := kmsOptions.NewKeyManager()
store = baseKMS.NewKeyMakingWrapper(store, keyManager)
}

case "v2":
store = openKeyStoreV2(*outputDir, keyLoader)
case "":
Expand All @@ -209,6 +214,8 @@ func main() {
}

if *poisonRecord {
//TODO: ask if we want to create KMS key per each poison key (private and symmetric) or just one

// Generate poison record symmetric key
if err = store.GeneratePoisonSymmetricKey(); err != nil {
panic(err)
Expand Down Expand Up @@ -287,23 +294,35 @@ func main() {
}

func openKeyStoreV1(output, outputPublic string, loader keyloader.MasterKeyLoader) keystore.KeyMaking {
masterKey, err := loader.LoadMasterKey()
if err != nil {
log.WithError(err).Errorln("Cannot load master key")
os.Exit(1)
}
scellEncryptor, err := keystore.NewSCellKeyEncryptor(masterKey)
if err != nil {
log.WithError(err).Errorln("Can't init scell encryptor")
os.Exit(1)
var keyStoreEncryptor keystore.KeyEncryptor
if kmsOptions := kms.GetCLIParameters(); kmsOptions.KMSType != "" {
keyManager, err := kmsOptions.NewKeyManager()
if err != nil {
log.WithError(err).Errorln("Failed to initializer kms KeyManager")
os.Exit(1)
}

keyStoreEncryptor = baseKMS.NewKeyEncryptor(keyManager)
} else {
masterKey, err := loader.LoadMasterKey()
if err != nil {
log.WithError(err).Errorln("Cannot load master key")
os.Exit(1)
}
keyStoreEncryptor, err = keystore.NewSCellKeyEncryptor(masterKey)
if err != nil {
log.WithError(err).Errorln("Can't init scell encryptor")
os.Exit(1)
}
}

keyStore := filesystem.NewCustomFilesystemKeyStore()
if outputPublic != output {
keyStore.KeyDirectories(output, outputPublic)
} else {
keyStore.KeyDirectory(output)
}
keyStore.Encryptor(scellEncryptor)
keyStore.Encryptor(keyStoreEncryptor)
redis := cmd.GetRedisParameters()
if redis.KeysConfigured() {
keyStorage, err := filesystem.NewRedisStorage(redis.HostPort, redis.Password, redis.DBKeys, nil)
Expand Down
35 changes: 25 additions & 10 deletions cmd/acra-server/acra-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"errors"
"flag"
"fmt"
baseKMS "github.com/cossacklabs/acra/keystore/kms"
"net/http"
_ "net/http/pprof"
"os"
Expand Down Expand Up @@ -870,20 +871,34 @@ func waitReadPipe(timeoutDuration time.Duration) error {
}

func openKeyStoreV1(output string, cacheSize int, loader keyloader.MasterKeyLoader) (keystore.ServerKeyStore, error) {
masterKey, err := loader.LoadMasterKey()
if err != nil {
log.WithError(err).Errorln("Cannot load master key")
return nil, err
}
scellEncryptor, err := keystore.NewSCellKeyEncryptor(masterKey)
if err != nil {
log.WithError(err).Errorln("Can't init scell encryptor")
return nil, err
var keyStoreEncryptor keystore.KeyEncryptor
// TODO: consider creating new flag exactly for KMS keystore

if kmsOptions := kms.GetCLIParameters(); kmsOptions.KMSType != "" {
keyManager, err := kmsOptions.NewKeyManager()
if err != nil {
log.WithError(err).Errorln("Failed to initializer kms KeyManager")
return nil, err
}

keyStoreEncryptor = baseKMS.NewKeyEncryptor(keyManager)
} else {
masterKey, err := loader.LoadMasterKey()
if err != nil {
log.WithError(err).Errorln("Cannot load master key")
return nil, err
}
keyStoreEncryptor, err = keystore.NewSCellKeyEncryptor(masterKey)
if err != nil {
log.WithError(err).Errorln("Can't init scell encryptor")
return nil, err
}
}

keyStore := filesystem.NewCustomFilesystemKeyStore()
keyStore.KeyDirectory(output)
keyStore.CacheSize(cacheSize)
keyStore.Encryptor(scellEncryptor)
keyStore.Encryptor(keyStoreEncryptor)

redis := cmd.GetRedisParameters()
if redis.KeysConfigured() {
Expand Down
46 changes: 28 additions & 18 deletions keystore/filesystem/filesystem_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package filesystem

import (
"bytes"
"context"
"encoding/gob"
"path/filepath"
"strings"
Expand Down Expand Up @@ -82,57 +83,58 @@ func isPrivate(fname string) bool {
return true
}

func getIDFromFilename(fname string) []byte {
func getIDFromFilename(fname string) (keystore.KeyPurpose, []byte) {
if isHistoricalFilename(fname) {
fname = filepath.Dir(fname)
}
if fname == PoisonKeyFilename {
return []byte(fname)
return keystore.PurposePoisonRecordKeyPair, []byte(fname)
}
if fname == getSymmetricKeyName(PoisonKeyFilename) {
return []byte(fname[:len(fname)-len("_sym")])
return keystore.PurposePoisonRecordSymmetricKey, []byte(fname[:len(fname)-len("_sym")])
}
fname = filepath.Base(fname)
if strings.HasSuffix(fname, ".old") {
fname = fname[:len(fname)-len(".old")]
}
if strings.HasSuffix(fname, "_hmac") {
return []byte(fname[:len(fname)-len("_hmac")])
return keystore.PurposeSearchHMAC, []byte(fname[:len(fname)-len("_hmac")])
}
if strings.HasSuffix(fname, "_server") {
return []byte(fname[:len(fname)-len("_server")])
return keystore.PurposeLegacy, []byte(fname[:len(fname)-len("_server")])
}
if strings.HasSuffix(fname, "_translator") {
return []byte(fname[:len(fname)-len("_translator")])
return keystore.PurposeLegacy, []byte(fname[:len(fname)-len("_translator")])
}
if strings.HasSuffix(fname, "_storage") {
return []byte(fname[:len(fname)-len("_storage")])
return keystore.PurposeStorageClientPrivateKey, []byte(fname[:len(fname)-len("_storage")])
}
if strings.HasSuffix(fname, "_storage_sym") {
return []byte(fname[:len(fname)-len("_storage_sym")])
return keystore.PurposeStorageClientSymmetricKey, []byte(fname[:len(fname)-len("_storage_sym")])
}
if strings.HasSuffix(fname, "_zone") {
return []byte(fname[:len(fname)-len("_zone")])
return keystore.PurposeStorageZonePrivateKey, []byte(fname[:len(fname)-len("_zone")])
}
if strings.HasSuffix(fname, "_zone_sym") {
return []byte(fname[:len(fname)-len("_zone_sym")])
return keystore.PurposeStorageZoneSymmetricKey, []byte(fname[:len(fname)-len("_zone_sym")])
}
if strings.HasSuffix(fname, "_sym") {
return []byte(fname[:len(fname)-len("_sym")])
//TODO: what it the sym key here?
Zhaars marked this conversation as resolved.
Show resolved Hide resolved
return "", []byte(fname[:len(fname)-len("_sym")])
}

return []byte(fname)
return "", []byte(fname)
Zhaars marked this conversation as resolved.
Show resolved Hide resolved
}

type dummyEncryptor struct{}

// Encrypt return data as is, used for tests
func (d dummyEncryptor) Encrypt(key, context []byte) ([]byte, error) {
func (d dummyEncryptor) Encrypt(ctx context.Context, key []byte, keyContext keystore.KeyContext) ([]byte, error) {
return key, nil
}

// Decrypt return data as is, used for tests
func (d dummyEncryptor) Decrypt(key, context []byte) ([]byte, error) {
func (d dummyEncryptor) Decrypt(ctx context.Context, key []byte, keyContext keystore.KeyContext) ([]byte, error) {
return key, nil
}

Expand All @@ -151,7 +153,10 @@ func readFilesAsKeys(files []string, basePath string, encryptor keystore2.KeyEnc
// remove absolute first part, leave only relative to path
relativeName := strings.Replace(f, basePath+"/", "", -1)
if isPrivate(relativeName) {
content, err = encryptor.Decrypt(content, getIDFromFilename(relativeName))
purpose, id := getIDFromFilename(relativeName)

keyContext := keystore.NewKeyContext(purpose).WithContext(id).WithZoneID(id).WithClientID(id)
Zhaars marked this conversation as resolved.
Show resolved Hide resolved
content, err = encryptor.Decrypt(context.Background(), content, *keyContext)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -210,7 +215,8 @@ func (store *KeyBackuper) Export() (*keystore.KeysBackup, error) {
if err != nil {
return nil, err
}
encryptedKeys, err := encryptor.Encrypt(buf.Bytes(), nil)

encryptedKeys, err := encryptor.Encrypt(context.Background(), buf.Bytes(), *keystore.NewEmptyKeyContext())
if err != nil {
return nil, err
}
Expand All @@ -223,7 +229,8 @@ func (store *KeyBackuper) Import(backup *keystore.KeysBackup) error {
if err != nil {
return err
}
decryptedData, err := decryptor.Decrypt(backup.Keys, nil)

decryptedData, err := decryptor.Decrypt(context.Background(), backup.Keys, *keystore.NewEmptyKeyContext())
if err != nil {
return err
}
Expand All @@ -240,7 +247,10 @@ func (store *KeyBackuper) Import(backup *keystore.KeysBackup) error {
fullName := filepath.Join(store.privateFolder, key.Name)
content := key.Content
if isPrivateKey {
content, err = store.currentDecryptor.Encrypt(key.Content, getIDFromFilename(key.Name))

purpose, id := getIDFromFilename(key.Name)
keyContext := keystore.NewKeyContext(purpose).WithContext(id).WithClientID(id).WithZoneID(id)
content, err = store.currentDecryptor.Encrypt(context.Background(), key.Content, *keyContext)
// anyway fill with zeros
utils.ZeroizeBytes(key.Content)
if err != nil {
Expand Down
Loading