-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Fix broken multi-account/multi-region functionality #9541
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
Conversation
|
|
||
| # create target S3 bucket | ||
| aws_client.s3.create_bucket(Bucket=bucket_name) | ||
| s3_create_bucket(Bucket=bucket_name) |
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.
Using this fixture ensures the the appropriate LocationConstraint is added automatically.
| monkeypatch.setattr(config, "SQS_ENDPOINT_STRATEGY", strategy) | ||
|
|
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.
The parametrized value for SQS endpoint strategy was not being taken into account.
89d8626 to
4173d4f
Compare
| Principal=f"logs.{TEST_AWS_REGION_NAME}.amazonaws.com", | ||
| Action="lambda:InvokeFunction", | ||
| SourceArn=f"arn:aws:logs:{config.AWS_REGION_US_EAST_1}:{account_id}:log-group:{logs_log_group}:*", | ||
| SourceArn=f"arn:aws:logs:{TEST_AWS_REGION_NAME}:{account_id}:log-group:{logs_log_group}:*", |
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.
Assertions expected the us-east-1 region even when the resources were created in a different region (by setting TEST_AWS_REGION_NAME)
TO BE REVERTED BEFORE MERGE
localstack/services/logs/provider.py
Outdated
| client = connect_to().firehose | ||
| client = connect_to( | ||
| aws_access_key_id=arn_data["account"], region_name=arn_data["region"] | ||
| ).firehose |
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.
Ensures logs are sent to correct account and region.
Identified in following tests:
- test_put_subscription_filter_lambda
- test_put_subscription_filter_firehose
- test_put_subscription_filter_kinesis
|
|
||
| # assert ARN formats | ||
| expected_arn_prefix = "arn:aws:dynamodb:" + aws_stack.get_local_region() | ||
| expected_arn_prefix = "arn:aws:dynamodb:" + TEST_AWS_REGION_NAME |
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.
Ensures expected value is correctly constructed.
Fixes this test: test_stream_spec_and_region_replacement
| assert result["ResponseMetadata"]["HTTPStatusCode"] == 200 | ||
| assert result["loggingConfiguration"] == {"level": "OFF", "includeExecutionData": False} | ||
| finally: | ||
| custom_client.stepfunctions.delete_state_machine(stateMachineArn=result["stateMachineArn"]) |
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.
The test did not use custom_client to create the statemachine and then failed during retrieval using this client.
Affected test: test_default_logging_configuration
| queue_url = sqs_create_queue(QueueName=queue_name) | ||
| account_id, region_name, queue_name_from_url = parse_queue_url(queue_url) | ||
| assert account_id == DEFAULT_AWS_ACCOUNT_ID | ||
| assert account_id == TEST_AWS_ACCOUNT_ID |
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.
Assertion was done against the wrong account
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.
Nice changes! I have some comments regarding the lambda changes, I'd also like the opinion of @dfangl (for IAM, maybe future?) or maybe a lambda service owner, but I believe we should use the ARN there. Good catch for the S3 buckets as well, more cleanups! 🧹
What about the default region changes? I believe some of the test logic was always expecting us-east-1 to be the default, especially for S3, and snapshots might need to be regenerated.
localstack/services/logs/provider.py
Outdated
| if ":lambda:" in destination_arn: | ||
| client = connect_to(region_name=extract_region_from_arn(destination_arn)).lambda_ | ||
| client = connect_to( | ||
| aws_access_key_id=arn_data["account"], region_name=arn_data["region"] | ||
| ).lambda_ | ||
| lambda_name = arns.lambda_function_name(destination_arn) | ||
| client.invoke(FunctionName=lambda_name, Payload=json.dumps(event)) |
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.
Same as commented above, I believe we shouldn't extract the lambda function name but use the ARN to invoke the function:
client = connect_to(region_name=extract_region_from_arn(destination_arn)).lambda_
client.invoke(FunctionName=destination_arn, Payload=json.dumps(event))|
Thanks for the tag @bentsku ! You are right, for cross account/region requests which are done on behalf of the service, we should definitely work on having the proper account just in the request body as the target resource, and use the request metadata to set the service name, instead of setting the account id as access key id. If we do the latter, IAM for example would not detect it as a cross-account request, as the originating account is the same as the targets. Ideally, all services extract the account id from the arn if provided, to access the correct account. |
160bfa8 to
ebdcceb
Compare
This reverts commit 9589c56.
bentsku
left a comment
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.
LGTM! This is looking great! thanks for addressing the comments! There's just this part with the role and with_assumed_role and the else part which I'm not sure I understand the intricacies, but the rest is all good to me!
There's just 2 S3 tests that are not cleaning up due to the use of localstack.utils.aws.resources.create_s3_bucket now. Maybe we could add its cleanup to the cleanups fixture.
Thanks a lot again for all of these fixes! 🚀
| else: | ||
| factory = connect_to(aws_access_key_id=arn_data["account"], region_name=arn_data["region"]) |
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.
q: is this a fallback? this whole with_assumed_role addition is looking really nice 😄 I lack some knowledge in the IAM part, so this kind of things I don't feel qualified enough to review.
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.
You're correct, if a role ARN is available, IAM enforcement can be performed. Else there is a fallback.
This usage is similar to elsewhere, eg:
localstack/localstack/services/sns/publisher.py
Lines 646 to 652 in 05832fc
| if role_arn := subscriber.get("SubscriptionRoleArn"): | |
| factory = connect_to.with_assumed_role( | |
| role_arn=role_arn, service_principal=ServicePrincipal.sns, region_name=region | |
| ) | |
| else: | |
| account_id = extract_account_id_from_arn(subscriber["Endpoint"]) | |
| factory = connect_to(aws_access_key_id=account_id, region_name=region) |
or
localstack/localstack/services/firehose/provider.py
Lines 734 to 739 in 05832fc
| if role_arn := s3_destination_description.get("RoleARN"): | |
| factory = connect_to.with_assumed_role( | |
| role_arn=role_arn, service_principal=ServicePrincipal.firehose | |
| ) | |
| else: | |
| factory = connect_to() |
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.
IAM enforcement can be performed in both cases. However, only if the aws_access_key_id is set to the INTERNAL_AWS_ACCESS_KEY_ID value. There should be no case, other than resource creation, to set the account id as access key id for internal clients, in my opinion. The first snippet by viren for example leads to no IAM enforcement in the else case, which is neither parity nor should happen.
4cf4e20 to
17c34bd
Compare
Motivation
This PR fixes multi-account/multi-region region functionality that misbehave in non-default region and accounts.
In effect, fixes following tests: