allow using assumeRoleChain with IAM resources - #451
Conversation
435addc to
ffc0bac
Compare
|
|
||
| // AssumeRoleSTSRegion defines the region used for STS requests. If not defined, | ||
| // the managed resource region will be used if available | ||
| AssumeRoleSTSRegion *string `json:"assumeRoleSTSRegion,omitempty"` |
There was a problem hiding this comment.
An alternative to consider would be to add the the STS region option to the v1beta1.AssumeRoleOptions type. Then, the ProviderConfig would look like:
...
spec:
assumeRoleChain:
- stsRegion: us-west-1
roleARN: <role ARN 1>
- stsRegion: us-west-1
roleARN: <role ARN 2>
credentials:
secretRef:
key: creds
name: aws-creds
namespace: upbound-system
source: SecretHowever, you'd need to configure an STS region for each role in the chain if you are provisioning a resource without a region (e.g., IAM role) and not sure if there's utility in configuring different STS regions for different roles in the chain. Of course, if needed, we could have both levels of API exposed, e.g., a spec.assumeRoleSTSRegion and spec.assumeRoleChain[].stsRegion (which we could add later if needed). So, I think the proposed API is fine. What do you think?
There was a problem hiding this comment.
my first idea was also to put it in v1beta1.AssumeRoleOptions, but then I moved it because I didn't think there would be a need to chain assume role requests across different regions. I definitely would have rather put it inside an assumeRole config, but the current structure doesn't really support that. so I think this is probably the best option
There was a problem hiding this comment.
As a side note for documentation purposes, we had also previously discussed defaulting to a region specified in the ProviderConfig if a managed resource does not specify an optional spec.forProvider.region. The discussion's context was not this PR's target issue (but rather the UX around provider-aws MR APIs). But looks like it's also related to the current discussion.
|
|
||
| // AssumeRoleSTSRegion defines the region used for STS requests. If not defined, | ||
| // the managed resource region will be used if available | ||
| AssumeRoleSTSRegion *string `json:"assumeRoleSTSRegion,omitempty"` |
There was a problem hiding this comment.
nit: We may give an example of the new API under examples/providerconfig/, e.g., in examples/providerconfig/user-creds-with-assume-role.yaml or in a new example file.
|
/test-examples="examples/ec2/vpc.yaml" |
|
thank you for the review @ulucinar. let me know if you have more thoughts on this |
|
/test-examples="examples/ec2/vpc.yaml" |
| regionOpt := func(o *sts.Options) { | ||
| if pcs.AssumeRoleSTSRegion != nil { | ||
| o.Region = *pcs.AssumeRoleSTSRegion | ||
| } | ||
| } |
There was a problem hiding this comment.
@ctkeyser @ulucinar I wonder if it would make sense to fall back to the AWS global partition here if an STS region is not defined? The AWS SDK itself will do so if it does not recognize the region that is passed, but will error if no region is passed. Thoughts?
There was a problem hiding this comment.
that sounds good to me, but I'm not sure what that change looks like. I tried changing region to global and aws-global and I ended up getting errors saying dns doesn't resolve for sts.aws-global.amazonaws.com or sts.global.amazonaws.com. dns does resolve for sts.us-west-1.amazonaws.com though
I also don't see STS in this list of global endpoints https://docs.aws.amazon.com/general/latest/gr/rande.html#global-endpoints
There was a problem hiding this comment.
@ctkeyser I believe it may just be sts.amazonaws.com https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html
There was a problem hiding this comment.
ok I tested just falling back to aws-global if no region set, and that does work in my environment:
--- a/internal/clients/provider_config.go
+++ b/internal/clients/provider_config.go
@@ -265,8 +265,8 @@ func UseProviderSecret(ctx context.Context, data []byte, profile, region string)
func GetRoleChainConfig(ctx context.Context, pcs *v1beta1.ProviderConfigSpec, cfg *aws.Config) (*aws.Config, error) {
pCfg := cfg
regionOpt := func(o *sts.Options) {
- if pcs.AssumeRoleSTSRegion != nil {
- o.Region = *pcs.AssumeRoleSTSRegion
+ if cfg.Region == "" {
+ o.Region = GlobalRegion
}
}
for _, aro := range pcs.AssumeRoleChain {I was able to assume a role and create an IAM resource with that
I also tried changing getRegion to return GlobalRegion if no region was found in the managed resource, but that didn't work. got the error:
managed/iam.aws.upbound.io/v1beta1, kind=role cannot run refresh: refresh failed: Invalid AWS Region: aws-global
do you guys think this is good enough and we don't need the providerconfig option? so basically any region-less managed resource will use aws-global for STS. that seems simple enough to me
There was a problem hiding this comment.
This seems reasonable to me -- we can always expand the API of ProviderConfig if needed. So in summary:
- If an assume role chain is being used and the MR specifies a region, we will use that region endpoint for the STS operations.
- If chain is being used and the MR does not specify a region, we use the global STS endpoint.
I think potentially using a separate region's STS endpoint could be desired by a user, but let's wait until it is requested since it involves API expansion. Are you aligned @ulucinar?
There was a problem hiding this comment.
I don't know much about the use cases here. But one hypothetical scenario I may imagine is what happens if networking access to the host sts.amazonaws.com is blocked (due to law, temporary issue, etc.). But my understanding is that it (role chaining) was not working up to now for region-less resources and if we make a backward-compatible change (i.e., only revert back to sts.amazonaws.com for role chaining if the MR does not specify a region), we should not be breaking any existing (already working) scenarios and would be solving the problem for at least a subset of the users (of provider-aws).
So, I think we are good to go. But to be on the safe side, even if, currently, we will not allow configuration of the STS region for region-less resources, let's scope the change only for region-less resources (so that the change is backward-compatible as discussed above).
There was a problem hiding this comment.
ok I pushed the change. it only sets the region to aws-global for STS requests when no region is set, so it should only occur in situations where it currently doesn't work at all
|
/test-examples="examples/ec2/vpc.yaml" |
| regionOpt := func(o *sts.Options) { | ||
| if cfg.Region == "" { | ||
| o.Region = GlobalRegion | ||
| } | ||
| } |
There was a problem hiding this comment.
might be nice to pull this out into something like:
NewRegionFallbackOpt(region string) func(*sts.Options) {
if region != "" {
return func(*sts.Options) {}
}
return func(o *sts.Options) {
o.Region = GlobalRegion
}
}But I am fine with deferring doing so for now.
|
@hasheddan should I squash and force-push or is squash+merge preferred? |
|
@ctkeyser squash and force push would be great if you don't mind! |
ddfcdf1 to
fa0eafb
Compare
|
I'll go ahead and merge here since @ulucinar previously approved and indicated alignment on the updated direction 👍🏻 |
Description of your changes
Fixes #215
currently assumeRoleChain doesn't work for IAM resources because IAM resources don't require a region. the error is
this change adds a fallback to "aws-global" region for STS requests in cases where no region is set in the managed resource
I have:
make reviewable testto ensure this PR is ready for review.How has this code been tested
I built the provider w/ the fix, installed it in my environment, and confirmed I no longer get the 'region is required' error