diff --git a/cmd/sops/main.go b/cmd/sops/main.go index 9853505af..d6f00e828 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -528,6 +528,14 @@ func main() { Name: "aws-profile", Usage: "The AWS profile to use for requests to AWS", }, + cli.StringFlag{ + Name: "aws-kms-endpoint", + Usage: "The AWS KMS Endpoint to use for requests to AWS. Ex: https://kms.ap-southeast-2.amazonaws.com", + }, + cli.StringFlag{ + Name: "aws-sts-endpoint", + Usage: "The AWS STS Endpoint to use for requests to AWS. Ex: https://sts.ap-southeast-2.amazonaws.com", + }, cli.StringSliceFlag{ Name: "gcp-kms", Usage: "the GCP KMS Resource ID the new group should contain. Can be specified more than once", @@ -572,7 +580,7 @@ func main() { group = append(group, pgp.NewMasterKeyFromFingerprint(fp)) } for _, arn := range kmsArns { - group = append(group, kms.NewMasterKeyFromArn(arn, kms.ParseKMSContext(c.String("encryption-context")), c.String("aws-profile"))) + group = append(group, kms.NewMasterKeyFromArn(arn, kms.ParseKMSContext(c.String("encryption-context")), c.String("aws-profile"), c.String("aws-kms-endpoint"), c.String("aws-sts-endpoint"))) } for _, kms := range gcpKmses { group = append(group, gcpkms.NewMasterKeyFromResourceID(kms)) @@ -890,6 +898,14 @@ func main() { Name: "aws-profile", Usage: "The AWS profile to use for requests to AWS", }, + cli.StringFlag{ + Name: "aws-kms-endpoint", + Usage: "The AWS KMS Endpoint to use for requests to AWS", + }, + cli.StringFlag{ + Name: "aws-sts-endpoint", + Usage: "The AWS STS Endpoint to use for requests to AWS", + }, cli.StringFlag{ Name: "gcp-kms", Usage: "comma separated list of GCP KMS resource IDs", @@ -1228,6 +1244,14 @@ func main() { Name: "aws-profile", Usage: "The AWS profile to use for requests to AWS", }, + cli.StringFlag{ + Name: "aws-kms-endpoint", + Usage: "The AWS KMS Endpoint to use for requests to AWS", + }, + cli.StringFlag{ + Name: "aws-sts-endpoint", + Usage: "The AWS STS Endpoint to use for requests to AWS", + }, cli.StringFlag{ Name: "gcp-kms", Usage: "comma separated list of GCP KMS resource IDs", @@ -1602,6 +1626,14 @@ func main() { Name: "aws-profile", Usage: "The AWS profile to use for requests to AWS", }, + cli.StringFlag{ + Name: "aws-kms-endpoint", + Usage: "The AWS KMS Endpoint to use for requests to AWS", + }, + cli.StringFlag{ + Name: "aws-sts-endpoint", + Usage: "The AWS STS Endpoint to use for requests to AWS", + }, cli.StringFlag{ Name: "gcp-kms", Usage: "comma separated list of GCP KMS resource IDs", @@ -2085,7 +2117,7 @@ func getEncryptConfig(c *cli.Context, fileName string) (encryptConfig, error) { func getMasterKeys(c *cli.Context, kmsEncryptionContext map[string]*string, kmsOptionName string, pgpOptionName string, gcpKmsOptionName string, azureKvOptionName string, hcVaultTransitOptionName string, ageOptionName string) ([]keys.MasterKey, error) { var masterKeys []keys.MasterKey - for _, k := range kms.MasterKeysFromArnString(c.String(kmsOptionName), kmsEncryptionContext, c.String("aws-profile")) { + for _, k := range kms.MasterKeysFromArnString(c.String(kmsOptionName), kmsEncryptionContext, c.String("aws-profile"), c.String("aws-kms-endpoint"), c.String("aws-sts-endpoint")) { masterKeys = append(masterKeys, k) } for _, k := range pgp.MasterKeysFromFingerprintString(c.String(pgpOptionName)) { @@ -2274,7 +2306,7 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) { return nil, common.NewExitError("Invalid KMS encryption context format", codes.ErrorInvalidKMSEncryptionContextFormat) } if c.String("kms") != "" { - for _, k := range kms.MasterKeysFromArnString(c.String("kms"), kmsEncryptionContext, c.String("aws-profile")) { + for _, k := range kms.MasterKeysFromArnString(c.String("kms"), kmsEncryptionContext, c.String("aws-profile"), c.String("aws-kms-endpoint"), c.String("aws-sts-endpoint")) { kmsKeys = append(kmsKeys, k) } } diff --git a/config/config.go b/config/config.go index 06ad57370..8bf717dab 100644 --- a/config/config.go +++ b/config/config.go @@ -143,10 +143,12 @@ type gcpKmsKey struct { } type kmsKey struct { - Arn string `yaml:"arn"` - Role string `yaml:"role,omitempty"` - Context map[string]*string `yaml:"context"` - AwsProfile string `yaml:"aws_profile"` + Arn string `yaml:"arn"` + Role string `yaml:"role,omitempty"` + Context map[string]*string `yaml:"context"` + AwsProfile string `yaml:"aws_profile"` + AwsKmsEndpoint string `yaml:"aws_kms_endpoint"` + AwsStsEndpoint string `yaml:"aws_sts_endpoint"` } type azureKVKey struct { @@ -173,6 +175,8 @@ type creationRule struct { PathRegex string `yaml:"path_regex"` KMS string AwsProfile string `yaml:"aws_profile"` + AwsKmsEndpoint string `yaml:"aws_kms_endpoint"` + AwsStsEndpoint string `yaml:"aws_sts_endpoint"` Age string `yaml:"age"` PGP string GCPKMS string `yaml:"gcp_kms"` @@ -261,7 +265,7 @@ func extractMasterKeys(group keyGroup) (sops.KeyGroup, error) { keyGroup = append(keyGroup, pgp.NewMasterKeyFromFingerprint(k)) } for _, k := range group.KMS { - keyGroup = append(keyGroup, kms.NewMasterKeyWithProfile(k.Arn, k.Role, k.Context, k.AwsProfile)) + keyGroup = append(keyGroup, kms.NewMasterKeyWithProfile(k.Arn, k.Role, k.Context, k.AwsProfile, k.AwsKmsEndpoint, k.AwsStsEndpoint)) } for _, k := range group.GCPKMS { keyGroup = append(keyGroup, gcpkms.NewMasterKeyFromResourceID(k.ResourceID)) @@ -304,7 +308,7 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[ for _, k := range pgp.MasterKeysFromFingerprintString(cRule.PGP) { keyGroup = append(keyGroup, k) } - for _, k := range kms.MasterKeysFromArnString(cRule.KMS, kmsEncryptionContext, cRule.AwsProfile) { + for _, k := range kms.MasterKeysFromArnString(cRule.KMS, kmsEncryptionContext, cRule.AwsProfile, cRule.AwsKmsEndpoint, cRule.AwsStsEndpoint) { keyGroup = append(keyGroup, k) } for _, k := range gcpkms.MasterKeysFromResourceIDString(cRule.GCPKMS) { diff --git a/keyservice/keyservice.pb.go b/keyservice/keyservice.pb.go index a810b2805..282105f85 100644 --- a/keyservice/keyservice.pb.go +++ b/keyservice/keyservice.pb.go @@ -205,10 +205,12 @@ type KmsKey struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Arn string `protobuf:"bytes,1,opt,name=arn,proto3" json:"arn,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - Context map[string]string `protobuf:"bytes,3,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile,json=awsProfile,proto3" json:"aws_profile,omitempty"` + Arn string `protobuf:"bytes,1,opt,name=arn,proto3" json:"arn,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + Context map[string]string `protobuf:"bytes,3,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile,json=awsProfile,proto3" json:"aws_profile,omitempty"` + AwsKmsEndpoint string `protobuf:"bytes,5,opt,name=aws_kms_endpoint,json=awsKmsEndpoint,proto3" json:"aws_kms_endpoint,omitempty"` + AwsStsEndpoint string `protobuf:"bytes,6,opt,name=aws_sts_endpoint,json=awsStsEndpoint,proto3" json:"aws_sts_endpoint,omitempty"` } func (x *KmsKey) Reset() { @@ -269,6 +271,20 @@ func (x *KmsKey) GetAwsProfile() string { return "" } +func (x *KmsKey) GetAwsKmsEndpoint() string { + if x != nil { + return x.AwsKmsEndpoint + } + return "" +} + +func (x *KmsKey) GetAwsStsEndpoint() string { + if x != nil { + return x.AwsStsEndpoint + } + return "" +} + type GcpKmsKey struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -702,7 +718,7 @@ var file_keyservice_keyservice_proto_rawDesc = []byte{ 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x06, 0x50, 0x67, 0x70, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x6e, 0x74, 0x22, 0xbb, 0x01, 0x0a, 0x06, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, + 0x72, 0x69, 0x6e, 0x74, 0x22, 0x8f, 0x02, 0x0a, 0x06, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, @@ -710,52 +726,58 @@ var file_keyservice_keyservice_proto_rawDesc = []byte{ 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x77, 0x73, 0x50, - 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x2c, 0x0a, 0x09, 0x47, 0x63, 0x70, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, - 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, - 0x22, 0x6b, 0x0a, 0x08, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, - 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5d, 0x0a, - 0x10, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, - 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x26, 0x0a, 0x06, - 0x41, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, - 0x69, 0x65, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, - 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x31, 0x0a, 0x0f, - 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, - 0x48, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, - 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, - 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0x2f, 0x0a, 0x0f, 0x44, 0x65, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x32, 0x6c, 0x0a, 0x0a, 0x4b, 0x65, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x07, 0x44, 0x65, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0e, 0x5a, 0x0c, 0x2e, 0x2f, 0x6b, 0x65, - 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x77, 0x73, 0x5f, 0x6b, 0x6d, + 0x73, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x61, 0x77, 0x73, 0x4b, 0x6d, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x12, 0x28, 0x0a, 0x10, 0x61, 0x77, 0x73, 0x5f, 0x73, 0x74, 0x73, 0x5f, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x77, 0x73, 0x53, + 0x74, 0x73, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x2c, 0x0a, 0x09, 0x47, 0x63, 0x70, 0x4b, 0x6d, 0x73, + 0x4b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x64, 0x22, 0x6b, 0x0a, 0x08, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, + 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, + 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0x5d, 0x0a, 0x10, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x75, + 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x55, + 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x26, 0x0a, 0x06, 0x41, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, + 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x22, 0x31, 0x0a, 0x0f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, + 0x65, 0x78, 0x74, 0x22, 0x48, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, + 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0x2f, 0x0a, + 0x0f, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x32, 0x6c, + 0x0a, 0x0a, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x07, + 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x07, + 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0e, 0x5a, 0x0c, + 0x2e, 0x2f, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/keyservice/keyservice.proto b/keyservice/keyservice.proto index 8bf62f89b..eee764b39 100644 --- a/keyservice/keyservice.proto +++ b/keyservice/keyservice.proto @@ -22,6 +22,8 @@ message KmsKey { string role = 2; map context = 3; string aws_profile = 4; + string aws_kms_endpoint = 5; + string aws_sts_endpoint = 6; } message GcpKmsKey { diff --git a/keyservice/server.go b/keyservice/server.go index 9f2b486a6..5b251bb5f 100644 --- a/keyservice/server.go +++ b/keyservice/server.go @@ -323,5 +323,7 @@ func kmsKeyToMasterKey(key *KmsKey) kms.MasterKey { Role: key.Role, EncryptionContext: ctx, AwsProfile: key.AwsProfile, + AwsKmsEndpoint: key.AwsKmsEndpoint, + AwsStsEndpoint: key.AwsStsEndpoint, } } diff --git a/keyservice/server_test.go b/keyservice/server_test.go index cc29c4528..4f8de72d1 100644 --- a/keyservice/server_test.go +++ b/keyservice/server_test.go @@ -9,18 +9,22 @@ import ( func TestKmsKeyToMasterKey(t *testing.T) { cases := []struct { - description string - expectedArn string - expectedRole string - expectedCtx map[string]string - expectedAwsProfile string + description string + expectedArn string + expectedRole string + expectedCtx map[string]string + expectedAwsProfile string + expectedAwsKmsEndpoint string + expectedAwsStsEndpoint string }{ { - description: "empty context", - expectedArn: "arn:aws:kms:eu-west-1:123456789012:key/d5c90a06-f824-4628-922b-12424571ed4d", - expectedRole: "ExampleRole", - expectedCtx: map[string]string{}, - expectedAwsProfile: "", + description: "empty context", + expectedArn: "arn:aws:kms:eu-west-1:123456789012:key/d5c90a06-f824-4628-922b-12424571ed4d", + expectedRole: "ExampleRole", + expectedCtx: map[string]string{}, + expectedAwsProfile: "", + expectedAwsKmsEndpoint: "", + expectedAwsStsEndpoint: "", }, { description: "context with one key-value pair", @@ -29,7 +33,9 @@ func TestKmsKeyToMasterKey(t *testing.T) { expectedCtx: map[string]string{ "firstKey": "first value", }, - expectedAwsProfile: "ExampleProfile", + expectedAwsProfile: "ExampleProfile", + expectedAwsKmsEndpoint: "Example AWS KMS Endpoint", + expectedAwsStsEndpoint: "Example AWS STS Endpoint", }, { description: "context with three key-value pairs", @@ -40,7 +46,9 @@ func TestKmsKeyToMasterKey(t *testing.T) { "secondKey": "second value", "thirdKey": "third value", }, - expectedAwsProfile: "", + expectedAwsProfile: "", + expectedAwsKmsEndpoint: "", + expectedAwsStsEndpoint: "", }, } @@ -54,10 +62,12 @@ func TestKmsKeyToMasterKey(t *testing.T) { } key := &KmsKey{ - Arn: c.expectedArn, - Role: c.expectedRole, - Context: inputCtx, - AwsProfile: c.expectedAwsProfile, + Arn: c.expectedArn, + Role: c.expectedRole, + Context: inputCtx, + AwsProfile: c.expectedAwsProfile, + AwsKmsEndpoint: c.expectedAwsKmsEndpoint, + AwsStsEndpoint: c.expectedAwsStsEndpoint, } masterKey := kmsKeyToMasterKey(key) diff --git a/kms/keysource.go b/kms/keysource.go index d3be8d104..04596a4c5 100644 --- a/kms/keysource.go +++ b/kms/keysource.go @@ -74,35 +74,38 @@ type MasterKey struct { // using CredentialsProvider.ApplyToMasterKey. If nil, the default client is used // which utilizes runtime environmental values. credentialsProvider aws.CredentialsProvider - // 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. - baseEndpoint string + // AwsKmsEndpoint can be used to override the endpoint the AWS client resolves + // to by default. This is mostly used for custom AWS that has custom endpoint. + AwsKmsEndpoint string + // AwsStsEndpoint can be used to override the endpoint the AWS client resolves + // to by default. This is mostly used for custom AWS that has custom endpoint. + AwsStsEndpoint string } // NewMasterKey creates a new MasterKey from an ARN, role and context, setting // the creation date to the current date. -func NewMasterKey(arn string, role string, context map[string]*string) *MasterKey { +func NewMasterKey(arn string, role string, context map[string]*string, awsKmsEndpoint string, awsStsEndpoint string) *MasterKey { return &MasterKey{ Arn: arn, Role: role, EncryptionContext: context, CreationDate: time.Now().UTC(), + AwsKmsEndpoint: awsKmsEndpoint, + AwsStsEndpoint: awsStsEndpoint, } } // NewMasterKeyWithProfile creates a new MasterKey from an ARN, role, context // and awsProfile, setting the creation date to the current date. -func NewMasterKeyWithProfile(arn string, role string, context map[string]*string, awsProfile string) *MasterKey { - k := NewMasterKey(arn, role, context) +func NewMasterKeyWithProfile(arn string, role string, context map[string]*string, awsProfile string, awsKmsEndpoint string, awsStsEndpoint string) *MasterKey { + k := NewMasterKey(arn, role, context, awsKmsEndpoint, awsStsEndpoint) k.AwsProfile = awsProfile return k } // NewMasterKeyFromArn takes an ARN string and returns a new MasterKey for that // ARN. -func NewMasterKeyFromArn(arn string, context map[string]*string, awsProfile string) *MasterKey { +func NewMasterKeyFromArn(arn string, context map[string]*string, awsProfile string, awsKmsEndpoint string, awsStsEndpoint string) *MasterKey { key := &MasterKey{} arn = strings.Replace(arn, " ", "", -1) key.Arn = arn @@ -115,18 +118,20 @@ func NewMasterKeyFromArn(arn string, context map[string]*string, awsProfile stri key.EncryptionContext = context key.CreationDate = time.Now().UTC() key.AwsProfile = awsProfile + key.AwsKmsEndpoint = awsKmsEndpoint + key.AwsStsEndpoint = awsStsEndpoint return key } // MasterKeysFromArnString takes a comma separated list of AWS KMS ARNs, and // returns a slice of new MasterKeys for those ARNs. -func MasterKeysFromArnString(arn string, context map[string]*string, awsProfile string) []*MasterKey { +func MasterKeysFromArnString(arn string, context map[string]*string, awsProfile string, awsKmsEndpoint string, awsStsEndpoint string) []*MasterKey { var keys []*MasterKey if arn == "" { return keys } for _, s := range strings.Split(arn, ",") { - keys = append(keys, NewMasterKeyFromArn(s, context, awsProfile)) + keys = append(keys, NewMasterKeyFromArn(s, context, awsProfile, awsKmsEndpoint, awsStsEndpoint)) } return keys } @@ -384,8 +389,8 @@ func (key MasterKey) createKMSConfig() (*aws.Config, error) { // 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) + if key.AwsKmsEndpoint != "" { + o.BaseEndpoint = aws.String(key.AwsKmsEndpoint) } }) } @@ -403,7 +408,11 @@ func (key MasterKey) createSTSConfig(config *aws.Config) (*aws.Config, error) { RoleSessionName: &name, } - client := sts.NewFromConfig(*config) + client := sts.NewFromConfig(*config, func(o *sts.Options) { + if key.AwsStsEndpoint != "" { + o.BaseEndpoint = aws.String(key.AwsStsEndpoint) + } + }) out, err := client.AssumeRole(context.TODO(), 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..b033b7dd1 100644 --- a/kms/keysource_test.go +++ b/kms/keysource_test.go @@ -116,7 +116,7 @@ func TestNewMasterKey(t *testing.T) { "foo": aws.String("bar"), } ) - key := NewMasterKey(dummyARN, dummyRole, dummyEncryptionContext) + key := NewMasterKey(dummyARN, dummyRole, dummyEncryptionContext, "", "") assert.Equal(t, dummyARN, key.Arn) assert.Equal(t, dummyRole, key.Role) assert.Equal(t, dummyEncryptionContext, key.EncryptionContext) @@ -131,7 +131,7 @@ func TestNewMasterKeyWithProfile(t *testing.T) { } dummyProfile = "a-profile" ) - key := NewMasterKeyWithProfile(dummyARN, dummyRole, dummyEncryptionContext, dummyProfile) + key := NewMasterKeyWithProfile(dummyARN, dummyRole, dummyEncryptionContext, dummyProfile, "", "") assert.Equal(t, dummyARN, key.Arn) assert.Equal(t, dummyRole, key.Role) assert.Equal(t, dummyEncryptionContext, key.EncryptionContext) @@ -147,7 +147,7 @@ func TestNewMasterKeyFromArn(t *testing.T) { } dummyProfile = "a-profile" ) - key := NewMasterKeyFromArn(dummyARN, dummyEncryptionContext, dummyProfile) + key := NewMasterKeyFromArn(dummyARN, dummyEncryptionContext, dummyProfile, "", "") assert.Equal(t, dummyARN, key.Arn) assert.Equal(t, dummyEncryptionContext, key.EncryptionContext) assert.Equal(t, dummyProfile, key.AwsProfile) @@ -156,12 +156,12 @@ func TestNewMasterKeyFromArn(t *testing.T) { }) t.Run("arn with spaces", func(t *testing.T) { - key := NewMasterKeyFromArn(" arn:aws:kms:us-west-2 :107501996527:key/612d5f 0p-p1l3-45e6-aca6-a5b00569 3a48 ", nil, "") + key := NewMasterKeyFromArn(" arn:aws:kms:us-west-2 :107501996527:key/612d5f 0p-p1l3-45e6-aca6-a5b00569 3a48 ", nil, "", "", "") assert.Equal(t, "arn:aws:kms:us-west-2:107501996527:key/612d5f0p-p1l3-45e6-aca6-a5b005693a48", key.Arn) }) t.Run("arn with role", func(t *testing.T) { - key := NewMasterKeyFromArn("arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500+arn:aws:iam::927034868273:role/sops-dev-xyz", nil, "") + key := NewMasterKeyFromArn("arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500+arn:aws:iam::927034868273:role/sops-dev-xyz", nil, "", "", "") assert.Equal(t, "arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500", key.Arn) assert.Equal(t, "arn:aws:iam::927034868273:role/sops-dev-xyz", key.Role) }) @@ -169,7 +169,7 @@ func TestNewMasterKeyFromArn(t *testing.T) { func TestMasterKeysFromArnString(t *testing.T) { s := "arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e+arn:aws:iam::927034868273:role/sops-dev, arn:aws:kms:ap-southeast-1:656532927350:key/9006a8aa-0fa6-4c14-930e-a2dfb916de1d" - ks := MasterKeysFromArnString(s, nil, "foo") + ks := MasterKeysFromArnString(s, nil, "foo", "", "") k1 := ks[0] k2 := ks[1] @@ -359,7 +359,7 @@ func TestMasterKey_EncryptDecrypt_RoundTrip(t *testing.T) { } func TestMasterKey_NeedsRotation(t *testing.T) { - key := NewMasterKeyFromArn(dummyARN, nil, "") + key := NewMasterKeyFromArn(dummyARN, nil, "", "", "") assert.False(t, key.NeedsRotation()) key.CreationDate = key.CreationDate.Add(-(kmsTTL + time.Second)) @@ -376,28 +376,28 @@ func TestMasterKey_ToString(t *testing.T) { "baz": &bam, } - key := NewMasterKeyFromArn(dummyARN, nil, "") + key := NewMasterKeyFromArn(dummyARN, nil, "", "", "") assert.Equal(t, dummyARN, key.ToString()) - key = NewMasterKeyFromArn(dummyARNWithRole, nil, "") + key = NewMasterKeyFromArn(dummyARNWithRole, nil, "", "", "") assert.Equal(t, dummyARNWithRole, key.ToString()) - key = NewMasterKeyFromArn(dummyARN, nil, "profile") + key = NewMasterKeyFromArn(dummyARN, nil, "profile", "", "") assert.Equal(t, fmt.Sprintf("%s||profile", dummyARN), key.ToString()) - key = NewMasterKeyFromArn(dummyARNWithRole, nil, "profile") + key = NewMasterKeyFromArn(dummyARNWithRole, nil, "profile", "", "") assert.Equal(t, fmt.Sprintf("%s||profile", dummyARNWithRole), key.ToString()) - key = NewMasterKeyFromArn(dummyARN, context, "") + key = NewMasterKeyFromArn(dummyARN, context, "", "", "") assert.Equal(t, fmt.Sprintf("%s|baz:bam,foo:bar", dummyARN), key.ToString()) - key = NewMasterKeyFromArn(dummyARNWithRole, context, "") + key = NewMasterKeyFromArn(dummyARNWithRole, context, "", "", "") assert.Equal(t, fmt.Sprintf("%s|baz:bam,foo:bar", dummyARNWithRole), key.ToString()) - key = NewMasterKeyFromArn(dummyARN, context, "profile") + key = NewMasterKeyFromArn(dummyARN, context, "profile", "", "") assert.Equal(t, fmt.Sprintf("%s|baz:bam,foo:bar|profile", dummyARN), key.ToString()) - key = NewMasterKeyFromArn(dummyARNWithRole, context, "profile") + key = NewMasterKeyFromArn(dummyARNWithRole, context, "profile", "", "") assert.Equal(t, fmt.Sprintf("%s|baz:bam,foo:bar|profile", dummyARNWithRole), key.ToString()) } @@ -548,7 +548,7 @@ func TestMasterKey_createSTSConfig(t *testing.T) { err = fmt.Errorf("an error") return } - key := NewMasterKeyFromArn(dummyARN, nil, "") + key := NewMasterKeyFromArn(dummyARN, nil, "", "", "") cfg, err := key.createSTSConfig(nil) assert.Error(t, err) assert.ErrorContains(t, err, "failed to construct STS session name") @@ -556,7 +556,7 @@ func TestMasterKey_createSTSConfig(t *testing.T) { }) t.Run("role assumption error", func(t *testing.T) { - key := NewMasterKeyFromArn(dummyARN, nil, "") + key := NewMasterKeyFromArn(dummyARN, nil, "", "", "") key.Role = "role" got, err := key.createSTSConfig(&aws.Config{}) assert.Error(t, err) @@ -622,7 +622,7 @@ func createTestMasterKey(arn string) MasterKey { return MasterKey{ Arn: arn, credentialsProvider: credentials.NewStaticCredentialsProvider("id", "secret", ""), - baseEndpoint: testKMSServerURL, + AwsKmsEndpoint: testKMSServerURL, } } diff --git a/stores/stores.go b/stores/stores.go index bdc026a00..78f6de7a5 100644 --- a/stores/stores.go +++ b/stores/stores.go @@ -84,6 +84,8 @@ type kmskey struct { CreatedAt string `yaml:"created_at" json:"created_at"` EncryptedDataKey string `yaml:"enc" json:"enc"` AwsProfile string `yaml:"aws_profile" json:"aws_profile"` + AwsKmsEndpoint string `yaml:"aws_kms_endpoint" json:"aws_kms_endpoint"` + AwsStsEndpoint string `yaml:"aws_sts_endpoint" json:"aws_sts_endpoint"` } type gcpkmskey struct { @@ -175,6 +177,8 @@ func kmsKeysFromGroup(group sops.KeyGroup) (keys []kmskey) { Context: key.EncryptionContext, Role: key.Role, AwsProfile: key.AwsProfile, + AwsKmsEndpoint: key.AwsKmsEndpoint, + AwsStsEndpoint: key.AwsStsEndpoint, }) } } @@ -376,6 +380,8 @@ func (kmsKey *kmskey) toInternal() (*kms.MasterKey, error) { CreationDate: creationDate, Arn: kmsKey.Arn, AwsProfile: kmsKey.AwsProfile, + AwsKmsEndpoint: kmsKey.AwsKmsEndpoint, + AwsStsEndpoint: kmsKey.AwsStsEndpoint, }, nil }