From 036ef9faec8d2a00fab15f437c9c973f151e67f9 Mon Sep 17 00:00:00 2001 From: Matheus Pimenta Date: Sat, 3 May 2025 13:07:20 +0100 Subject: [PATCH] Introduce EncryptContext and DecryptContext for AWS, Azure, GCP, PGP and HashiCorp Vault Signed-off-by: Matheus Pimenta --- azkv/keysource.go | 20 ++++++++++++++++-- gcpkms/keysource.go | 25 ++++++++++++++++------ gcpkms/keysource_test.go | 7 ++++--- hcvault/keysource.go | 20 ++++++++++++++++-- kms/keysource.go | 34 ++++++++++++++++++++++-------- kms/keysource_test.go | 8 +++---- pgp/keysource.go | 45 ++++++++++++++++++++++++++++++++-------- pgp/keysource_test.go | 21 ++++++++++--------- 8 files changed, 135 insertions(+), 45 deletions(-) diff --git a/azkv/keysource.go b/azkv/keysource.go index 28cb6ebde..b4eef54c6 100644 --- a/azkv/keysource.go +++ b/azkv/keysource.go @@ -120,7 +120,15 @@ func (t TokenCredential) ApplyToMasterKey(key *MasterKey) { // Encrypt takes a SOPS data key, encrypts it with Azure Key Vault, and stores // the result in the EncryptedKey field. +// +// Consider using EncryptContext instead. func (key *MasterKey) Encrypt(dataKey []byte) error { + return key.EncryptContext(context.Background(), dataKey) +} + +// EncryptContext takes a SOPS data key, encrypts it with Azure Key Vault, and stores +// the result in the EncryptedKey field. +func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error { token, err := key.getTokenCredential() if err != nil { log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Encryption failed") @@ -133,7 +141,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { return fmt.Errorf("failed to construct Azure Key Vault client to encrypt data: %w", err) } - resp, err := c.Encrypt(context.Background(), key.Name, key.Version, azkeys.KeyOperationParameters{ + resp, err := c.Encrypt(ctx, key.Name, key.Version, azkeys.KeyOperationParameters{ Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256), Value: dataKey, }, nil) @@ -169,7 +177,15 @@ func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error { // Decrypt decrypts the EncryptedKey field with Azure Key Vault and returns // the result. +// +// Consider using DecryptContext instead. func (key *MasterKey) Decrypt() ([]byte, error) { + return key.DecryptContext(context.Background()) +} + +// DecryptContext decrypts the EncryptedKey field with Azure Key Vault and returns +// the result. +func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) { token, err := key.getTokenCredential() if err != nil { log.WithFields(logrus.Fields{"key": key.Name, "version": key.Version}).Info("Decryption failed") @@ -188,7 +204,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, fmt.Errorf("failed to construct Azure Key Vault client to decrypt data: %w", err) } - resp, err := c.Decrypt(context.Background(), key.Name, key.Version, azkeys.KeyOperationParameters{ + resp, err := c.Decrypt(ctx, key.Name, key.Version, azkeys.KeyOperationParameters{ Algorithm: to.Ptr(azkeys.EncryptionAlgorithmRSAOAEP256), Value: rawEncryptedKey, }, nil) diff --git a/gcpkms/keysource.go b/gcpkms/keysource.go index 408a22de9..cc834b055 100644 --- a/gcpkms/keysource.go +++ b/gcpkms/keysource.go @@ -118,8 +118,16 @@ func (c CredentialJSON) ApplyToMasterKey(key *MasterKey) { // Encrypt takes a SOPS data key, encrypts it with GCP KMS, and stores the // result in the EncryptedKey field. +// +// Consider using EncryptContext instead. func (key *MasterKey) Encrypt(dataKey []byte) error { - service, err := key.newKMSClient() + return key.EncryptContext(context.Background(), dataKey) +} + +// EncryptContext takes a SOPS data key, encrypts it with GCP KMS, and stores the +// result in the EncryptedKey field. +func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error { + service, err := key.newKMSClient(ctx) if err != nil { log.WithField("resourceID", key.ResourceID).Info("Encryption failed") return fmt.Errorf("cannot create GCP KMS service: %w", err) @@ -134,7 +142,6 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { Name: key.ResourceID, Plaintext: dataKey, } - ctx := context.Background() resp, err := service.Encrypt(ctx, req) if err != nil { log.WithField("resourceID", key.ResourceID).Info("Encryption failed") @@ -169,8 +176,16 @@ func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error { // Decrypt decrypts the EncryptedKey field with GCP KMS and returns // the result. +// +// Consider using DecryptContext instead. func (key *MasterKey) Decrypt() ([]byte, error) { - service, err := key.newKMSClient() + return key.DecryptContext(context.Background()) +} + +// DecryptContext decrypts the EncryptedKey field with GCP KMS and returns +// the result. +func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) { + service, err := key.newKMSClient(ctx) if err != nil { log.WithField("resourceID", key.ResourceID).Info("Decryption failed") return nil, fmt.Errorf("cannot create GCP KMS service: %w", err) @@ -193,7 +208,6 @@ func (key *MasterKey) Decrypt() ([]byte, error) { Name: key.ResourceID, Ciphertext: decodedCipher, } - ctx := context.Background() resp, err := service.Decrypt(ctx, req) if err != nil { log.WithField("resourceID", key.ResourceID).Info("Decryption failed") @@ -232,7 +246,7 @@ func (key *MasterKey) TypeToIdentifier() string { // or credentialJSON, and/or grpcConn, falling back to environmental defaults. // It returns an error if the ResourceID is invalid, or if the setup of the // client fails. -func (key *MasterKey) newKMSClient() (*kms.KeyManagementClient, error) { +func (key *MasterKey) newKMSClient(ctx context.Context) (*kms.KeyManagementClient, error) { re := regexp.MustCompile(`^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$`) matches := re.FindStringSubmatch(key.ResourceID) if matches == nil { @@ -265,7 +279,6 @@ func (key *MasterKey) newKMSClient() (*kms.KeyManagementClient, error) { opts = append(opts, option.WithGRPCConn(key.grpcConn)) } - ctx := context.Background() client, err := kms.NewKeyManagementClient(ctx, opts...) if err != nil { return nil, err diff --git a/gcpkms/keysource_test.go b/gcpkms/keysource_test.go index c2442eeca..e0365de34 100644 --- a/gcpkms/keysource_test.go +++ b/gcpkms/keysource_test.go @@ -1,6 +1,7 @@ package gcpkms import ( + "context" "encoding/base64" "fmt" "net" @@ -155,7 +156,7 @@ func TestMasterKey_createCloudKMSService_withCredentialsFile(t *testing.T) { } for _, tt := range tests { - _, err := tt.key.newKMSClient() + _, err := tt.key.newKMSClient(context.Background()) if tt.errString != "" { assert.Error(t, err) assert.ErrorContains(t, err, tt.errString) @@ -172,7 +173,7 @@ func TestMasterKey_createCloudKMSService_withOauthToken(t *testing.T) { ResourceID: testResourceID, } - _, err := masterKey.newKMSClient() + _, err := masterKey.newKMSClient(context.Background()) assert.NoError(t, err) } @@ -182,7 +183,7 @@ func TestMasterKey_createCloudKMSService_withoutCredentials(t *testing.T) { ResourceID: testResourceID, } - _, err := masterKey.newKMSClient() + _, err := masterKey.newKMSClient(context.Background()) assert.Error(t, err) assert.ErrorContains(t, err, "credentials: could not find default credentials") diff --git a/hcvault/keysource.go b/hcvault/keysource.go index c120d9c99..2b1a9909f 100644 --- a/hcvault/keysource.go +++ b/hcvault/keysource.go @@ -2,6 +2,7 @@ package hcvault import ( "bytes" + "context" "encoding/base64" "errors" "fmt" @@ -130,7 +131,15 @@ func NewMasterKey(address, enginePath, keyName string) *MasterKey { // Encrypt takes a SOPS data key, encrypts it with Vault Transit, and stores // the result in the EncryptedKey field. +// +// Consider using EncryptContext instead. func (key *MasterKey) Encrypt(dataKey []byte) error { + return key.EncryptContext(context.Background(), dataKey) +} + +// EncryptContext takes a SOPS data key, encrypts it with Vault Transit, and stores +// the result in the EncryptedKey field. +func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error { fullPath := key.encryptPath() client, err := vaultClient(key.VaultAddress, key.token) @@ -139,7 +148,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { return err } - secret, err := client.Logical().Write(fullPath, encryptPayload(dataKey)) + secret, err := client.Logical().WriteWithContext(ctx, fullPath, encryptPayload(dataKey)) if err != nil { log.WithField("Path", fullPath).Info("Encryption failed") return fmt.Errorf("failed to encrypt sops data key to Vault transit backend '%s': %w", fullPath, err) @@ -175,7 +184,14 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { } // Decrypt decrypts the EncryptedKey field with Vault Transit and returns the result. +// +// Consider using DecryptContext instead. func (key *MasterKey) Decrypt() ([]byte, error) { + return key.DecryptContext(context.Background()) +} + +// DecryptContext decrypts the EncryptedKey field with Vault Transit and returns the result. +func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) { fullPath := key.decryptPath() client, err := vaultClient(key.VaultAddress, key.token) @@ -184,7 +200,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, err } - secret, err := client.Logical().Write(fullPath, decryptPayload(key.EncryptedKey)) + secret, err := client.Logical().WriteWithContext(ctx, fullPath, decryptPayload(key.EncryptedKey)) if err != nil { log.WithField("Path", fullPath).Info("Decryption failed") return nil, fmt.Errorf("failed to decrypt sops data key from Vault transit backend '%s': %w", fullPath, err) diff --git a/kms/keysource.go b/kms/keysource.go index d3be8d104..515c4b853 100644 --- a/kms/keysource.go +++ b/kms/keysource.go @@ -235,8 +235,16 @@ func (c CredentialsProvider) ApplyToMasterKey(key *MasterKey) { // Encrypt takes a SOPS data key, encrypts it with KMS and stores the result // in the EncryptedKey field. +// +// Consider using EncryptContext instead. func (key *MasterKey) Encrypt(dataKey []byte) error { - cfg, err := key.createKMSConfig() + return key.EncryptContext(context.Background(), dataKey) +} + +// EncryptContext takes a SOPS data key, encrypts it with KMS and stores the result +// in the EncryptedKey field. +func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error { + cfg, err := key.createKMSConfig(ctx) if err != nil { log.WithField("arn", key.Arn).Info("Encryption failed") return err @@ -247,7 +255,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { Plaintext: dataKey, EncryptionContext: stringPointerToStringMap(key.EncryptionContext), } - out, err := client.Encrypt(context.TODO(), input) + out, err := client.Encrypt(ctx, input) if err != nil { log.WithField("arn", key.Arn).Info("Encryption failed") return fmt.Errorf("failed to encrypt sops data key with AWS KMS: %w", err) @@ -278,13 +286,21 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { // Decrypt decrypts the EncryptedKey with a newly created AWS KMS config, and // returns the result. +// +// Consider using DecryptContext instead. func (key *MasterKey) Decrypt() ([]byte, error) { + return key.DecryptContext(context.Background()) +} + +// DecryptContext decrypts the EncryptedKey with a newly created AWS KMS config, and +// returns the result. +func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) { k, err := base64.StdEncoding.DecodeString(key.EncryptedKey) if err != nil { log.WithField("arn", key.Arn).Info("Decryption failed") return nil, fmt.Errorf("error base64-decoding encrypted data key: %s", err) } - cfg, err := key.createKMSConfig() + cfg, err := key.createKMSConfig(ctx) if err != nil { log.WithField("arn", key.Arn).Info("Decryption failed") return nil, err @@ -295,7 +311,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { CiphertextBlob: k, EncryptionContext: stringPointerToStringMap(key.EncryptionContext), } - decrypted, err := client.Decrypt(context.TODO(), input) + decrypted, err := client.Decrypt(ctx, input) if err != nil { log.WithField("arn", key.Arn).Info("Decryption failed") return nil, fmt.Errorf("failed to decrypt sops data key with AWS KMS: %w", err) @@ -351,7 +367,7 @@ func (key *MasterKey) TypeToIdentifier() string { // createKMSConfig returns an AWS config with the credentialsProvider of the // MasterKey, or the default configuration sources. -func (key MasterKey) createKMSConfig() (*aws.Config, error) { +func (key MasterKey) createKMSConfig(ctx context.Context) (*aws.Config, error) { re := regexp.MustCompile(arnRegex) matches := re.FindStringSubmatch(key.Arn) if matches == nil { @@ -359,7 +375,7 @@ func (key MasterKey) createKMSConfig() (*aws.Config, error) { } region := matches[1] - cfg, err := config.LoadDefaultConfig(context.TODO(), func(lo *config.LoadOptions) error { + cfg, err := config.LoadDefaultConfig(ctx, func(lo *config.LoadOptions) error { // Use the credentialsProvider if present, otherwise default to reading credentials // from the environment. if key.credentialsProvider != nil { @@ -376,7 +392,7 @@ func (key MasterKey) createKMSConfig() (*aws.Config, error) { } if key.Role != "" { - return key.createSTSConfig(&cfg) + return key.createSTSConfig(ctx, &cfg) } return &cfg, nil } @@ -393,7 +409,7 @@ func (key MasterKey) createClient(config *aws.Config) *kms.Client { // createSTSConfig uses AWS STS to assume a role and returns a config // configured with that role's credentials. It returns an error if // it fails to construct a session name, or assume the role. -func (key MasterKey) createSTSConfig(config *aws.Config) (*aws.Config, error) { +func (key MasterKey) createSTSConfig(ctx context.Context, config *aws.Config) (*aws.Config, error) { name, err := stsSessionName() if err != nil { return nil, err @@ -404,7 +420,7 @@ func (key MasterKey) createSTSConfig(config *aws.Config) (*aws.Config, error) { } client := sts.NewFromConfig(*config) - out, err := client.AssumeRole(context.TODO(), input) + out, err := client.AssumeRole(ctx, input) if err != nil { return nil, fmt.Errorf("failed to assume role '%s': %w", key.Role, err) } diff --git a/kms/keysource_test.go b/kms/keysource_test.go index da3c6b51e..e44929cb9 100644 --- a/kms/keysource_test.go +++ b/kms/keysource_test.go @@ -535,7 +535,7 @@ aws_secret_access_key = test-secret`), 0600)) if tt.envFunc != nil { tt.envFunc(t) } - cfg, err := tt.key.createKMSConfig() + cfg, err := tt.key.createKMSConfig(context.Background()) tt.assertFunc(t, cfg, err) }) } @@ -549,7 +549,7 @@ func TestMasterKey_createSTSConfig(t *testing.T) { return } key := NewMasterKeyFromArn(dummyARN, nil, "") - cfg, err := key.createSTSConfig(nil) + cfg, err := key.createSTSConfig(context.Background(), nil) assert.Error(t, err) assert.ErrorContains(t, err, "failed to construct STS session name") assert.Nil(t, cfg) @@ -558,7 +558,7 @@ func TestMasterKey_createSTSConfig(t *testing.T) { t.Run("role assumption error", func(t *testing.T) { key := NewMasterKeyFromArn(dummyARN, nil, "") key.Role = "role" - got, err := key.createSTSConfig(&aws.Config{}) + got, err := key.createSTSConfig(context.Background(), &aws.Config{}) assert.Error(t, err) assert.ErrorContains(t, err, "failed to assume role 'role'") assert.Nil(t, got) @@ -629,7 +629,7 @@ func createTestMasterKey(arn string) MasterKey { // createTestKMSClient creates a new client with the // aws.EndpointResolverWithOptions set to epResolver. func createTestKMSClient(key MasterKey) (*kms.Client, error) { - cfg, err := key.createKMSConfig() + cfg, err := key.createKMSConfig(context.Background()) if err != nil { return nil, err } diff --git a/pgp/keysource.go b/pgp/keysource.go index 65769a3bf..63e31027c 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -8,6 +8,7 @@ package pgp // import "github.com/getsops/sops/v3/pgp" import ( "bytes" + "context" "encoding/hex" "errors" "fmt" @@ -129,13 +130,22 @@ func NewGnuPGHome() (GnuPGHome, error) { // Import attempts to import the armored key bytes into the GnuPGHome keyring. // It returns an error if the GnuPGHome does not pass Validate, or if the // import failed. +// +// Consider using ImportContext instead. func (d GnuPGHome) Import(armoredKey []byte) error { + return d.ImportContext(context.Background(), armoredKey) +} + +// ImportContext attempts to import the armored key bytes into the GnuPGHome keyring. +// It returns an error if the GnuPGHome does not pass Validate, or if the +// import failed. +func (d GnuPGHome) ImportContext(ctx context.Context, armoredKey []byte) error { if err := d.Validate(); err != nil { return fmt.Errorf("cannot import armored key data into GnuPG keyring: %w", err) } args := []string{"--batch", "--import"} - _, stderr, err := gpgExec(d.String(), args, bytes.NewReader(armoredKey)) + _, stderr, err := gpgExec(ctx, d.String(), args, bytes.NewReader(armoredKey)) if err != nil { stderrStr := strings.TrimSpace(stderr.String()) errStr := err.Error() @@ -254,7 +264,15 @@ func (e errSet) Error() string { // Encrypt encrypts the data key with the PGP key with the same // fingerprint as the MasterKey. +// +// Consider using EncryptContext instead. func (key *MasterKey) Encrypt(dataKey []byte) error { + return key.EncryptContext(context.Background(), dataKey) +} + +// EncryptContext encrypts the data key with the PGP key with the same +// fingerprint as the MasterKey. +func (key *MasterKey) EncryptContext(ctx context.Context, dataKey []byte) error { var errs errSet if !key.disableOpenPGP { @@ -266,7 +284,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { errs = append(errs, fmt.Errorf("github.com/ProtonMail/go-crypto/openpgp error: %w", openpgpErr)) } - binaryErr := key.encryptWithGnuPG(dataKey) + binaryErr := key.encryptWithGnuPG(ctx, dataKey) if binaryErr == nil { log.WithField("fingerprint", key.Fingerprint).Info("Encryption succeeded") return nil @@ -320,7 +338,7 @@ func (key *MasterKey) encryptWithOpenPGP(dataKey []byte) error { // encryptWithOpenPGP attempts to encrypt the data key using GnuPG with the // PGP key that belongs to Fingerprint. It sets EncryptedDataKey, or returns // an error. -func (key *MasterKey) encryptWithGnuPG(dataKey []byte) error { +func (key *MasterKey) encryptWithGnuPG(ctx context.Context, dataKey []byte) error { fingerprint := shortenFingerprint(key.Fingerprint) args := []string{ @@ -334,7 +352,7 @@ func (key *MasterKey) encryptWithGnuPG(dataKey []byte) error { fingerprint, "--no-encrypt-to", } - stdout, stderr, err := gpgExec(key.gnuPGHomeDir, args, bytes.NewReader(dataKey)) + stdout, stderr, err := gpgExec(ctx, key.gnuPGHomeDir, args, bytes.NewReader(dataKey)) if err != nil { return fmt.Errorf("failed to encrypt sops data key with pgp: %s", strings.TrimSpace(stderr.String())) } @@ -365,7 +383,16 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { // Decrypt first attempts to obtain the data key from the EncryptedKey // stored in the MasterKey using OpenPGP, before falling back to GnuPG. // When both attempts fail, an error is returned. +// +// Consider using DecryptContext instead. func (key *MasterKey) Decrypt() ([]byte, error) { + return key.DecryptContext(context.Background()) +} + +// DecryptContext first attempts to obtain the data key from the EncryptedKey +// stored in the MasterKey using OpenPGP, before falling back to GnuPG. +// When both attempts fail, an error is returned. +func (key *MasterKey) DecryptContext(ctx context.Context) ([]byte, error) { var errs errSet if !key.disableOpenPGP { @@ -377,7 +404,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { errs = append(errs, fmt.Errorf("github.com/ProtonMail/go-crypto/openpgp error: %w", openpgpErr)) } - dataKey, binaryErr := key.decryptWithGnuPG() + dataKey, binaryErr := key.decryptWithGnuPG(ctx) if binaryErr == nil { log.WithField("fingerprint", key.Fingerprint).Info("Decryption succeeded") return dataKey, nil @@ -419,11 +446,11 @@ func (key *MasterKey) decryptWithOpenPGP() ([]byte, error) { // GnuPG and returns the result. If DisableAgent is configured on the MasterKey, // the GnuPG agent is not enabled. When the decryption command fails, it returns // the error from stdout. -func (key *MasterKey) decryptWithGnuPG() ([]byte, error) { +func (key *MasterKey) decryptWithGnuPG(ctx context.Context) ([]byte, error) { args := []string{ "-d", } - stdout, stderr, err := gpgExec(key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) + stdout, stderr, err := gpgExec(ctx, key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) if err != nil { return nil, fmt.Errorf("failed to decrypt sops data key with pgp: %s", strings.TrimSpace(stderr.String())) @@ -595,12 +622,12 @@ func fingerprintIndex(ring openpgp.EntityList) map[string]openpgp.Entity { // gpgExec runs the provided args with the gpgBinary, while restricting it to // homeDir when provided. Stdout and stderr can be read from the returned // buffers. When the command fails, an error is returned. -func gpgExec(homeDir string, args []string, stdin io.Reader) (stdout bytes.Buffer, stderr bytes.Buffer, err error) { +func gpgExec(ctx context.Context, homeDir string, args []string, stdin io.Reader) (stdout bytes.Buffer, stderr bytes.Buffer, err error) { if homeDir != "" { args = append([]string{"--homedir", homeDir}, args...) } - cmd := exec.Command(gpgBinary(), args...) + cmd := exec.CommandContext(ctx, gpgBinary(), args...) cmd.Stdin = stdin cmd.Stdout = &stdout cmd.Stderr = &stderr diff --git a/pgp/keysource_test.go b/pgp/keysource_test.go index 28fcfeb8e..4bed79747 100644 --- a/pgp/keysource_test.go +++ b/pgp/keysource_test.go @@ -2,6 +2,7 @@ package pgp import ( "bytes" + "context" "io" "os" "os/user" @@ -56,14 +57,14 @@ func TestGnuPGHome_Import(t *testing.T) { assert.NoError(t, err) assert.NoError(t, gnuPGHome.Import(b)) - _, stderr, err := gpgExec(gnuPGHome.String(), []string{"--list-keys", mockFingerprint}, nil) + _, stderr, err := gpgExec(context.Background(), gnuPGHome.String(), []string{"--list-keys", mockFingerprint}, nil) assert.NoErrorf(t, err, stderr.String()) b, err = os.ReadFile(mockPrivateKey) assert.NoError(t, err) assert.NoError(t, gnuPGHome.Import(b)) - _, stderr, err = gpgExec(gnuPGHome.String(), []string{"--list-secret-keys", mockFingerprint}, nil) + _, stderr, err = gpgExec(context.Background(), gnuPGHome.String(), []string{"--list-secret-keys", mockFingerprint}, nil) assert.NoErrorf(t, err, stderr.String()) err = gnuPGHome.Import([]byte("invalid armored data")) @@ -281,7 +282,7 @@ func TestMasterKey_encryptWithGnuPG(t *testing.T) { key := NewMasterKeyFromFingerprint(mockFingerprint) gnuPGHome.ApplyToMasterKey(key) data := []byte("oh no, my darkest secret") - assert.NoError(t, key.encryptWithGnuPG(data)) + assert.NoError(t, key.encryptWithGnuPG(context.Background(), data)) assert.NotEmpty(t, key.EncryptedKey) assert.NotEqual(t, data, key.EncryptedKey) @@ -291,14 +292,14 @@ func TestMasterKey_encryptWithGnuPG(t *testing.T) { args := []string{ "-d", } - stdout, stderr, err := gpgExec(key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) + stdout, stderr, err := gpgExec(context.Background(), key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) assert.NoError(t, err, stderr.String()) assert.Equal(t, data, stdout.Bytes()) }) t.Run("invalid fingerprint error", func(t *testing.T) { key := NewMasterKeyFromFingerprint("invalid") - err := key.encryptWithGnuPG([]byte("invalid")) + err := key.encryptWithGnuPG(context.Background(), []byte("invalid")) assert.Error(t, err) assert.ErrorContains(t, err, "failed to encrypt sops data key with pgp: gpg: 'invalid' is not a valid long keyID") }) @@ -341,7 +342,7 @@ func TestMasterKey_Decrypt(t *testing.T) { fingerprint := shortenFingerprint(mockFingerprint) data := []byte("this data is absolutely top secret") - stdout, stderr, err := gpgExec(gnuPGHome.String(), []string{ + stdout, stderr, err := gpgExec(context.Background(), gnuPGHome.String(), []string{ "--no-default-recipient", "--yes", "--encrypt", @@ -424,7 +425,7 @@ func TestMasterKey_decryptWithOpenPGP(t *testing.T) { fingerprint := shortenFingerprint(mockFingerprint) data := []byte("this data is absolutely top secret") - stdout, stderr, err := gpgExec(gnuPGHome.String(), []string{ + stdout, stderr, err := gpgExec(context.Background(), gnuPGHome.String(), []string{ "--no-default-recipient", "--yes", "--encrypt", @@ -473,7 +474,7 @@ func TestMasterKey_decryptWithGnuPG(t *testing.T) { fingerprint := shortenFingerprint(mockFingerprint) data := []byte("this data is absolutely top secret") - stdout, stderr, err := gpgExec(gnuPGHome.String(), []string{ + stdout, stderr, err := gpgExec(context.Background(), gnuPGHome.String(), []string{ "--no-default-recipient", "--yes", "--encrypt", @@ -494,7 +495,7 @@ func TestMasterKey_decryptWithGnuPG(t *testing.T) { gnuPGHome.ApplyToMasterKey(key) key.EncryptedKey = encryptedData - got, err := key.decryptWithGnuPG() + got, err := key.decryptWithGnuPG(context.Background()) assert.NoError(t, err) assert.Equal(t, data, got) }) @@ -502,7 +503,7 @@ func TestMasterKey_decryptWithGnuPG(t *testing.T) { t.Run("invalid data error", func(t *testing.T) { key := NewMasterKeyFromFingerprint(mockFingerprint) key.EncryptedKey = "absolute invalid" - got, err := key.decryptWithGnuPG() + got, err := key.decryptWithGnuPG(context.Background()) assert.Error(t, err) assert.ErrorContains(t, err, "gpg: no valid OpenPGP data found") assert.Nil(t, got)