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

Implement KMS AWS master key loading #552

Merged
merged 6 commits into from Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion cmd/acra-server/acra-server.go
Expand Up @@ -37,6 +37,7 @@ import (
"errors"
"flag"
"fmt"
"github.com/cossacklabs/acra/keystore/keyloader/kms"
"net/http"
_ "net/http/pprof"
"os"
Expand Down Expand Up @@ -181,6 +182,7 @@ func realMain() error {
enableAuditLog := flag.Bool("audit_log_enable", false, "Enable audit log functionality")

hashicorp.RegisterVaultCLIParameters()
kms.RegisterCLIParameters()
cmd.RegisterTracingCmdParameters()
cmd.RegisterJaegerCmdParameters()
logging.RegisterCLIArgs()
Expand Down Expand Up @@ -287,7 +289,7 @@ func realMain() error {
serverConfig.SetServiceName(ServiceName)
serverConfig.SetConfigPath(cmd.ConfigPath(DefaultConfigPath))

keyLoader, err := keyloader.GetInitializedMasterKeyLoader(hashicorp.GetVaultCLIParameters())
keyLoader, err := keyloader.GetInitializedMasterKeyLoader(hashicorp.GetVaultCLIParameters(), kms.GetCLIParameters())
if err != nil {
log.WithError(err).Errorln("Can't initialize ACRA_MASTER_KEY loader")
return err
Expand Down
6 changes: 6 additions & 0 deletions configs/acra-server.yaml
Expand Up @@ -83,6 +83,9 @@ keystore_cache_on_start_enable: true
# Maximum number of keys stored in in-memory LRU cache in encrypted form. 0 - no limits, -1 - turn off cache. Default is 1000
keystore_cache_size: 1000

# KMS credentials JSON file path
kms_credentials_path:

# Log to stderr if true
log_to_console: true

Expand All @@ -92,6 +95,9 @@ log_to_file:
# Logging format: plaintext, json or CEF
logging_format: plaintext

# KMS Key identifier in Tink's format
master_key_encryption_key_uri:

# Handle MySQL connections
mysql_enable: false

Expand Down
4 changes: 4 additions & 0 deletions go.mod
Expand Up @@ -4,6 +4,10 @@ go 1.14

require (
contrib.go.opencensus.io/exporter/jaeger v0.2.1
github.com/aws/aws-sdk-go-v2 v1.16.6
github.com/aws/aws-sdk-go-v2/config v1.15.12
github.com/aws/aws-sdk-go-v2/credentials v1.12.7
github.com/aws/aws-sdk-go-v2/service/kms v1.17.4
github.com/cossacklabs/themis/gothemis v0.14.0
github.com/gin-gonic/gin v1.7.2
github.com/go-redis/redis/v7 v7.0.1
Expand Down
29 changes: 28 additions & 1 deletion go.sum
Expand Up @@ -63,6 +63,30 @@ github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6l
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.16.6 h1:kzafGZYwkwVgLZ2zEX7P+vTwLli6uIMXF8aGjunN6UI=
github.com/aws/aws-sdk-go-v2 v1.16.6/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
github.com/aws/aws-sdk-go-v2/config v1.15.12 h1:D4mdf0cOSmZRgJe0DDOd1Qm6tkwHJ7r5i1lz0asa+AA=
github.com/aws/aws-sdk-go-v2/config v1.15.12/go.mod h1:oxRNnH11J580bxDEXyfTqfB3Auo2fxzhV052LD4HnyA=
github.com/aws/aws-sdk-go-v2/credentials v1.12.7 h1:e2DcCR0gP+T2zVj5eQPMQoRdxo+vd2p9BkpJ72BdyzA=
github.com/aws/aws-sdk-go-v2/credentials v1.12.7/go.mod h1:8b1nSHdDaKLho9VEK+K8WivifA/2K5pPm4sfI21NlQ8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.7 h1:8yi2ORCwXpXEPnj0vP3DjYhejwDQD/5klgBoxXcKOxY=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.7/go.mod h1:81k6q0UUZj6AdQZ1E/VQ27cLrTUpJGraZR6/hVHRxjE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.13 h1:WuQ1yGs3TMJgxpGVLspcsU/5q1omSA0SG6Cu0yZ4jkM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.13/go.mod h1:wLLesU+LdMZDM3U0PP9vZXJW39zmD/7L4nY2pSrYZ/g=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.7 h1:mCeDDYeDXp3loo/xKi7nkx34eeh7q3n1mUBtzptsj8c=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.7/go.mod h1:93Uot80ddyVzSl//xEJreNKMhxntr71WtR3v/A1cRYk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.14 h1:bJv4Y9QOiW0GZPStgLgpGrpdfRDSR3XM4V4M3YCQRZo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.14/go.mod h1:R1HF8ZDdcRFfAGF+13En4LSHi2IrrNuPQCaxgWCeGyY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.7 h1:M7/BzQNsu0XXiJRe3gUn8UA8tExF6kLMAfvo5PT/KJY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.7/go.mod h1:HvVdEh/x4jsPBsjNvDy+MH3CDCPy4gTZEzFe2r4uJY8=
github.com/aws/aws-sdk-go-v2/service/kms v1.17.4 h1:5NKN9OaBjXa6WiLaC7W2qRccJRE2D6rTzBRavswtae8=
github.com/aws/aws-sdk-go-v2/service/kms v1.17.4/go.mod h1:Q4PYKLlbDackWmZYMvdNLtGIY1I1k4xUpLQzzPXIx4c=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.10 h1:icon5WWg9Yg5nkB0pJF6bfKw6M0xozukeGKSNKtnqzw=
github.com/aws/aws-sdk-go-v2/service/sso v1.11.10/go.mod h1:UHxA35uPrCykRySBV5iSPZhZRlYnWSS2c/aaZVsoU94=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.8 h1:GLGfpqX+1bmjNvUJkwB1ZaDpNFXQwJ3z9RkQDA58OBY=
github.com/aws/aws-sdk-go-v2/service/sts v1.16.8/go.mod h1:50YdFq1WIuxA0AGrygvYGucnNYrG24WYzu5fNp7lMgY=
github.com/aws/smithy-go v1.12.0 h1:gXpeZel/jPoWQ7OEmLIgCUnhkFftqNfwWUwAHSlp1v0=
github.com/aws/smithy-go v1.12.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -233,8 +257,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand Down Expand Up @@ -383,6 +408,8 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
Expand Down
34 changes: 32 additions & 2 deletions keystore/keyloader/hashicorp/vault_cli.go
Expand Up @@ -2,7 +2,10 @@ package hashicorp

import (
"flag"

"github.com/cossacklabs/acra/keystore/keyloader"
"github.com/hashicorp/vault/api"
log "github.com/sirupsen/logrus"
)

const (
Expand Down Expand Up @@ -53,6 +56,33 @@ func (options *VaultCLIOptions) TLSConfig() *api.TLSConfig {
}

// GetVaultCLIParameters returns a copy of VaultCLIOptions parsed from the command line.
func GetVaultCLIParameters() VaultCLIOptions {
return vaultOptions
func GetVaultCLIParameters() *VaultCLIOptions {
return &vaultOptions
}

// New create MasterKeyLoader from VaultCLIOptions - implementation of keyloader.CliMasterKeyLoaderCreator interface
func (options VaultCLIOptions) New() (keyloader.MasterKeyLoader, error) {
if options.Address == "" {
return nil, nil
}

log.Infoln("Initializing connection to HashiCorp Vault for ACRA_MASTER_KEY loading")
vaultConfig := api.DefaultConfig()
vaultConfig.Address = options.Address

if options.EnableTLS {
log.Infoln("Configuring TLS connection to HashiCorp Vault")

if err := vaultConfig.ConfigureTLS(options.TLSConfig()); err != nil {
return nil, err
}
}

keyLoader, err := NewVaultLoader(vaultConfig, options.SecretsPath)
if err != nil {
log.WithError(err).Errorln("Can't initialize HashiCorp Vault loader")
return nil, err
}
log.Infoln("Initialized HashiCorp Vault ACRA_MASTER_KEY loader")
return keyLoader, nil
}
44 changes: 17 additions & 27 deletions keystore/keyloader/keyloader.go
Expand Up @@ -2,12 +2,14 @@ package keyloader

import (
"github.com/cossacklabs/acra/keystore"
"github.com/cossacklabs/acra/keystore/keyloader/hashicorp"

"github.com/hashicorp/vault/api"
log "github.com/sirupsen/logrus"
)

// CliMasterKeyLoaderCreator represent interface for all creators of MasterKeyLoader
type CliMasterKeyLoaderCreator interface {
New() (MasterKeyLoader, error)
}

// MasterKeyLoader interface for loading ACRA_MASTER_KEYs from different sources.
type MasterKeyLoader interface {
LoadMasterKey() (key []byte, err error)
Expand All @@ -16,42 +18,30 @@ type MasterKeyLoader interface {

// GetInitializedMasterKeyLoader returns initialized MasterKeyLoader interface depending on hashicorp vault params
// with predefined ACRA_MASTER_KEY env name
func GetInitializedMasterKeyLoader(vaultParams hashicorp.VaultCLIOptions) (keyLoader MasterKeyLoader, err error) {
return initMasterKeyLoaderWithEnv(keystore.AcraMasterKeyVarName, vaultParams)
func GetInitializedMasterKeyLoader(creators ...CliMasterKeyLoaderCreator) (keyLoader MasterKeyLoader, err error) {
return initMasterKeyLoaderWithEnv(keystore.AcraMasterKeyVarName, creators...)
}

// GetInitializedMasterKeyLoaderWithEnv returns initialized MasterKeyLoader interface depending on hashicorp vault params and env name
func GetInitializedMasterKeyLoaderWithEnv(envVarName string, vaultParams hashicorp.VaultCLIOptions) (keyLoader MasterKeyLoader, err error) {
return initMasterKeyLoaderWithEnv(envVarName, vaultParams)
func GetInitializedMasterKeyLoaderWithEnv(envVarName string, creators ...CliMasterKeyLoaderCreator) (keyLoader MasterKeyLoader, err error) {
return initMasterKeyLoaderWithEnv(envVarName, creators...)
}

// initMasterKeyLoaderWithEnv returns initialized MasterKeyLoader interface depending on incoming params,
// if HashiCorp Vault connection address is provided, hashicorp.VaultLoader will be initialized,
// via provided CliMasterKeyLoaderCreator
// otherwise EnvLoader with env name will be returned.
func initMasterKeyLoaderWithEnv(envVarName string, vaultParams hashicorp.VaultCLIOptions) (keyLoader MasterKeyLoader, err error) {
func initMasterKeyLoaderWithEnv(envVarName string, creators ...CliMasterKeyLoaderCreator) (keyLoader MasterKeyLoader, err error) {
log.Infof("Initializing ACRA_MASTER_KEY loader...")

if vaultParams.Address != "" {
log.Infoln("Initializing connection to HashiCorp Vault for ACRA_MASTER_KEY loading")

vaultConfig := api.DefaultConfig()
vaultConfig.Address = vaultParams.Address

if vaultParams.EnableTLS {
log.Infoln("Configuring TLS connection to HashiCorp Vault")

if err := vaultConfig.ConfigureTLS(vaultParams.TLSConfig()); err != nil {
return nil, err
}
for _, creator := range creators {
masterKeyLoader, err := creator.New()
if err != nil {
return nil, err
}

keyLoader, err = hashicorp.NewVaultLoader(vaultConfig, vaultParams.SecretsPath)
if err != nil {
log.WithError(err).Errorln("Can't initialize HashiCorp Vault loader")
return
if masterKeyLoader != nil {
return masterKeyLoader, nil
}
log.Infoln("Initialized HashiCorp Vault ACRA_MASTER_KEY loader")
return
}

log.Infof("Initialized default env %s loader", envVarName)
Expand Down
53 changes: 53 additions & 0 deletions keystore/keyloader/kms/kms_cli.go
@@ -0,0 +1,53 @@
package kms

import (
"flag"

"github.com/cossacklabs/acra/keystore/keyloader"
log "github.com/sirupsen/logrus"
)

const (
kmsKeyURIFlag = "master_key_encryption_key_uri"
)

// CLIOptions keep command-line options related to KMS ACRA_MASTER_KEY loading.
type CLIOptions struct {
KeyIdentifierURI string
CredentialsPath string
}

var cliOptions CLIOptions

// RegisterCLIParameters registers CLI parameters for reading ACRA_MASTER_KEY from KMS.
func RegisterCLIParameters() {
cliOptions.RegisterCLIParameters(flag.CommandLine, "", "")
}

// RegisterCLIParameters look up for vault_connection_api_string, if none exists, vault_connection_api_string and vault_secrets_path
// will be added to provided flags.
func (options *CLIOptions) RegisterCLIParameters(flags *flag.FlagSet, prefix string, description string) {
if description != "" {
description = " (" + description + ")"
}
if flags.Lookup(prefix+kmsKeyURIFlag) == nil {
flags.StringVar(&options.KeyIdentifierURI, prefix+kmsKeyURIFlag, "", "KMS Key identifier in Tink's format"+description)
// TODO: how to better provide an example of configuration files for different providers
flags.StringVar(&options.CredentialsPath, prefix+"kms_credentials_path", "", "KMS credentials JSON file path"+description)
}
}

// GetCLIParameters returns a copy of CLIOptions parsed from the command line.
func GetCLIParameters() *CLIOptions {
return &cliOptions
}

// New create MasterKeyLoader from kms.CLIOptions - implementation of keyloader.CliMasterKeyLoaderCreator interface
func (options *CLIOptions) New() (keyloader.MasterKeyLoader, error) {
if options.KeyIdentifierURI == "" {
return nil, nil
}

log.Infoln("Using KMS for ACRA_MASTER_KEY loading...")
return NewLoader(options.CredentialsPath, options.KeyIdentifierURI)
}
106 changes: 106 additions & 0 deletions keystore/keyloader/kms/kms_loader.go
@@ -0,0 +1,106 @@
package kms

import (
"crypto/subtle"

"github.com/cossacklabs/acra/keystore"
keystoreCE "github.com/cossacklabs/acra/keystore"
"github.com/cossacklabs/acra/keystore/kms"
"github.com/cossacklabs/acra/keystore/kms/aws"
keystoreV2CE "github.com/cossacklabs/acra/keystore/v2/keystore"
log "github.com/sirupsen/logrus"
)

// Loader is implementation of MasterKeyLoader for kms
type Loader struct {
keyID kms.KeyIdentifier
encryptor kms.Encryptor
}

// NewLoader create new kms MasterKeyLoader
func NewLoader(credentialPath, keyIdentifierURI string) (*Loader, error) {
keyID, err := kms.NewKeyIdentifierFromURI(keyIdentifierURI)
if err != nil {
return nil, err
}

var encryptor kms.Encryptor
switch keyID.Prefix() {
Copy link
Collaborator

@Lagovas Lagovas Jul 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, it push me to think about registries. what about to use here registries approach as we did it for CryptoHandlers? Turn implementation on with build tag and register it at start? for example:

type EncryptorFactoryMethod interface {
  New(credentialPath string) (kms.Encryptor, error)
}
// or type EncryptorFactoryMethod func(credentialPath string) (kms.Encryptor, error)
var lock = sync.Lock{}
var encryptors map[string]EncryptorFactoryMethod
RegisterEncryptor(encryptor EncryptorFactoryMethod){
  lock.Lock()
  encryptors[encryptor.ID()] = encryptor
  lock.Unlock()
}

Then we can use :

func NewLoader(credentialPath, keyIdentifierURI string) (*Loader, error) {
	keyID, err := kms.NewKeyIdentifierFromURI(keyIdentifierURI)
	if err != nil {
		return nil, err
	}
        encryptorFactory, ok := encryptors[keyID]
        if !ok {
            log.Errorln("Unknown key ID")
        }
        encryptor, err := encryptorFactory.New(credentialPath) // or encryptorFactory(credentialPath)
}

Then our AWS implementation should have:

func init(){
  kms.RegisterEncryptor(someFactoryFunction)
}

With such approach we can extend with enterprise KMS support.

Additionally, we can make default loader that do nothing with master key (current approach where env variable store result master key. this implementation will return master key as is in Encrypt/Decrypt methods) and registered by default and +1 with AWS. Then current loader will be consistent with new approach

And +1 pros for that it be able to cut AWS support and all dependencies via build tags even in CE version. If client doesn't need AWS KMS support, it can compile it with build tag that turns off it. Result binary size and amount of dependencies will be less.

case aws.KeyIdentifierPrefix:
encryptor, err = aws.NewEncryptor(credentialPath)
}
if err != nil {
log.WithError(err).Errorf("Failed to initialize %s MasterKeyLoader", encryptor.Source())
return nil, err
}

log.Infof("Initialized %s MasterKeyLoader", encryptor.Source())
return &Loader{
keyID: keyID,
encryptor: encryptor,
}, nil
}

// LoadMasterKey implementation kms MasterKeyLoader for loading AcraMasterKey for keystore v1
func (loader *Loader) LoadMasterKey() ([]byte, error) {
rawKey, err := loader.decryptWithKMSKey(loader.keyID)
if err != nil {
log.WithError(err).Warnf("Failed to decrypt ACRA_MASTER_KEY with KMS keyID %s", loader.keyID.ID())
return nil, err
}

if err := keystoreCE.ValidateMasterKey(rawKey); err != nil {
log.WithError(err).Warn("Decrypted key is invalid")
return nil, err
}

return rawKey, nil
}

// LoadMasterKeys implementation kms MasterKeyLoader for loading AcraMasterKey for keystore v2
func (loader *Loader) LoadMasterKeys() (encryption []byte, signature []byte, err error) {
rawKey, err := loader.decryptWithKMSKey(loader.keyID)
if err != nil {
log.WithError(err).Warnf("Failed to decrypt ACRA_MASTER_KEY with KMS keyID %s", loader.keyID.ID())
return nil, nil, err
}

keys := &keystoreV2CE.SerializedKeys{}
err = keys.Unmarshal(rawKey)
if err != nil {
log.WithError(err).Warn("Failed to parse KMS decrypted key as SerializedKeys")
return nil, nil, err
}

if subtle.ConstantTimeCompare(keys.Encryption, keys.Signature) == 1 {
log.Warn("ACRA_MASTER_KEYs must not be the same")
return nil, nil, keystoreV2CE.ErrEqualMasterKeys
}

err = keystoreCE.ValidateMasterKey(keys.Encryption)
if err != nil {
log.WithError(err).Warn("Invalid encryption key")
return nil, nil, err
}
err = keystoreCE.ValidateMasterKey(keys.Signature)
if err != nil {
log.WithError(err).Warn("Invalid signature key")
return nil, nil, err
}

return keys.Encryption, keys.Signature, nil
}

func (loader *Loader) decryptWithKMSKey(keyID kms.KeyIdentifier) ([]byte, error) {
cipherMasterKey, err := keystore.GetMasterKeyFromEnvironmentVariable(keystore.AcraMasterKeyVarName)
if err != nil {
return nil, err
}

masterKey, err := loader.encryptor.Decrypt(keyID.ID(), cipherMasterKey)
if err != nil {
return nil, err
}

return masterKey, nil
}