Skip to content

Commit

Permalink
FIPS & DualStack Endpoint Resolver Support (#3938)
Browse files Browse the repository at this point in the history
* DualStack and FIPS Modeling Support
  • Loading branch information
skmcgrail authored Nov 5, 2021
1 parent e292407 commit 2582633
Show file tree
Hide file tree
Showing 346 changed files with 28,292 additions and 10,456 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
### SDK Features
* Support has been added for configuring endpoints with requirements such as FIPS and DualStack. ([#3938](https://github.com/aws/aws-sdk-go/pull/3938))
* `AWS_USE_FIPS_ENDPOINT` and `AWS_USE_DUALSTACK_ENDPOINT` can be set to `true` or `false` in the environment to indicate an endpoint with the respective characteristic must be resolved.
* `use_fips_endpoint` and `use_dualstack_endpoint` can be set to `true` or `false` in the shared config file to indicate an endpoint with the respective characteristic must be resolved.
* Programmatic configuration of FIPS and DualStack endpoint resolution.
* For more information see the `aws/session` package documentation.

### SDK Enhancements

Expand Down
13 changes: 7 additions & 6 deletions aws/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import (

// A Config provides configuration to a service client instance.
type Config struct {
Config *aws.Config
Handlers request.Handlers
PartitionID string
Endpoint string
SigningRegion string
SigningName string
Config *aws.Config
Handlers request.Handlers
PartitionID string
Endpoint string
SigningRegion string
SigningName string
ResolvedRegion string

// States that the signing name did not come from a modeled source but
// was derived based on other data. Used by service client constructors
Expand Down
19 changes: 10 additions & 9 deletions aws/client/metadata/client_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package metadata

// ClientInfo wraps immutable data from the client.Client structure.
type ClientInfo struct {
ServiceName string
ServiceID string
APIVersion string
PartitionID string
Endpoint string
SigningName string
SigningRegion string
JSONVersion string
TargetPrefix string
ServiceName string
ServiceID string
APIVersion string
PartitionID string
Endpoint string
SigningName string
SigningRegion string
JSONVersion string
TargetPrefix string
ResolvedRegion string
}
23 changes: 23 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,19 @@ type Config struct {
// svc := s3.New(sess, &aws.Config{
// UseDualStack: aws.Bool(true),
// })
//
// Deprecated: This option will continue to function for S3 and S3 Control for backwards compatibility.
// UseDualStackEndpoint should be used to enable usage of a service's dual-stack endpoint for all service clients
// moving forward. For S3 and S3 Control, when UseDualStackEndpoint is set to a non-zero value it takes higher
// precedence then this option.
UseDualStack *bool

// Sets the resolver to resolve a dual-stack endpoint for the service.
UseDualStackEndpoint endpoints.DualStackEndpointState

// UseFIPSEndpoint specifies the resolver must resolve a FIPS endpoint.
UseFIPSEndpoint endpoints.FIPSEndpointState

// SleepDelay is an override for the func the SDK will call when sleeping
// during the lifecycle of a request. Specifically this will be used for
// request delays. This value should only be used for testing. To adjust
Expand Down Expand Up @@ -554,6 +565,10 @@ func mergeInConfig(dst *Config, other *Config) {
dst.UseDualStack = other.UseDualStack
}

if other.UseDualStackEndpoint != endpoints.DualStackEndpointStateUnset {
dst.UseDualStackEndpoint = other.UseDualStackEndpoint
}

if other.EC2MetadataDisableTimeoutOverride != nil {
dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride
}
Expand Down Expand Up @@ -589,6 +604,14 @@ func mergeInConfig(dst *Config, other *Config) {
if other.LowerCaseHeaderMaps != nil {
dst.LowerCaseHeaderMaps = other.LowerCaseHeaderMaps
}

if other.UseDualStackEndpoint != endpoints.DualStackEndpointStateUnset {
dst.UseDualStackEndpoint = other.UseDualStackEndpoint
}

if other.UseFIPSEndpoint != endpoints.FIPSEndpointStateUnset {
dst.UseFIPSEndpoint = other.UseFIPSEndpoint
}
}

// Copy will return a shallow copy of the Config object. If any additional
Expand Down
59 changes: 25 additions & 34 deletions aws/endpoints/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resol
// Customization
for i := 0; i < len(ps); i++ {
p := &ps[i]
custAddS3DualStack(p)
custRegionalS3(p)
custRmIotDataService(p)
custFixAppAutoscalingChina(p)
Expand All @@ -91,15 +90,6 @@ func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resol
return ps, nil
}

func custAddS3DualStack(p *partition) {
if !(p.ID == "aws" || p.ID == "aws-cn" || p.ID == "aws-us-gov") {
return
}

custAddDualstack(p, "s3")
custAddDualstack(p, "s3-control")
}

func custRegionalS3(p *partition) {
if p.ID != "aws" {
return
Expand All @@ -110,35 +100,28 @@ func custRegionalS3(p *partition) {
return
}

const awsGlobal = "aws-global"
const usEast1 = "us-east-1"

// If global endpoint already exists no customization needed.
if _, ok := service.Endpoints["aws-global"]; ok {
if _, ok := service.Endpoints[endpointKey{Region: awsGlobal}]; ok {
return
}

service.PartitionEndpoint = "aws-global"
service.Endpoints["us-east-1"] = endpoint{}
service.Endpoints["aws-global"] = endpoint{
service.PartitionEndpoint = awsGlobal
if _, ok := service.Endpoints[endpointKey{Region: usEast1}]; !ok {
service.Endpoints[endpointKey{Region: usEast1}] = endpoint{}
}
service.Endpoints[endpointKey{Region: awsGlobal}] = endpoint{
Hostname: "s3.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
Region: usEast1,
},
}

p.Services["s3"] = service
}

func custAddDualstack(p *partition, svcName string) {
s, ok := p.Services[svcName]
if !ok {
return
}

s.Defaults.HasDualStack = boxedTrue
s.Defaults.DualStackHostname = "{service}.dualstack.{region}.{dnsSuffix}"

p.Services[svcName] = s
}

func custRmIotDataService(p *partition) {
delete(p.Services, "data.iot")
}
Expand All @@ -155,12 +138,13 @@ func custFixAppAutoscalingChina(p *partition) {
}

const expectHostname = `autoscaling.{region}.amazonaws.com`
if e, a := s.Defaults.Hostname, expectHostname; e != a {
serviceDefault := s.Defaults[defaultKey{}]
if e, a := expectHostname, serviceDefault.Hostname; e != a {
fmt.Printf("custFixAppAutoscalingChina: ignoring customization, expected %s, got %s\n", e, a)
return
}

s.Defaults.Hostname = expectHostname + ".cn"
serviceDefault.Hostname = expectHostname + ".cn"
s.Defaults[defaultKey{}] = serviceDefault
p.Services[serviceName] = s
}

Expand All @@ -175,18 +159,25 @@ func custFixAppAutoscalingUsGov(p *partition) {
return
}

if a := s.Defaults.CredentialScope.Service; a != "" {
serviceDefault := s.Defaults[defaultKey{}]
if a := serviceDefault.CredentialScope.Service; a != "" {
fmt.Printf("custFixAppAutoscalingUsGov: ignoring customization, expected empty credential scope service, got %s\n", a)
return
}

if a := s.Defaults.Hostname; a != "" {
if a := serviceDefault.Hostname; a != "" {
fmt.Printf("custFixAppAutoscalingUsGov: ignoring customization, expected empty hostname, got %s\n", a)
return
}

s.Defaults.CredentialScope.Service = "application-autoscaling"
s.Defaults.Hostname = "autoscaling.{region}.amazonaws.com"
serviceDefault.CredentialScope.Service = "application-autoscaling"
serviceDefault.Hostname = "autoscaling.{region}.amazonaws.com"

if s.Defaults == nil {
s.Defaults = make(endpointDefaults)
}

s.Defaults[defaultKey{}] = serviceDefault

p.Services[serviceName] = s
}
Expand Down
Loading

0 comments on commit 2582633

Please sign in to comment.