Skip to content

Commit

Permalink
[v12] Don't force the use of FIPS endpoints for DynamoDB Streams and …
Browse files Browse the repository at this point in the history
…Application Auto Scaling

Backport of #34876.

DynamoDB Streams and Application Auto Scaling do not currently have FIPS endpoints in
non-GovCloud, leading to invalid endpoints for FIPS users running in AWS Standard.

See also: https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service

Regression from #34170.

Fixes #34804.

Additionally, clean-up a few more AWS session initiations to be consistent and clear.
  • Loading branch information
reedloden committed Nov 29, 2023
1 parent 35cbdf4 commit c79acb2
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 53 deletions.
4 changes: 4 additions & 0 deletions integration/ec2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/gravitational/trace"
Expand Down Expand Up @@ -138,6 +139,9 @@ func getIID(t *testing.T) imds.InstanceIdentityDocument {
func getCallerIdentity(t *testing.T) *sts.GetCallerIdentityOutput {
sess, err := session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Config: aws.Config{
EC2MetadataEnableFallback: aws.Bool(false),
},
})
require.NoError(t, err)
stsService := sts.New(sess)
Expand Down
6 changes: 3 additions & 3 deletions lib/auth/join_iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,11 @@ func newSTSClient(ctx context.Context, cfg *stsIdentityRequestConfig) (*sts.STS,
if cfg.fipsEndpointOption == endpoints.FIPSEndpointStateEnabled &&
!slices.Contains(validSTSEndpoints, strings.TrimPrefix(stsClient.Endpoint, "https://")) {
// The AWS SDK will generate invalid endpoints when attempting to
// resolve the FIPS endpoint for a region which does not have one.
// resolve the FIPS endpoint for a region that does not have one.
// In this case, try to use the FIPS endpoint in us-east-1. This should
// work for all regions in the standard partition. In GovCloud we should
// work for all regions in the standard partition. In GovCloud, we should
// not hit this because all regional endpoints support FIPS. In China or
// other partitions this will fail and FIPS mode will not be supported.
// other partitions, this will fail, and FIPS mode will not be supported.
log.Infof("AWS SDK resolved FIPS STS endpoint %s, which does not appear to be valid. "+
"Attempting to use the FIPS STS endpoint for us-east-1.",
stsClient.Endpoint)
Expand Down
37 changes: 21 additions & 16 deletions lib/backend/dynamo/dynamodbbk.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,32 +221,30 @@ func New(ctx context.Context, params backend.Params) (*Backend, error) {
clock: clockwork.NewRealClock(),
buf: buf,
}

// determine if the FIPS endpoints should be used
useFIPSEndpoint := endpoints.FIPSEndpointStateUnset
if modules.GetModules().IsBoringBinary() {
useFIPSEndpoint = endpoints.FIPSEndpointStateEnabled
}
// create an AWS session using default SDK behavior, i.e. it will interpret
// the environment and ~/.aws directory just like an AWS CLI tool would:

awsConfig := aws.Config{
EC2MetadataEnableFallback: aws.Bool(false),
}
if cfg.Region != "" {
awsConfig.Region = aws.String(cfg.Region)
}
if cfg.AccessKey != "" || cfg.SecretKey != "" {
awsConfig.Credentials = credentials.NewStaticCredentials(cfg.AccessKey, cfg.SecretKey, "")
}

b.session, err = session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
Config: aws.Config{
EC2MetadataEnableFallback: aws.Bool(false),
UseFIPSEndpoint: useFIPSEndpoint,
},
Config: awsConfig,
})
if err != nil {
return nil, trace.Wrap(err)
}
// override the default environment (region + credentials) with the values
// from the YAML file:
if cfg.Region != "" {
b.session.Config.Region = aws.String(cfg.Region)
}
if cfg.AccessKey != "" || cfg.SecretKey != "" {
creds := credentials.NewStaticCredentials(cfg.AccessKey, cfg.SecretKey, "")
b.session.Config.Credentials = creds
}

// Increase the size of the connection pool. This substantially improves the
// performance of Teleport under load as it reduces the number of TLS
Expand All @@ -261,7 +259,14 @@ func New(ctx context.Context, params backend.Params) (*Backend, error) {
b.session.Config.HTTPClient = httpClient

// create DynamoDB service:
svc, err := dynamometrics.NewAPIMetrics(dynamometrics.Backend, dynamodb.New(b.session))
svc, err := dynamometrics.NewAPIMetrics(dynamometrics.Backend, dynamodb.New(b.session, &aws.Config{
// Setting this on the individual service instead of the session, as DynamoDB Streams
// and Application Auto Scaling do not yet have FIPS endpoints in non-GovCloud.
// See also: https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service
// TODO(reed): This can be simplified once https://github.com/aws/aws-sdk-go/pull/5078
// is available (or whenever AWS adds the missing FIPS endpoints).
UseFIPSEndpoint: useFIPSEndpoint,
}))
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
39 changes: 22 additions & 17 deletions lib/events/dynamoevents/dynamoevents.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,34 +261,39 @@ func New(ctx context.Context, cfg Config) (*Log, error) {
Entry: l,
Config: cfg,
}
// create an AWS session using default SDK behavior, i.e. it will interpret
// the environment and ~/.aws directory just like an AWS CLI tool would:
b.session, err = awssession.NewSessionWithOptions(awssession.Options{
SharedConfigState: awssession.SharedConfigEnable,
})
if err != nil {
return nil, trace.Wrap(err)

awsConfig := aws.Config{
EC2MetadataEnableFallback: aws.Bool(false),
}
// override the default environment (region + credentials) with the values
// from the YAML file:

// Override the default environment's region if value set in YAML file:
if cfg.Region != "" {
b.session.Config.Region = aws.String(cfg.Region)
awsConfig.Region = aws.String(cfg.Region)
}

// Override the service endpoint using the "endpoint" query parameter from
// "audit_events_uri". This is for non-AWS DynamoDB-compatible backends.
if cfg.Endpoint != "" {
b.session.Config.Endpoint = aws.String(cfg.Endpoint)
awsConfig.Endpoint = aws.String(cfg.Endpoint)
}

// Explicitly enable or disable FIPS endpoints for DynamoDB
b.session.Config.UseFIPSEndpoint = events.FIPSProtoStateToAWSState(cfg.UseFIPSEndpoint)

// Explicitly disable IMDSv1 fallback
b.session.Config.EC2MetadataEnableFallback = aws.Bool(false)
b.session, err = awssession.NewSessionWithOptions(awssession.Options{
SharedConfigState: awssession.SharedConfigEnable,
Config: awsConfig,
})
if err != nil {
return nil, trace.Wrap(err)
}

// create DynamoDB service:
svc, err := dynamometrics.NewAPIMetrics(dynamometrics.Events, dynamodb.New(b.session))
svc, err := dynamometrics.NewAPIMetrics(dynamometrics.Events, dynamodb.New(b.session, &aws.Config{
// Setting this on the individual service instead of the session, as DynamoDB Streams
// and Application Auto Scaling do not yet have FIPS endpoints in non-GovCloud.
// See also: https://aws.amazon.com/compliance/fips/#FIPS_Endpoints_by_Service
// TODO(reed): This can be simplified once https://github.com/aws/aws-sdk-go/pull/5078
// is available (or whenever AWS adds the missing FIPS endpoints).
UseFIPSEndpoint: events.FIPSProtoStateToAWSState(cfg.UseFIPSEndpoint),
}))
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
32 changes: 15 additions & 17 deletions lib/events/s3sessions/s3handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,33 +155,31 @@ func (s *Config) CheckAndSetDefaults() error {
return trace.BadParameter("missing parameter Bucket")
}
if s.Session == nil {
// create an AWS session using default SDK behavior, i.e. it will interpret
// the environment and ~/.aws directory just like an AWS CLI tool would:
sess, err := awssession.NewSessionWithOptions(awssession.Options{
SharedConfigState: awssession.SharedConfigEnable,
})
if err != nil {
return trace.Wrap(err)
awsConfig := aws.Config{
EC2MetadataEnableFallback: aws.Bool(false),
UseFIPSEndpoint: events.FIPSProtoStateToAWSState(s.UseFIPSEndpoint),
}
// override the default environment (region + Host + credentials) with the values
// from the YAML file:
if s.Region != "" {
sess.Config.Region = aws.String(s.Region)
awsConfig.Region = aws.String(s.Region)
}
if s.Endpoint != "" {
sess.Config.Endpoint = aws.String(s.Endpoint)
sess.Config.S3ForcePathStyle = aws.Bool(true)
awsConfig.Endpoint = aws.String(s.Endpoint)
awsConfig.S3ForcePathStyle = aws.Bool(true)
}
if s.Insecure {
sess.Config.DisableSSL = aws.Bool(s.Insecure)
awsConfig.DisableSSL = aws.Bool(s.Insecure)
}
if s.Credentials != nil {
sess.Config.Credentials = s.Credentials
awsConfig.Credentials = s.Credentials
}

sess.Config.EC2MetadataEnableFallback = aws.Bool(false)

sess.Config.UseFIPSEndpoint = events.FIPSProtoStateToAWSState(s.UseFIPSEndpoint)
sess, err := awssession.NewSessionWithOptions(awssession.Options{
SharedConfigState: awssession.SharedConfigEnable,
Config: awsConfig,
})
if err != nil {
return trace.Wrap(err)
}

s.Session = sess
}
Expand Down

0 comments on commit c79acb2

Please sign in to comment.