Skip to content

Enable EventBridge API destinations and connections #11896

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

Merged
merged 9 commits into from
Nov 22, 2024

Conversation

dfangl
Copy link
Member

@dfangl dfangl commented Nov 21, 2024

Motivation

In the current v2 provider, we do not support eventbridge API destinations.

As we do want this in 4.0.1, and I am unsure if we should do such a big code change, I staggered the commits in terms of escalating changes / complexity.

93822dd has the minimal changes necessary to make the feature work, we could cherry pick that into a separate PR.

After this commit, we increasingly increase parity, with more snapshots, creation of eventbridge secrets, bypass of secretmanager name assertions (since official EventBridge secrets contain a ! in the name).

It might be too much for a release tomorrow, but I will let the reviewers judge that.

Changes

  • Allow persistence for connections and api destinations by moving them into the store (very simply, without dataclasses as for other models)
  • Detect API destinations and forward events correctly
  • Connections now correctly create secrets in secretsmanager for connection secrets
  • Change snapshot transformers to add more assertions on the structure of ARNs
  • Some minor testing improvements, to increase reliability of the tests (against AWS)
  • Move the snapshots to an autouse fixture, to be able to use the snapshot name directly (honestly a preference, but I did quite some work in the tests)
  • Add more snapshot on the event secrets
  • Unskip test for api destinations
  • Fix partitions in some ARNs

…re (for now), quick copy of send_event_to_api_destination to get values from new store
@dfangl dfangl added this to the 4.0.1 milestone Nov 21, 2024
@dfangl dfangl added the semver: patch Non-breaking changes which can be included in patch releases label Nov 21, 2024
@dfangl dfangl self-assigned this Nov 21, 2024
@dfangl dfangl marked this pull request as draft November 21, 2024 13:48
@dfangl dfangl marked this pull request as ready for review November 21, 2024 16:33
Comment on lines +176 to +187
# Some providers need to create keys which are not usually creatable by users
if not any(
tag_entry["Key"] == "BYPASS_SECRET_ID_VALIDATION"
for tag_entry in request.get("Tags", [])
):
self._raise_if_invalid_secret_id(request["Name"])
else:
request["Tags"] = [
tag_entry
for tag_entry in request.get("Tags", [])
if tag_entry["Key"] != "BYPASS_SECRET_ID_VALIDATION"
]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We sadly need something to bypass the name validation here, as eventbridge connection secrets contain a !, which is not allowed. I used a tag here, but there are other options should we decide against it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which is not allowed

I'm not sure I'm following here. Not allowed as in our SecretsManager service should support it, but doesn't? Or how would this otherwise work on AWS?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are AWS services able to create keys with names that we (as external users) can't?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that way. The error message clearly states it should not be allowed, the aws console also does not allow it. So maybe aws services have some bypass for it.

Copy link

LocalStack Community integration with Pro

    2 files  ±0      2 suites  ±0   1h 43m 49s ⏱️ + 2m 11s
3 568 tests +3  3 235 ✅ +6  333 💤  - 3  0 ❌ ±0 
3 570 runs  +3  3 235 ✅ +6  335 💤  - 3  0 ❌ ±0 

Results for commit 02baf71. ± Comparison against base commit 6748e0e.

Copy link
Member

@dominikschubert dominikschubert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🏆 Think it's a good idea to move from the transient state in the provider to directly using the entities from the store. Much simpler and less error-prone.

The somewhat weird workaround with the secret names might be worth looking into later again. Maybe we can just detect it as an internal call via headers/request context and then allow arbitrary keys? We can discuss this at a later date though.

@@ -1754,7 +1754,7 @@
]
}
},
"tests/aws/services/events/test_events.py::TestEvents::test_create_connection_validations": {
"tests/aws/services/events/test_events.py::TestEvents::test_create_connection_validations": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: interesting 🤨

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn’t notice that, that is really interesting. Did someone manually mess with this file?

"recorded-content": {
"create-connection": {
"ConnectionArn": "connection-arn",
"ConnectionArn": "arn:<partition>:events:<region>:111111111111:connection/<connection-name>/<resource:1>",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️: nice attention to detail with the ARN decomposition in the snapshots 🙌

"LastAuthorizedTime": "datetime",
"LastModifiedTime": "datetime",
"Name": "<connection-name>",
"SecretArn": "arn:<partition>:secretsmanager:<region>:111111111111:secret:events!connection/<connection-name>/<secret-uuid>-<secret-id-suffix>",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment: that ! is certainly an interesting choice on AWS's side

Comment on lines +569 to +574
yield _create_connection

try:
aws_client.events.delete_connection(Name=connection_name)
except Exception as e:
LOG.debug("Error cleaning up connection: %s", e)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch. Kinda reminding me of the fact that it might be nice to revive the client-based cleanups at some point 😁

Comment on lines +176 to +187
# Some providers need to create keys which are not usually creatable by users
if not any(
tag_entry["Key"] == "BYPASS_SECRET_ID_VALIDATION"
for tag_entry in request.get("Tags", [])
):
self._raise_if_invalid_secret_id(request["Name"])
else:
request["Tags"] = [
tag_entry
for tag_entry in request.get("Tags", [])
if tag_entry["Key"] != "BYPASS_SECRET_ID_VALIDATION"
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which is not allowed

I'm not sure I'm following here. Not allowed as in our SecretsManager service should support it, but doesn't? Or how would this otherwise work on AWS?

Comment on lines +1931 to +1934
@pytest.mark.skipif(
is_old_provider(),
reason="V1 provider does not support this feature",
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dfangl going above and beyond 🚀

Comment on lines +230 to +231
ConnectionDict = dict[ConnectionName, DescribeConnectionResponse]
ApiDestinationDict = dict[ApiDestinationName, DescribeApiDestinationResponse]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess that's something for service owners to judge, but I don't see this blocking for this iteration.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really a temporary shortcut to get some typing, I would also think this needs another iteration at some point.

@@ -390,6 +391,10 @@ class EventsTargetSender(TargetSender):
def send_event(self, event):
# TODO add validation and tests for eventbridge to eventbridge requires Detail, DetailType, and Source
# https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/events/client/put_events.html
target_arn = self.target["Arn"]
if ":api-destination/" in target_arn or ":destination/" in target_arn:
send_event_to_api_destination(target_arn, event, self.target.get("HttpParameters"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxhoheiser Might be something were instrumentation for EventStudio might be a good idea in a follow up

Comment on lines +382 to +383
# TODO use service role as described here: https://docs.aws.amazon.com/eventbridge/latest/userguide/using-service-linked-roles-service-action-1.html
# not too important as it is created automatically on AWS anyway, with the right permissions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even when using the API or only via the AWS Console?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also be the case with the api.

@@ -339,33 +338,112 @@ def _create_connection_arn(
self, context: RequestContext, name: str, connection_uuid: str
) -> str:
"""Create a standardized connection ARN."""
return f"arn:aws:events:{context.region}:{context.account_id}:connection/{name}/{connection_uuid}"
return f"arn:{get_partition(context.region)}:events:{context.region}:{context.account_id}:connection/{name}/{connection_uuid}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch here as well 👍

Copy link
Member

@joe4dev joe4dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀 Thanks a lot @dfangl

@dominikschubert dominikschubert merged commit 7c2d1e3 into master Nov 22, 2024
32 checks passed
@dominikschubert dominikschubert deleted the events/connections branch November 22, 2024 08:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver: patch Non-breaking changes which can be included in patch releases
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants