-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate eks discovery to aws sdk v2 #50603
base: master
Are you sure you want to change the base?
Conversation
e270e36
to
6432b9a
Compare
6432b9a
to
03fd997
Compare
e662c31
to
3f265de
Compare
2c56eb2
to
8de9fdc
Compare
7174944
to
d968a0e
Compare
lib/kube/proxy/cluster_details.go
Outdated
// ClientGetter is an interface for getting an EKS client and an STS client. | ||
type ClientGetter interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this intended to only ever be for retrieving AWS clients? If so should this be renamed to reflect that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote for the same
lib/kube/proxy/cluster_details.go
Outdated
// TODO(@GavinFrazar): Re-enable this when session cache v2 gets merged (#50561). | ||
// awsconfig.WithoutSessionCache(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#50561 was merged earlier today
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be worth mentioning #50809 as well, though I'm not sure it applies here - you can just call awsconfig.GetConfig
, which is not cached, instead of using awsconfig.Cache
.
for k, v := range cfg.eksCluster.Tags { | ||
eksTags[k] = aws.String(v) | ||
eksTags[k] = v | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use maps.Clone/Copy now?
lib/kube/proxy/cluster_details.go
Outdated
// ClientGetter is an interface for getting an EKS client and an STS client. | ||
type ClientGetter interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote for the same
type EKSClient interface { | ||
eks.DescribeClusterAPIClient | ||
} | ||
|
||
// STSClient is the subset of the STS Client interface we use. | ||
type STSClient interface { | ||
stscreds.AssumeRoleAPIClient | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If our goal is to expose on those two interfaces, why not referring them directly?
This is mostly internal packages and I don't see them being expanded in the future
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is easier to have them split as one is implemented by sts.Client the other by eks.Client, used in different places.
lib/kube/proxy/cluster_details.go
Outdated
opts := []awsconfig.OptionsFn{ | ||
awsconfig.WithAmbientCredentials(), | ||
// TODO(@GavinFrazar): Re-enable this when session cache v2 gets merged (#50561). | ||
// awsconfig.WithoutSessionCache(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need this merged otherwise we will introduce the same bug #50074 again
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not going through cache in this case, since the ClientGetter
is calling the uncached awsconfig.GetConfig
free function:
func (*awsClientsGetter) getAWSConfig(ctx context.Context, region string, opts ...awsconfig.OptionsFn) (aws.Config, error) {
cfg, err := awsconfig.GetConfig(ctx, region, opts...)
return cfg, trace.Wrap(err)
}
I think the expiry time returned from GenAWSEKSToken
should be taken from the underlying aws.Credentials expiry instead of the 14 minute const, but just skipping the cache works too
lib/kube/proxy/server.go
Outdated
@@ -74,6 +78,7 @@ type TLSServerConfig struct { | |||
OnReconcile func(types.KubeClusters) | |||
// CloudClients is a set of cloud clients that Teleport supports. | |||
CloudClients cloud.Clients | |||
AWSClients *awsClientsGetter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a private structure w/out any way of building it, does it make sense for the field to public?
// GenAWSEKSToken creates an AWS token to access EKS clusters. | ||
// Logic from https://github.com/aws/aws-cli/blob/6c0d168f0b44136fc6175c57c090d4b115437ad1/awscli/customizations/eks/get_token.py#L211-L229 | ||
func GenAWSEKSToken(stsClient stsiface.STSAPI, clusterID string, clock clockwork.Clock) (string, time.Time, error) { | ||
func GenAWSEKSToken(ctx context.Context, stsClient STSPresignClient, clusterID string, clock clockwork.Clock) (string, time.Time, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now that this package was converted to sdkv2, we can make unify
teleport/lib/integrations/awsoidc/eks_enroll_clusters.go
Lines 341 to 372 in d37da51
func presignCallerIdentityURL(ctx context.Context, stsClient *sts.Client, clusterName string) (string, error) { | |
presignClient := sts.NewPresignClient(stsClient) | |
// This function adds required headers for accessing an EKS cluster to the presigned URL. | |
// Header "x-k8s-aws-id" specifies EKS cluster name and header "X-Amz-Expires" is just required for compatibility reasons. | |
addEKSHeaders := func(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) ( | |
out middleware.BuildOutput, metadata middleware.Metadata, err error, | |
) { | |
req, ok := in.Request.(*smithyhttp.Request) | |
if !ok { | |
return out, metadata, fmt.Errorf("unknown transport type %T", req) | |
} | |
req.Header.Add(awsHeaderClusterName, clusterName) | |
// 60 is put for compatibility reasons, in reality it is ignored and real expiration time is 15 minutes. | |
req.Header.Add(awsHeaderExpires, "60") | |
return next.HandleBuild(ctx, in) | |
} | |
presigned, err := presignClient.PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}, func(options *sts.PresignOptions) { | |
options.ClientOptions = append(options.ClientOptions, | |
sts.WithAPIOptions(func(stack *middleware.Stack) error { | |
return stack.Build.Add(middleware.BuildMiddlewareFunc("AddEKSHeaders", addEKSHeaders), 0) | |
})) | |
}) | |
if err != nil { | |
return "", trace.Wrap(err, "failed to presign caller identity") | |
} | |
return presigned.URL, nil | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are essentially doing the same thing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe better in a separate PR as the integration one requires a full blown sts Client, which would be difficult to test. Added a TODO.
lib/srv/discovery/discovery.go
Outdated
@@ -115,6 +117,13 @@ type gcpInstaller interface { | |||
type Config struct { | |||
// CloudClients is an interface for retrieving cloud clients. | |||
CloudClients cloud.Clients | |||
|
|||
// FetchersClients gets the AWS clients for the given region for the fetchers. | |||
FetchersClients fetchers.ClientGetter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IF we reserve FetchersClients for AWS, it should be more clear about it.
We should probably also split the cloud clients as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the idea indeed, EC2 and SSM have been split out from cloud clients already, this extracts out completely EKS and partially STS. I'll rename to be more explicit about AWS.
lib/srv/discovery/discovery.go
Outdated
c *Config | ||
} | ||
|
||
func (f *fetchersClientsGetter) GetAWSEKSClient(ctx context.Context, region string, opts ...awsconfig.OptionsFn) (fetchers.EKSClient, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend just making these into simple functions that take an aws.Config
and return the relevant interface, and using the awsconfig.Provider
along side them instead.
Then in tests you just set Config.AWSConfigProvider
to &mocks.AWSConfigProvider{}
to mock out the config loading
It's a little more tedious/ceremony because you end up doing this:
awsCfg, err := foo.getAWSConfig(...options...)
if err != nil {
...
}
barClt := foo.GetBarClient(awsCfg)
But the benefit is that you always test the options passed to getAWSConfig
, and each client can be mocked separately as a trivial function rather than trying to fake config loading in each mock client provider.
I nitpick on this because the sdk v1 cloud clients code was structured like you've done so here and I've found that tests end up faking more than they should, e.g not checking the credentials source at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed #48950 model 😅 we probably should align everything. Should it be done upfront here though, or in a separate PR?
Closes #49129
Removes all usage of sdk v1 for EKS.