diff --git a/.cfnlintrc.yaml b/.cfnlintrc.yaml index e3c59116f..a5a54820e 100644 --- a/.cfnlintrc.yaml +++ b/.cfnlintrc.yaml @@ -85,6 +85,7 @@ ignore_templates: - tests/translator/output/**/function_with_event_dest_conditional.json - tests/translator/output/**/function_with_event_schedule_state.json - tests/translator/output/**/function_with_file_system_config.json + - tests/translator/output/**/function_with_event_filtering.json # TODO: remove once Event's KmsKeyArn is available - tests/translator/output/**/function_with_function_url_config_conditions.json - tests/translator/output/**/function_with_globals_role_path.json - tests/translator/output/**/function_with_intrinsic_architecture.json diff --git a/integration/resources/expected/single/basic_function_with_event_filtering_using_kms.json b/integration/resources/expected/single/basic_function_with_event_filtering_using_kms.json new file mode 100644 index 000000000..e8d5caee9 --- /dev/null +++ b/integration/resources/expected/single/basic_function_with_event_filtering_using_kms.json @@ -0,0 +1,22 @@ +[ + { + "LogicalResourceId": "BasicFunctionWithEventFilteringUsingKmsKeyArn", + "ResourceType": "AWS::Lambda::Function" + }, + { + "LogicalResourceId": "BasicFunctionWithEventFilteringUsingKmsKeyArnRole", + "ResourceType": "AWS::IAM::Role" + }, + { + "LogicalResourceId": "MyKey", + "ResourceType": "AWS::KMS::Key" + }, + { + "LogicalResourceId": "MySqsQueue", + "ResourceType": "AWS::SQS::Queue" + }, + { + "LogicalResourceId": "BasicFunctionWithEventFilteringUsingKmsKeyArnMySqsEvent", + "ResourceType": "AWS::Lambda::EventSourceMapping" + } +] diff --git a/integration/resources/templates/single/basic_function_with_event_filtering_using_kms.yaml b/integration/resources/templates/single/basic_function_with_event_filtering_using_kms.yaml new file mode 100644 index 000000000..8c663fb8a --- /dev/null +++ b/integration/resources/templates/single/basic_function_with_event_filtering_using_kms.yaml @@ -0,0 +1,45 @@ +Resources: + BasicFunctionWithEventFilteringUsingKmsKeyArn: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + Runtime: nodejs18.x + CodeUri: ${codeuri} + MemorySize: 128 + Events: + MySqsEvent: + Type: SQS + Properties: + Queue: !GetAtt MySqsQueue.Arn + FilterCriteria: + Filters: + - Pattern: '{ "body" : { "RequestCode" : [ "BBBB" ] } }' + KmsKeyArn: !GetAtt MyKey.Arn + + MyKey: + Type: AWS::KMS::Key + Properties: + Description: A sample key + KeyPolicy: + Version: '2012-10-17' + Id: key-default-1 + Statement: + - Sid: Allow administration of the key + Effect: Allow + Principal: + AWS: !Sub arn:${AWS::Partition}:iam::${AWS::AccountId}:root + Action: + - kms:* + Resource: '*' + - Sid: Allow encryption/decryption access to Lambda Service Principal + Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: kms:Decrypt + Resource: '*' + + MySqsQueue: + Type: AWS::SQS::Queue + +Metadata: + SamTransformTest: true diff --git a/integration/single/test_basic_function.py b/integration/single/test_basic_function.py index 0c77bc708..5678130c6 100644 --- a/integration/single/test_basic_function.py +++ b/integration/single/test_basic_function.py @@ -274,6 +274,28 @@ def test_basic_function_with_tracing(self): "Expecting tracing config mode to be set to PassThrough.", ) + # TODO: add the integration test back after the feature launch on 06/05 + # @skipIf(current_region_does_not_support([KMS]), "KMS is not supported in this testing region") + # def test_basic_function_with_event_filtering_using_kms(self): + # """ + # Creates a basic lambda function with KMS key arn + # """ + # self.create_and_verify_stack("single/basic_function_with_event_filtering_using_kms") + + # lambda_function_name = self.get_physical_id_by_type("AWS::Lambda::Function") + # event_source_mappings = self.client_provider.lambda_client.list_event_source_mappings( + # FunctionName=lambda_function_name + # ) + + # event_source_mapping = event_source_mappings["EventSourceMappings"][0] + # function_uuid = event_source_mapping["UUID"] + + # event_source_mapping_config = self.client_provider.lambda_client.get_event_source_mapping(UUID=function_uuid) + + # kms_key_arn = event_source_mapping_config["KMSKeyArn"] + + # self.assertIsNotNone(kms_key_arn, "Expecting KmsKeyArn to be set.") + def _assert_invoke(self, lambda_client, function_name, qualifier=None, expected_status_code=200): """ Assert if a Lambda invocation returns the expected status code diff --git a/samtranslator/internal/schema_source/aws_serverless_function.py b/samtranslator/internal/schema_source/aws_serverless_function.py index 3e5f18f05..74c252dce 100644 --- a/samtranslator/internal/schema_source/aws_serverless_function.py +++ b/samtranslator/internal/schema_source/aws_serverless_function.py @@ -169,6 +169,7 @@ class KinesisEventProperties(BaseModel): Enabled: Optional[PassThroughProp] = kinesiseventproperties("Enabled") FilterCriteria: Optional[PassThroughProp] = kinesiseventproperties("FilterCriteria") FunctionResponseTypes: Optional[PassThroughProp] = kinesiseventproperties("FunctionResponseTypes") + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation MaximumBatchingWindowInSeconds: Optional[PassThroughProp] = kinesiseventproperties("MaximumBatchingWindowInSeconds") MaximumRecordAgeInSeconds: Optional[PassThroughProp] = kinesiseventproperties("MaximumRecordAgeInSeconds") MaximumRetryAttempts: Optional[PassThroughProp] = kinesiseventproperties("MaximumRetryAttempts") @@ -191,6 +192,7 @@ class DynamoDBEventProperties(BaseModel): Enabled: Optional[PassThroughProp] = dynamodbeventproperties("Enabled") FilterCriteria: Optional[PassThroughProp] = dynamodbeventproperties("FilterCriteria") FunctionResponseTypes: Optional[PassThroughProp] = dynamodbeventproperties("FunctionResponseTypes") + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation MaximumBatchingWindowInSeconds: Optional[PassThroughProp] = dynamodbeventproperties( "MaximumBatchingWindowInSeconds" ) @@ -235,6 +237,7 @@ class SQSEventProperties(BaseModel): Enabled: Optional[PassThroughProp] = sqseventproperties("Enabled") FilterCriteria: Optional[PassThroughProp] = sqseventproperties("FilterCriteria") FunctionResponseTypes: Optional[PassThroughProp] = sqseventproperties("FunctionResponseTypes") + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation MaximumBatchingWindowInSeconds: Optional[PassThroughProp] = sqseventproperties("MaximumBatchingWindowInSeconds") Queue: PassThroughProp = sqseventproperties("Queue") ScalingConfig: Optional[PassThroughProp] # Update docs when live @@ -406,6 +409,7 @@ class HttpApiEvent(BaseModel): class MSKEventProperties(BaseModel): ConsumerGroupId: Optional[PassThroughProp] = mskeventproperties("ConsumerGroupId") FilterCriteria: Optional[PassThroughProp] = mskeventproperties("FilterCriteria") + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation MaximumBatchingWindowInSeconds: Optional[PassThroughProp] = mskeventproperties("MaximumBatchingWindowInSeconds") StartingPosition: Optional[PassThroughProp] = mskeventproperties("StartingPosition") StartingPositionTimestamp: Optional[PassThroughProp] = mskeventproperties("StartingPositionTimestamp") @@ -426,6 +430,7 @@ class MQEventProperties(BaseModel): DynamicPolicyName: Optional[bool] = mqeventproperties("DynamicPolicyName") Enabled: Optional[PassThroughProp] = mqeventproperties("Enabled") FilterCriteria: Optional[PassThroughProp] = mqeventproperties("FilterCriteria") + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation MaximumBatchingWindowInSeconds: Optional[PassThroughProp] = mqeventproperties("MaximumBatchingWindowInSeconds") Queues: PassThroughProp = mqeventproperties("Queues") SecretsManagerKmsKeyId: Optional[str] = mqeventproperties("SecretsManagerKmsKeyId") @@ -445,6 +450,7 @@ class SelfManagedKafkaEventProperties(BaseModel): KafkaBootstrapServers: Optional[List[SamIntrinsicable[str]]] = selfmanagedkafkaeventproperties( "KafkaBootstrapServers" ) + KmsKeyArn: Optional[PassThroughProp] # TODO: add documentation SourceAccessConfigurations: PassThroughProp = selfmanagedkafkaeventproperties("SourceAccessConfigurations") StartingPosition: Optional[PassThroughProp] # TODO: add documentation StartingPositionTimestamp: Optional[PassThroughProp] # TODO: add documentation diff --git a/samtranslator/model/eventsources/pull.py b/samtranslator/model/eventsources/pull.py index 9c5df897c..b5298771c 100644 --- a/samtranslator/model/eventsources/pull.py +++ b/samtranslator/model/eventsources/pull.py @@ -52,6 +52,7 @@ class PullEventSource(ResourceMacro, metaclass=ABCMeta): "FunctionResponseTypes": PropertyType(False, IS_LIST), "KafkaBootstrapServers": PropertyType(False, IS_LIST), "FilterCriteria": PropertyType(False, IS_DICT), + "KmsKeyArn": PassThroughProperty(False), "ConsumerGroupId": PropertyType(False, IS_STR), "ScalingConfig": PropertyType(False, IS_DICT), } @@ -74,6 +75,7 @@ class PullEventSource(ResourceMacro, metaclass=ABCMeta): FunctionResponseTypes: Optional[List[Any]] KafkaBootstrapServers: Optional[List[Any]] FilterCriteria: Optional[Dict[str, Any]] + KmsKeyArn: Optional[Intrinsicable[str]] ConsumerGroupId: Optional[Intrinsicable[str]] ScalingConfig: Optional[Dict[str, Any]] @@ -141,6 +143,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def] # noqa: P lambda_eventsourcemapping.TumblingWindowInSeconds = self.TumblingWindowInSeconds lambda_eventsourcemapping.FunctionResponseTypes = self.FunctionResponseTypes lambda_eventsourcemapping.FilterCriteria = self.FilterCriteria + lambda_eventsourcemapping.KmsKeyArn = self.KmsKeyArn lambda_eventsourcemapping.ScalingConfig = self.ScalingConfig self._validate_filter_criteria() diff --git a/samtranslator/model/lambda_.py b/samtranslator/model/lambda_.py index d48ced17d..e76809735 100644 --- a/samtranslator/model/lambda_.py +++ b/samtranslator/model/lambda_.py @@ -118,6 +118,7 @@ class LambdaEventSourceMapping(Resource): "FunctionResponseTypes": GeneratedProperty(), "SelfManagedEventSource": GeneratedProperty(), "FilterCriteria": GeneratedProperty(), + "KmsKeyArn": GeneratedProperty(), "AmazonManagedKafkaEventSourceConfig": GeneratedProperty(), "SelfManagedKafkaEventSourceConfig": GeneratedProperty(), "ScalingConfig": GeneratedProperty(), diff --git a/samtranslator/schema/schema.json b/samtranslator/schema/schema.json index 73236e71c..f56b63d8b 100644 --- a/samtranslator/schema/schema.json +++ b/samtranslator/schema/schema.json @@ -274745,6 +274745,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-ddb-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n*Valid values*: `ReportBatchItemFailures` \n*Type*: List \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -275489,6 +275492,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n*Valid values*: `ReportBatchItemFailures` \n*Type*: List \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -276052,6 +276058,9 @@ "markdownDescription": "A object that defines the criteria that determines whether Lambda should process an event\\. For more information, see [AWS Lambda event filtering](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [FilterCriteria](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterCriteria`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FilterCriteria" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -276145,6 +276154,9 @@ "markdownDescription": "A object that defines the criteria that determines whether Lambda should process an event\\. For more information, see [AWS Lambda event filtering](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [FilterCriteria](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterCriteria`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FilterCriteria" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -276771,6 +276783,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [ Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n *Valid values*: `ReportBatchItemFailures` \n *Type*: List \n *Required*: No \n *AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -276987,6 +277002,9 @@ "title": "KafkaBootstrapServers", "type": "array" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "SourceAccessConfigurations": { "allOf": [ { diff --git a/schema_source/sam.schema.json b/schema_source/sam.schema.json index 8f9bbee8c..1a897cdfb 100644 --- a/schema_source/sam.schema.json +++ b/schema_source/sam.schema.json @@ -974,6 +974,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-ddb-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n*Valid values*: `ReportBatchItemFailures` \n*Type*: List \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -1736,6 +1739,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n*Valid values*: `ReportBatchItemFailures` \n*Type*: List \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -2299,6 +2305,9 @@ "markdownDescription": "A object that defines the criteria that determines whether Lambda should process an event\\. For more information, see [AWS Lambda event filtering](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [FilterCriteria](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterCriteria`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FilterCriteria" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -2392,6 +2401,9 @@ "markdownDescription": "A object that defines the criteria that determines whether Lambda should process an event\\. For more information, see [AWS Lambda event filtering](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) in the *AWS Lambda Developer Guide*\\. \n*Type*: [FilterCriteria](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterCriteria`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-eventsourcemapping-filtercriteria.html) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FilterCriteria" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -2949,6 +2961,9 @@ "markdownDescription": "A list of the response types currently applied to the event source mapping\\. For more information, see [ Reporting batch item failures](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting) in the *AWS Lambda Developer Guide*\\. \n *Valid values*: `ReportBatchItemFailures` \n *Type*: List \n *Required*: No \n *AWS CloudFormation compatibility*: This property is passed directly to the [`FunctionResponseTypes`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html#cfn-lambda-eventsourcemapping-functionresponsetypes) property of an `AWS::Lambda::EventSourceMapping` resource\\.", "title": "FunctionResponseTypes" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "MaximumBatchingWindowInSeconds": { "allOf": [ { @@ -3165,6 +3180,9 @@ "title": "KafkaBootstrapServers", "type": "array" }, + "KmsKeyArn": { + "$ref": "#/definitions/PassThroughProp" + }, "SourceAccessConfigurations": { "allOf": [ { diff --git a/tests/translator/input/function_with_event_filtering.yaml b/tests/translator/input/function_with_event_filtering.yaml index 98a5f56de..11a1b3410 100644 --- a/tests/translator/input/function_with_event_filtering.yaml +++ b/tests/translator/input/function_with_event_filtering.yaml @@ -58,6 +58,7 @@ Resources: FilterCriteria: Filters: - Pattern: '{"name": "value"}' + KmsKeyArn: arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab MyMQQueue: Type: MQ Properties: diff --git a/tests/translator/output/aws-cn/function_with_event_filtering.json b/tests/translator/output/aws-cn/function_with_event_filtering.json index 70df8b142..051962663 100644 --- a/tests/translator/output/aws-cn/function_with_event_filtering.json +++ b/tests/translator/output/aws-cn/function_with_event_filtering.json @@ -105,6 +105,7 @@ "FunctionName": { "Ref": "FilteredEventsFunction" }, + "KmsKeyArn": "arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab", "SelfManagedEventSource": { "Endpoints": { "KafkaBootstrapServers": [ diff --git a/tests/translator/output/aws-us-gov/function_with_event_filtering.json b/tests/translator/output/aws-us-gov/function_with_event_filtering.json index 9b652467d..34fbe9fee 100644 --- a/tests/translator/output/aws-us-gov/function_with_event_filtering.json +++ b/tests/translator/output/aws-us-gov/function_with_event_filtering.json @@ -105,6 +105,7 @@ "FunctionName": { "Ref": "FilteredEventsFunction" }, + "KmsKeyArn": "arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab", "SelfManagedEventSource": { "Endpoints": { "KafkaBootstrapServers": [ diff --git a/tests/translator/output/function_with_event_filtering.json b/tests/translator/output/function_with_event_filtering.json index 8be187444..c35119f45 100644 --- a/tests/translator/output/function_with_event_filtering.json +++ b/tests/translator/output/function_with_event_filtering.json @@ -105,6 +105,7 @@ "FunctionName": { "Ref": "FilteredEventsFunction" }, + "KmsKeyArn": "arn:aws:kms:us-west-2:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab", "SelfManagedEventSource": { "Endpoints": { "KafkaBootstrapServers": [