diff --git a/.golangci.yml b/.golangci.yml
index 79929e35e17b0..c0632f4c790e9 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -59,16 +59,21 @@ issues:
path-except: ^e/
text: "non-constant format string in call to github.com/gravitational/trace."
# lib/utils/aws/ subpackages are allowed to use AWS SDK constructors.
+ - path: lib/utils/aws/iamutils/iam.go
+ linters: [forbidigo]
+ text: 'iam.NewFromConfig'
+ - path: lib/utils/aws/iamutils/iam_v1.go
+ linters: [forbidigo]
+ text: 'iam.New'
- path: lib/utils/aws/stsutils/sts.go
linters: [forbidigo]
text: 'sts.NewFromConfig'
- path: lib/utils/aws/stsutils/sts_v1.go
linters: [forbidigo]
text: 'sts.New'
- # TODO(codingllama): Remove once e/ is updated.
- - path: e/lib/cloud/aws/aws.go
+ - path: lib/utils/aws/stsutils/stscreds_v1.go
linters: [forbidigo]
- text: 'sts.NewFromConfig'
+ text: 'stscreds.NewCredentials'
exclude-use-default: true
max-same-issues: 0
max-issues-per-linter: 0
@@ -281,10 +286,17 @@ linters-settings:
forbid:
- p: '^rsa\.GenerateKey$'
msg: 'generating RSA keys is slow, use lib/cryptosuites to generate an appropriate key type'
+ # AWS SDK wrapped constructors.
+ - p: '^iam\.NewFromConfig$'
+ msg: 'Use iamutils.NewFromConfig'
+ - p: '^iam\.New$'
+ msg: 'Use iamutils.NewV1'
- p: '^sts\.NewFromConfig$'
msg: 'Use stsutils.NewFromConfig'
- p: '^sts\.New$'
msg: 'Use stsutils.NewV1'
+ - p: '^stscreds\.NewCredentials$'
+ msg: 'Use stsutils.NewCredentials'
run:
go: '1.23'
diff --git a/lib/cloud/clients.go b/lib/cloud/clients.go
index f8351d6309fa7..a89094a008f98 100644
--- a/lib/cloud/clients.go
+++ b/lib/cloud/clients.go
@@ -44,7 +44,6 @@ import (
"github.com/aws/aws-sdk-go/service/eks/eksiface"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/elasticache/elasticacheiface"
- "github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/iam/iamiface"
"github.com/aws/aws-sdk-go/service/kms"
"github.com/aws/aws-sdk-go/service/kms/kmsiface"
@@ -81,6 +80,7 @@ import (
gcpimds "github.com/gravitational/teleport/lib/cloud/imds/gcp"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/utils"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -589,7 +589,7 @@ func (c *cloudClients) GetAWSIAMClient(ctx context.Context, region string, opts
if err != nil {
return nil, trace.Wrap(err)
}
- return iam.New(session), nil
+ return iamutils.NewV1(session), nil
}
// GetAWSS3Client returns AWS S3 client.
diff --git a/lib/configurators/aws/aws.go b/lib/configurators/aws/aws.go
index 45063d9bc05bf..e8676a4925533 100644
--- a/lib/configurators/aws/aws.go
+++ b/lib/configurators/aws/aws.go
@@ -49,6 +49,7 @@ import (
"github.com/gravitational/teleport/lib/srv/db/secrets"
"github.com/gravitational/teleport/lib/utils"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -392,7 +393,7 @@ func (c *ConfiguratorConfig) CheckAndSetDefaults() error {
c.stsClient = stsutils.NewFromConfig(*c.awsCfg)
}
if c.iamClient == nil {
- c.iamClient = iam.NewFromConfig(*c.awsCfg)
+ c.iamClient = iamutils.NewFromConfig(*c.awsCfg)
}
if c.Identity == nil {
c.Identity, err = awslib.GetIdentityWithClientV2(context.Background(), c.stsClient)
@@ -423,7 +424,7 @@ func (c *ConfiguratorConfig) CheckAndSetDefaults() error {
if c.Policies == nil {
partition := c.Identity.GetPartition()
accountID := c.Identity.GetAccountID()
- iamClient := iam.NewFromConfig(*c.awsCfg)
+ iamClient := iamutils.NewFromConfig(*c.awsCfg)
c.Policies = awslib.NewPolicies(partition, accountID, iamClient)
}
}
diff --git a/lib/integrations/awsoidc/accessgraph_sync.go b/lib/integrations/awsoidc/accessgraph_sync.go
index 30232598b5e6f..ba272e0eeae07 100644
--- a/lib/integrations/awsoidc/accessgraph_sync.go
+++ b/lib/integrations/awsoidc/accessgraph_sync.go
@@ -29,6 +29,7 @@ import (
awslib "github.com/gravitational/teleport/lib/cloud/aws"
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -91,7 +92,7 @@ func NewAccessGraphIAMConfigureClient(ctx context.Context) (AccessGraphIAMConfig
return &defaultTAGIAMConfigureClient{
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/aws_app_access_iam_config.go b/lib/integrations/awsoidc/aws_app_access_iam_config.go
index 46fae5ad677d3..22b4139305ec9 100644
--- a/lib/integrations/awsoidc/aws_app_access_iam_config.go
+++ b/lib/integrations/awsoidc/aws_app_access_iam_config.go
@@ -31,6 +31,7 @@ import (
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
"github.com/gravitational/teleport/lib/modules"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -108,7 +109,7 @@ func NewAWSAppAccessConfigureClient(ctx context.Context) (AWSAppAccessConfigureC
}
return &defaultAWSAppAccessConfigureClient{
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/deployservice_iam_config.go b/lib/integrations/awsoidc/deployservice_iam_config.go
index d7b5b764c1962..67a16685217de 100644
--- a/lib/integrations/awsoidc/deployservice_iam_config.go
+++ b/lib/integrations/awsoidc/deployservice_iam_config.go
@@ -33,6 +33,7 @@ import (
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
"github.com/gravitational/teleport/lib/integrations/awsoidc/tags"
awslibutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -146,7 +147,7 @@ func NewDeployServiceIAMConfigureClient(ctx context.Context, region string) (Dep
}
return &defaultDeployServiceIAMConfigureClient{
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/ec2_ssm_iam_config.go b/lib/integrations/awsoidc/ec2_ssm_iam_config.go
index c2116a5cda714..4188749de612a 100644
--- a/lib/integrations/awsoidc/ec2_ssm_iam_config.go
+++ b/lib/integrations/awsoidc/ec2_ssm_iam_config.go
@@ -32,6 +32,7 @@ import (
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
"github.com/gravitational/teleport/lib/integrations/awsoidc/tags"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -143,7 +144,7 @@ func NewEC2SSMConfigureClient(ctx context.Context, region string) (EC2SSMConfigu
}
return &defaultEC2SSMConfigureClient{
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
ssmClient: ssm.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
diff --git a/lib/integrations/awsoidc/eice_iam_config.go b/lib/integrations/awsoidc/eice_iam_config.go
index 8158b45042e11..99d18e8a60928 100644
--- a/lib/integrations/awsoidc/eice_iam_config.go
+++ b/lib/integrations/awsoidc/eice_iam_config.go
@@ -29,6 +29,7 @@ import (
awslib "github.com/gravitational/teleport/lib/cloud/aws"
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -101,7 +102,7 @@ func NewEICEIAMConfigureClient(ctx context.Context, region string) (EICEIAMConfi
return &defaultEICEIAMConfigureClient{
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/eks_iam_config.go b/lib/integrations/awsoidc/eks_iam_config.go
index c4b13a5ed1dda..231a854b0734c 100644
--- a/lib/integrations/awsoidc/eks_iam_config.go
+++ b/lib/integrations/awsoidc/eks_iam_config.go
@@ -29,6 +29,7 @@ import (
awslib "github.com/gravitational/teleport/lib/cloud/aws"
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -100,7 +101,7 @@ func NewEKSIAMConfigureClient(ctx context.Context, region string) (EKSIAMConfigu
}
return &defaultEKSEIAMConfigureClient{
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/idp_iam_config.go b/lib/integrations/awsoidc/idp_iam_config.go
index 9b2a00e9f7da0..02a298d7466aa 100644
--- a/lib/integrations/awsoidc/idp_iam_config.go
+++ b/lib/integrations/awsoidc/idp_iam_config.go
@@ -35,6 +35,7 @@ import (
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/integrations/awsoidc/tags"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -194,7 +195,7 @@ func NewIdPIAMConfigureClient(ctx context.Context) (IdPIAMConfigureClient, error
return &defaultIdPIAMConfigureClient{
httpClient: httpClient,
awsConfig: cfg,
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/integrations/awsoidc/listdatabases_iam_config.go b/lib/integrations/awsoidc/listdatabases_iam_config.go
index bec7e1a00de73..a2d5bd2edaa7f 100644
--- a/lib/integrations/awsoidc/listdatabases_iam_config.go
+++ b/lib/integrations/awsoidc/listdatabases_iam_config.go
@@ -29,6 +29,7 @@ import (
awslib "github.com/gravitational/teleport/lib/cloud/aws"
"github.com/gravitational/teleport/lib/cloud/provisioning"
"github.com/gravitational/teleport/lib/cloud/provisioning/awsactions"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -92,7 +93,7 @@ func NewListDatabasesIAMConfigureClient(ctx context.Context, region string) (Lis
}
return &defaultListDatabasesIAMConfigureClient{
- Client: iam.NewFromConfig(cfg),
+ Client: iamutils.NewFromConfig(cfg),
CallerIdentityGetter: stsutils.NewFromConfig(cfg),
}, nil
}
diff --git a/lib/srv/app/cloud.go b/lib/srv/app/cloud.go
index 0196cdff2faa0..a7726f49e972a 100644
--- a/lib/srv/app/cloud.go
+++ b/lib/srv/app/cloud.go
@@ -39,6 +39,7 @@ import (
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/lib/tlsca"
awsutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
// Cloud provides cloud provider access related methods such as generating
@@ -208,7 +209,7 @@ func (c *cloud) getAWSSigninToken(ctx context.Context, req *AWSSigninRequest, en
creds.ExternalID = aws.String(req.ExternalID)
}
})
- stsCredentials, err := stscreds.NewCredentials(session, req.Identity.RouteToApp.AWSRoleARN, options...).Get()
+ stsCredentials, err := stsutils.NewCredentialsV1(session, req.Identity.RouteToApp.AWSRoleARN, options...).Get()
if err != nil {
return "", trace.Wrap(err)
}
diff --git a/lib/utils/aws/fips_disabled.go b/lib/utils/aws/awsfips/fips_disabled.go
similarity index 89%
rename from lib/utils/aws/fips_disabled.go
rename to lib/utils/aws/awsfips/fips_disabled.go
index 6773a61413770..a041facc8c64e 100644
--- a/lib/utils/aws/fips_disabled.go
+++ b/lib/utils/aws/awsfips/fips_disabled.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-package aws
+package awsfips
import (
"os"
@@ -27,8 +27,8 @@ import (
// Either "yes" or a "truthy" value (as defined by [strconv.ParseBool]) are
// considered true.
//
-// Prefer using specific functions, such as those in the
-// lib/utils/aws/stsutils or lib/utils/aws/dynamodbutils packages.
+// Prefer using specific functions, such as those in lib/utils/aws/*
+// subpackages.
func IsFIPSDisabledByEnv() bool {
const envVar = "TELEPORT_UNSTABLE_DISABLE_AWS_FIPS"
diff --git a/lib/utils/aws/credentials.go b/lib/utils/aws/credentials.go
index 257d6606d42a9..83889135aa547 100644
--- a/lib/utils/aws/credentials.go
+++ b/lib/utils/aws/credentials.go
@@ -37,6 +37,7 @@ import (
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/utils"
+ "github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
// GetCredentialsRequest is the request for obtaining STS credentials.
@@ -72,7 +73,7 @@ func NewCredentialsGetter() CredentialsGetter {
// Get obtains STS credentials.
func (g *credentialsGetter) Get(_ context.Context, request GetCredentialsRequest) (*credentials.Credentials, error) {
logrus.Debugf("Creating STS session %q for %q.", request.SessionName, request.RoleARN)
- return stscreds.NewCredentials(request.Provider, request.RoleARN,
+ return stsutils.NewCredentialsV1(request.Provider, request.RoleARN,
func(cred *stscreds.AssumeRoleProvider) {
cred.RoleSessionName = MaybeHashRoleSessionName(request.SessionName)
cred.Expiry.SetExpiration(request.Expiry, 0)
diff --git a/lib/utils/aws/dynamodbutils/dynamo.go b/lib/utils/aws/dynamodbutils/dynamo.go
index 822ee28c3ce7d..7713e5936dcde 100644
--- a/lib/utils/aws/dynamodbutils/dynamo.go
+++ b/lib/utils/aws/dynamodbutils/dynamo.go
@@ -18,13 +18,13 @@ package dynamodbutils
import (
"github.com/gravitational/teleport/lib/modules"
- awsutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
)
// IsFIPSEnabled returns true if FIPS should be enabled for DynamoDB.
// FIPS is enabled is the binary is boring ([modules.Modules.IsBoringBinary])
// and if FIPS is not disabled by the environment
-// ([awsutils.IsFIPSDisabledByEnv]).
+// ([awsfips.IsFIPSDisabledByEnv]).
func IsFIPSEnabled() bool {
- return !awsutils.IsFIPSDisabledByEnv() && modules.GetModules().IsBoringBinary()
+ return !awsfips.IsFIPSDisabledByEnv() && modules.GetModules().IsBoringBinary()
}
diff --git a/lib/utils/aws/iamutils/iam.go b/lib/utils/aws/iamutils/iam.go
new file mode 100644
index 0000000000000..a4784d1cc467b
--- /dev/null
+++ b/lib/utils/aws/iamutils/iam.go
@@ -0,0 +1,38 @@
+// Teleport
+// Copyright (C) 2025 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package iamutils
+
+import (
+ "github.com/aws/aws-sdk-go-v2/aws"
+ "github.com/aws/aws-sdk-go-v2/service/iam"
+
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
+)
+
+// NewFromConfig wraps [iam.NewFromConfig] and applies FIPS settings
+// according to environment variables.
+//
+// See [awsfips.IsFIPSDisabledByEnv].
+func NewFromConfig(cfg aws.Config, optFns ...func(*iam.Options)) *iam.Client {
+ if awsfips.IsFIPSDisabledByEnv() {
+ // append so it overrides any preceding settings.
+ optFns = append(optFns, func(opts *iam.Options) {
+ opts.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled
+ })
+ }
+ return iam.NewFromConfig(cfg, optFns...)
+}
diff --git a/lib/utils/aws/iamutils/iam_test.go b/lib/utils/aws/iamutils/iam_test.go
new file mode 100644
index 0000000000000..73306674fd0be
--- /dev/null
+++ b/lib/utils/aws/iamutils/iam_test.go
@@ -0,0 +1,64 @@
+// Teleport
+// Copyright (C) 2025 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package iamutils_test
+
+import (
+ "testing"
+
+ "github.com/aws/aws-sdk-go-v2/aws"
+ "github.com/aws/aws-sdk-go-v2/service/iam"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
+)
+
+func TestNewFromConfig(t *testing.T) {
+ // Don't t.Parallel(), uses t.Setenv().
+
+ cfg := aws.Config{}
+ opts := func(opts *iam.Options) {
+ opts.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateEnabled
+ }
+
+ tests := []struct {
+ name string
+ envVarValue string // value for the _DISABLE_FIPS environment variable
+ want aws.FIPSEndpointState
+ }{
+ {
+ name: "fips",
+ want: aws.FIPSEndpointStateEnabled,
+ },
+ {
+ name: "fips disabled by env",
+ envVarValue: "yes",
+ want: aws.FIPSEndpointStateDisabled,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ t.Setenv("TELEPORT_UNSTABLE_DISABLE_AWS_FIPS", test.envVarValue)
+
+ iamClient := iamutils.NewFromConfig(cfg, opts)
+ require.NotNil(t, iamClient, "*iam.Client")
+
+ got := iamClient.Options().EndpointOptions.UseFIPSEndpoint
+ assert.Equal(t, test.want, got, "opts.EndpointOptions.UseFIPSEndpoint mismatch")
+ })
+ }
+}
diff --git a/lib/utils/aws/iamutils/iam_v1.go b/lib/utils/aws/iamutils/iam_v1.go
new file mode 100644
index 0000000000000..2cc63aec5f03d
--- /dev/null
+++ b/lib/utils/aws/iamutils/iam_v1.go
@@ -0,0 +1,37 @@
+// Teleport
+// Copyright (C) 2025 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package iamutils
+
+import (
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/client"
+ "github.com/aws/aws-sdk-go/service/iam"
+
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
+)
+
+// NewV1 wraps [iam.New] and applies FIPS settings according to environment
+// variables.
+//
+// See [awsfips.IsFIPSDisabledByEnv].
+func NewV1(p client.ConfigProvider, cfgs ...*aws.Config) *iam.IAM {
+ if awsfips.IsFIPSDisabledByEnv() {
+ // append so it overrides any preceding settings.
+ cfgs = append(cfgs, aws.NewConfig().WithUseFIPSEndpoint(false))
+ }
+ return iam.New(p, cfgs...)
+}
diff --git a/lib/utils/aws/iamutils/iam_v1_test.go b/lib/utils/aws/iamutils/iam_v1_test.go
new file mode 100644
index 0000000000000..ddffa2467187e
--- /dev/null
+++ b/lib/utils/aws/iamutils/iam_v1_test.go
@@ -0,0 +1,76 @@
+// Teleport
+// Copyright (C) 2025 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package iamutils_test
+
+import (
+ "testing"
+
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/client"
+ "github.com/aws/aws-sdk-go/aws/endpoints"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
+)
+
+func TestNewV1(t *testing.T) {
+ // Don't t.Parallel(), uses t.Setenv().
+
+ configProvider := &mockConfigProvider{
+ Config: client.Config{
+ Config: aws.NewConfig().WithUseFIPSEndpoint(true),
+ },
+ }
+
+ tests := []struct {
+ name string
+ envVarValue string // value for the _DISABLE_FIPS environment variable
+ want endpoints.FIPSEndpointState
+ }{
+ {
+ name: "fips",
+ want: endpoints.FIPSEndpointStateEnabled,
+ },
+ {
+ name: "fips disabled by env",
+ envVarValue: "yes",
+ want: endpoints.FIPSEndpointStateDisabled,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ t.Setenv("TELEPORT_UNSTABLE_DISABLE_AWS_FIPS", test.envVarValue)
+
+ iamClient := iamutils.NewV1(configProvider)
+ require.NotNil(t, iamClient, "*iam.IAM")
+
+ got := iamClient.Config.UseFIPSEndpoint
+ assert.Equal(t, test.want, got, "iamClient.Config.UseFIPSEndpoint mismatch")
+ })
+ }
+}
+
+type mockConfigProvider struct {
+ Config client.Config
+}
+
+func (m *mockConfigProvider) ClientConfig(_ string, cfgs ...*aws.Config) client.Config {
+ cc := m.Config
+ cc.Config = cc.Config.Copy(cfgs...)
+ return cc
+}
diff --git a/lib/utils/aws/stsutils/sts.go b/lib/utils/aws/stsutils/sts.go
index 70f3d63196dce..4020a4f50ebfe 100644
--- a/lib/utils/aws/stsutils/sts.go
+++ b/lib/utils/aws/stsutils/sts.go
@@ -20,15 +20,15 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/sts"
- awsutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
)
// NewFromConfig wraps [sts.NewFromConfig] and applies FIPS settings
// according to environment variables.
//
-// See [awsutils.IsFIPSDisabledByEnv].
+// See [awsfips.IsFIPSDisabledByEnv].
func NewFromConfig(cfg aws.Config, optFns ...func(*sts.Options)) *sts.Client {
- if awsutils.IsFIPSDisabledByEnv() {
+ if awsfips.IsFIPSDisabledByEnv() {
// append so it overrides any preceding settings.
optFns = append(optFns, func(opts *sts.Options) {
opts.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateDisabled
diff --git a/lib/utils/aws/stsutils/sts_v1.go b/lib/utils/aws/stsutils/sts_v1.go
index 3d17e272de847..b60d3715c8c31 100644
--- a/lib/utils/aws/stsutils/sts_v1.go
+++ b/lib/utils/aws/stsutils/sts_v1.go
@@ -21,15 +21,15 @@ import (
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/service/sts"
- awsutils "github.com/gravitational/teleport/lib/utils/aws"
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
)
// NewV1 wraps [sts.New] and applies FIPS settings according to environment
// variables.
//
-// See [awsutils.IsFIPSDisabledByEnv].
+// See [awsfips.IsFIPSDisabledByEnv].
func NewV1(p client.ConfigProvider, cfgs ...*aws.Config) *sts.STS {
- if awsutils.IsFIPSDisabledByEnv() {
+ if awsfips.IsFIPSDisabledByEnv() {
// append so it overrides any preceding settings.
cfgs = append(cfgs, aws.NewConfig().WithUseFIPSEndpoint(false))
}
diff --git a/lib/utils/aws/stsutils/stscreds_v1.go b/lib/utils/aws/stsutils/stscreds_v1.go
new file mode 100644
index 0000000000000..b8f2049aad884
--- /dev/null
+++ b/lib/utils/aws/stsutils/stscreds_v1.go
@@ -0,0 +1,51 @@
+// Teleport
+// Copyright (C) 2025 Gravitational, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package stsutils
+
+import (
+ "github.com/aws/aws-sdk-go/aws"
+ "github.com/aws/aws-sdk-go/aws/client"
+ "github.com/aws/aws-sdk-go/aws/credentials"
+ "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
+
+ "github.com/gravitational/teleport/lib/utils/aws/awsfips"
+)
+
+// NewCredentialsV1 wraps [stscreds.NewCredentials] and applies FIPS settings
+// according to environment variables.
+//
+// See [awsfips.IsFIPSDisabledByEnv].
+func NewCredentialsV1(
+ c client.ConfigProvider,
+ roleARN string,
+ options ...func(*stscreds.AssumeRoleProvider),
+) *credentials.Credentials {
+ if awsfips.IsFIPSDisabledByEnv() {
+ c = fipsDisabledProvider{provider: c}
+ }
+ return stscreds.NewCredentials(c, roleARN, options...)
+}
+
+type fipsDisabledProvider struct {
+ provider client.ConfigProvider
+}
+
+func (p fipsDisabledProvider) ClientConfig(serviceName string, cfgs ...*aws.Config) client.Config {
+ cfgs = append(cfgs, aws.NewConfig().WithUseFIPSEndpoint(false))
+ cfg := p.provider.ClientConfig(serviceName, cfgs...)
+ return cfg
+}
diff --git a/tool/teleport/common/integration_configure.go b/tool/teleport/common/integration_configure.go
index 79e9275f17c91..6ebf3d65343e5 100644
--- a/tool/teleport/common/integration_configure.go
+++ b/tool/teleport/common/integration_configure.go
@@ -26,7 +26,6 @@ import (
awsConfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/athena"
"github.com/aws/aws-sdk-go-v2/service/glue"
- "github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/gravitational/trace"
@@ -40,6 +39,7 @@ import (
"github.com/gravitational/teleport/lib/integrations/samlidp"
"github.com/gravitational/teleport/lib/integrations/samlidp/samlidpconfig"
"github.com/gravitational/teleport/lib/utils"
+ "github.com/gravitational/teleport/lib/utils/aws/iamutils"
"github.com/gravitational/teleport/lib/utils/aws/stsutils"
)
@@ -218,7 +218,7 @@ func onIntegrationConfExternalAuditCmd(ctx context.Context, params easconfig.Ext
}
clt := &awsoidc.DefaultConfigureExternalAuditStorageClient{
- Iam: iam.NewFromConfig(cfg),
+ Iam: iamutils.NewFromConfig(cfg),
Sts: stsutils.NewFromConfig(cfg),
}
return trace.Wrap(awsoidc.ConfigureExternalAuditStorage(ctx, clt, params))