From 2b7b02351b6912a33ec6eef8dfd96eefc6cf4c11 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Thu, 17 Aug 2023 00:40:21 +0200 Subject: [PATCH 1/4] gcpkms: further deal with Google SDK deprecations xref: https://github.com/googleapis/google-cloud-go/blob/e535dc7c1d986c2ad6db3e8f5f2974935ee9ecda/migration.md Signed-off-by: Hidde Beydals --- gcpkms/keysource_test.go | 2 +- gcpkms/mock_kms_server_test.go | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/gcpkms/keysource_test.go b/gcpkms/keysource_test.go index 2904eb34b..a37fb5b6e 100644 --- a/gcpkms/keysource_test.go +++ b/gcpkms/keysource_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" + "cloud.google.com/go/kms/apiv1/kmspb" "github.com/stretchr/testify/assert" - kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" "google.golang.org/grpc" ) diff --git a/gcpkms/mock_kms_server_test.go b/gcpkms/mock_kms_server_test.go index 91b474747..bd2f30d60 100644 --- a/gcpkms/mock_kms_server_test.go +++ b/gcpkms/mock_kms_server_test.go @@ -23,12 +23,11 @@ import ( "io" "strings" - kmspb "google.golang.org/genproto/googleapis/cloud/kms/v1" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/types/known/anypb" - + "cloud.google.com/go/kms/apiv1/kmspb" "google.golang.org/genproto/googleapis/rpc/status" "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" ) var _ = io.EOF From faa0e29136b6313e1730f194615cfb922e28205f Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Thu, 17 Aug 2023 00:57:17 +0200 Subject: [PATCH 2/4] *: deal with various gRPC deprecations Signed-off-by: Hidde Beydals --- cmd/sops/main.go | 17 ++++++++++------- gcpkms/keysource_test.go | 3 ++- keyservice/server.go | 7 +++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/cmd/sops/main.go b/cmd/sops/main.go index 35dc5527f..50ec20355 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -1,6 +1,7 @@ package main //import "github.com/getsops/sops/v3/cmd/sops" import ( + "context" encodingjson "encoding/json" "fmt" "net" @@ -11,10 +12,7 @@ import ( "reflect" "strconv" "strings" - "time" - "github.com/sirupsen/logrus" - "github.com/urfave/cli" "github.com/getsops/sops/v3" "github.com/getsops/sops/v3/aes" "github.com/getsops/sops/v3/age" @@ -38,7 +36,10 @@ import ( "github.com/getsops/sops/v3/stores/dotenv" "github.com/getsops/sops/v3/stores/json" "github.com/getsops/sops/v3/version" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) var log *logrus.Logger @@ -1029,10 +1030,12 @@ func keyservices(c *cli.Context) (svcs []keyservice.KeyServiceClient) { addr = url.Path } opts := []grpc.DialOption{ - grpc.WithInsecure(), - grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout(url.Scheme, addr, timeout) - }), + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithContextDialer( + func(ctx context.Context, addr string) (net.Conn, error) { + return (&net.Dialer{}).DialContext(ctx, url.Scheme, addr) + }, + ), } log.WithField( "address", diff --git a/gcpkms/keysource_test.go b/gcpkms/keysource_test.go index a37fb5b6e..153bfb260 100644 --- a/gcpkms/keysource_test.go +++ b/gcpkms/keysource_test.go @@ -10,6 +10,7 @@ import ( "cloud.google.com/go/kms/apiv1/kmspb" "github.com/stretchr/testify/assert" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) var ( @@ -158,7 +159,7 @@ func newGRPCServer(port string) *grpc.ClientConn { } go serv.Serve(lis) - conn, err := grpc.Dial(lis.Addr().String(), grpc.WithInsecure()) + conn, err := grpc.Dial(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatal(err) } diff --git a/keyservice/server.go b/keyservice/server.go index 85829621a..9f2b486a6 100644 --- a/keyservice/server.go +++ b/keyservice/server.go @@ -10,7 +10,6 @@ import ( "github.com/getsops/sops/v3/kms" "github.com/getsops/sops/v3/pgp" "golang.org/x/net/context" - "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -239,7 +238,7 @@ func (ks Server) prompt(key *Key, requestType string) error { } } if response == "n" { - return grpc.Errorf(codes.PermissionDenied, "Request rejected by user") + return status.Errorf(codes.PermissionDenied, "Request rejected by user") } return nil } @@ -300,9 +299,9 @@ func (ks Server) Decrypt(ctx context.Context, Plaintext: plaintext, } case nil: - return nil, grpc.Errorf(codes.NotFound, "Must provide a key") + return nil, status.Errorf(codes.NotFound, "Must provide a key") default: - return nil, grpc.Errorf(codes.NotFound, "Unknown key type") + return nil, status.Errorf(codes.NotFound, "Unknown key type") } if ks.Prompt { err := ks.prompt(key, "decrypt") From 7e487fa0d292470578bafdd97e6f76f05eeac672 Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Thu, 17 Aug 2023 01:15:44 +0200 Subject: [PATCH 3/4] kms: use `BaseEndpoint` for testing This does the same, but with much less boilerplate. xref: https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/endpoints/#v2-endpointresolverv2--baseendpoint Signed-off-by: Hidde Beydals --- kms/keysource.go | 22 +++++++++++++--------- kms/keysource_test.go | 17 ++++------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/kms/keysource.go b/kms/keysource.go index 09a26a326..47c369b36 100644 --- a/kms/keysource.go +++ b/kms/keysource.go @@ -70,11 +70,11 @@ type MasterKey struct { // using CredentialsProvider.ApplyToMasterKey. If nil, the default client is used // which utilizes runtime environmental values. credentialsProvider aws.CredentialsProvider - // epResolver can be used to override the endpoint the AWS client resolves + // baseEndpoint can be used to override the endpoint the AWS client resolves // to by default. This is mostly used for testing purposes as it can not be // injected using e.g. an environment variable. The field is not publicly // exposed, nor configurable. - epResolver aws.EndpointResolverWithOptions + baseEndpoint string } // NewMasterKey creates a new MasterKey from an ARN, role and context, setting @@ -197,7 +197,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { log.WithField("arn", key.Arn).Error("Encryption failed") return err } - client := kms.NewFromConfig(*cfg) + client := key.createClient(cfg) input := &kms.EncryptInput{ KeyId: &key.Arn, Plaintext: dataKey, @@ -245,7 +245,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { log.WithField("arn", key.Arn).Error("Decryption failed") return nil, err } - client := kms.NewFromConfig(*cfg) + client := key.createClient(cfg) input := &kms.DecryptInput{ KeyId: &key.Arn, CiphertextBlob: k, @@ -309,11 +309,6 @@ func (key MasterKey) createKMSConfig() (*aws.Config, error) { lo.SharedConfigProfile = key.AwsProfile } lo.Region = region - - // Set the epResolver, if present. Used ONLY for tests. - if key.epResolver != nil { - lo.EndpointResolverWithOptions = key.epResolver - } return nil }) if err != nil { @@ -326,6 +321,15 @@ func (key MasterKey) createKMSConfig() (*aws.Config, error) { return &cfg, nil } +// createClient creates a new AWS KMS client with the provided config. +func (key MasterKey) createClient(config *aws.Config) *kms.Client { + return kms.NewFromConfig(*config, func(o *kms.Options) { + if key.baseEndpoint != "" { + o.BaseEndpoint = aws.String(key.baseEndpoint) + } + }) +} + // 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. diff --git a/kms/keysource_test.go b/kms/keysource_test.go index f558197ea..81cd9bbd8 100644 --- a/kms/keysource_test.go +++ b/kms/keysource_test.go @@ -549,7 +549,7 @@ func createTestMasterKey(arn string) MasterKey { return MasterKey{ Arn: arn, credentialsProvider: credentials.NewStaticCredentialsProvider("id", "secret", ""), - epResolver: epResolver{}, + baseEndpoint: testKMSServerURL, } } @@ -560,16 +560,7 @@ func createTestKMSClient(key MasterKey) (*kms.Client, error) { if err != nil { return nil, err } - cfg.EndpointResolverWithOptions = epResolver{} - return kms.NewFromConfig(*cfg), nil -} - -// epResolver is a dummy resolver that points to the local test KMS server. -type epResolver struct{} - -// ResolveEndpoint always resolves to testKMSServerURL. -func (e epResolver) ResolveEndpoint(_, _ string, _ ...interface{}) (aws.Endpoint, error) { - return aws.Endpoint{ - URL: testKMSServerURL, - }, nil + return kms.NewFromConfig(*cfg, func(options *kms.Options) { + options.BaseEndpoint = aws.String(testKMSServerURL) + }), nil } From 92aa55f06af0a00ba6666a2048b681136935862a Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Thu, 17 Aug 2023 01:21:25 +0200 Subject: [PATCH 4/4] *: `strings.Title` deprecation Replace with simple manual construction of upper boolean representation, as the (construction of the) `golang.org/x/text/cases` replacement is way too complex for this use case. Signed-off-by: Hidde Beydals --- aes/cipher.go | 9 ++++++--- sops.go | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/aes/cipher.go b/aes/cipher.go index d4ad74add..291f2fedf 100644 --- a/aes/cipher.go +++ b/aes/cipher.go @@ -11,11 +11,10 @@ import ( "fmt" "regexp" "strconv" - "strings" - "github.com/sirupsen/logrus" "github.com/getsops/sops/v3" "github.com/getsops/sops/v3/logging" + "github.com/sirupsen/logrus" ) var log *logrus.Logger @@ -172,7 +171,11 @@ func (c Cipher) Encrypt(plaintext interface{}, key []byte, additionalData string case bool: encryptedType = "bool" // The Python version encodes booleans with Titlecase - plainBytes = []byte(strings.Title(strconv.FormatBool(value))) + if value { + plainBytes = []byte("True") + } else { + plainBytes = []byte("False") + } case sops.Comment: encryptedType = "comment" plainBytes = []byte(value.Value) diff --git a/sops.go b/sops.go index 71b08f23e..ae0ecfc24 100644 --- a/sops.go +++ b/sops.go @@ -46,12 +46,12 @@ import ( "strings" "time" - "github.com/sirupsen/logrus" "github.com/getsops/sops/v3/audit" "github.com/getsops/sops/v3/keys" "github.com/getsops/sops/v3/keyservice" "github.com/getsops/sops/v3/logging" "github.com/getsops/sops/v3/shamir" + "github.com/sirupsen/logrus" "golang.org/x/net/context" ) @@ -727,7 +727,11 @@ func ToBytes(in interface{}) ([]byte, error) { case float64: return []byte(strconv.FormatFloat(in, 'f', -1, 64)), nil case bool: - return []byte(strings.Title(strconv.FormatBool(in))), nil + boolB := []byte("True") + if !in { + boolB = []byte("False") + } + return boolB, nil case []byte: return in, nil case Comment: