Issue with EventBridge rule for aws.events - amazon-web-services

I want to send to CloudWatch logs ALL the events sent to a custom event bus.
I created the custom event bus: my-event-bus
I created the CloudWatch log group
I created the event bus policy so everyone within my account can put an event into my-event-bus
I created a rule for that custom bus
This is the rule:
MyRuleForBus:
Type: AWS::Events::Rule
Properties:
Description: Testing rule
EventBusName:
Name: testing-rule-for-my-event-bus
EventPattern:
source:
- aws.events
State: ENABLED
Targets:
- Arn: arn:aws:logs:us-east-1:MY_ACCOUNT_ID:log-group:my-event-bus-log-group
Id: 'my-bus'
When I try to put an event
aws events put-events --entries file://put-events.json
I receive the following error
{
"FailedEntryCount": 1,
"Entries": [
{
"ErrorCode": "NotAuthorizedForSourceException",
"ErrorMessage": "Not authorized for the source."
}
]
}
This is the content of put-events.json
[
{
"Source": "aws.events",
"EventBusName": "my-event-bus",
"Detail": "{ \"key1\": \"value3\", \"key2\": \"value4\" }",
"Resources": [
"resource1",
"resource2"
],
"DetailType": "myDetailType"
}
]
But, if I change the source to other, for example, 'hello', in both, the rule and the event it works.
What am I doing wrong?
I want to make it work with aws.events so all the events sent to this bus end in CloudWatch (target)

aws.events belongs to AWS, not to you, thus you can't define it as source of your events. Only AWS can do it.
You need to use your own custom name for the source of your events, e.g. myapp.events.

Related

Enabling Logs for AWS WAF WebAcl does not work in CDK

My goal is to enable logging for a regional WebAcl via AWS CDK. This seems to be possible over Cloud Formation and there are the appropriate constructs in CDK. But when using the following code to create a Log Group and linking it in a LoggingConfiguration ...
const webAclLogGroup = new LogGroup(scope, "awsWafLogs", {
logGroupName: `aws-waf-logs`
});
// Create logging configuration with log group as destination
new CfnLoggingConfiguration(scope, "webAclLoggingConfiguration", {
logDestinationConfigs: webAclLogGroup.logGroupArn, // Arn of LogGroup
resourceArn: aclArn // Arn of Acl
});
... I get an exception during cdk deploy, stating that the string in the LogdestinationConfig is not a correct Arn (some parts of the Arn in the log messages have been removed):
Resource handler returned message: "Error reason: The ARN isn't valid. A valid ARN begins with arn: and includes other information separated by colons or slashes., field: LOG_DESTINATION, parameter: arn:aws:logs:xxx:xxx:xxx-awswaflogsF99ED1BA-PAeH9Lt2Y3fi:* (Service: Wafv2, Status Code: 400, Request ID: xxx, Extended Request ID: null)"
I cannot see an error in the generated Cloud Formation code after cdk synth:
"webAclLoggingConfiguration": {
"id": "webAclLoggingConfiguration",
"path": "xxx/xxx/webAclLoggingConfiguration",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::WAFv2::LoggingConfiguration",
"aws:cdk:cloudformation:props": {
"logDestinationConfigs": [
{
"Fn::GetAtt": [
{
"Ref": "awsWafLogs58D3FD01"
},
"Arn"
]
}
],
"resourceArn": {
"Fn::GetAtt": [
"webACL",
"Arn"
]
}
}
},
"constructInfo": {
"fqn": "aws-cdk-lib.aws_wafv2.CfnLoggingConfiguration",
"version": "2.37.1"
}
},
I'm using Cdk with Typescript and the Cdk version is currently set to 2.37.1 but it also did not work with 2.16.0.
WAF has particular requirements to the naming and format of Logging Destination configs as described and shown in their docs.
Specifically, the ARN of the Log Group cannot end in :* which unfortunately is the return value for a Log Group ARN in Cloudformation.
A workaround would be to construct the required ARN format manually like this, which will omit the :* suffix. Also note that logDestinationConfigs takes a List of Strings, though only with exactly 1 element in it.
const webAclLogGroup = new LogGroup(scope, "awsWafLogs", {
logGroupName: `aws-waf-logs`
});
// Create logging configuration with log group as destination
new CfnLoggingConfiguration(scope, "webAclLoggingConfiguration", {
logDestinationConfigs: [
// Construct the different ARN format from the logGroupName
Stack.of(this).formatArn({
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
service: "logs",
resource: "log-group",
resourceName: webAclLogGroup.logGroupName,
})
],
resourceArn: aclArn // Arn of Acl
});
PS: I work for AWS on the CDK team.

InputTransformer YAML not resolving for event rule

I am aiming to send following format to the data:
{
"headers": {
"Authorization": "Bearer expectedToken"
},
"body": {
"id": "abc",
"status": "ANY",
"preferences": [ [Object] ]
}
}
but struggling with the Input transformer in YAML:
inputTransformer:
inputPathsMap:
expectedToken: '$detail.metadata.someToken'
inputTemplate: '{"headers": {"Authorization": <expectedToken>}}'
And getting this error:
Received response status [FAILED] from custom resource. Message
returned: Event pattern is not valid. Reason: "expectedToken" must be
an object or an array+ +at [Source:
(String)"{"inputTransformer":{"inputPathsMap":{"expectedToken":"$detail.metadata.someToken"},"inputTemplate":"{"headers":
{"Authorization": }}"},"
Trigger is an APIGW with a mapping template that appends a Auth token as part of the metadata, but the target expects it as a header. Is it a viable solution? How can this be resolved to the expected format?
Later Edit: Data being sent from APIGW:
{
detail: {
body: {
id: 'abc',
extraInfo: 'Postman_15:07',
preferences: [Array]
},
metadata: {
service: 'my-service',
status: 'ANY',
someToken: 'Bearer expectedToken'
}
}
}
Could you share an example (scrubbed of personal info) of your event payload - ie the JSON that has the detail, and metadata sub-fields?
You could also try
inputTransformer:
inputPathsMap:
expectedToken: '$detail.metadata.someToken'
inputTemplate: '{"headers": {"Authorization": "Bearer <expectedToken>"}}'
Try it out with an input-path like $.detail.metadata.someToken
If this also doesn't work, as already asked for, give us an example of the event that arrives at the EventBridge itself. If you don't know the event payload you can setup an event rule that forwards the event to a CloudWatch log group so that you can check the logs. (tip: setup the cloudwatch target via AWS console, afaik there are some issues using CloudFormation for this)
Thank you for the suggestions. It looks like the issue was with indentation of the inputTransformer section under eventbridge. That error message was by no means helpful. Final format to match what the target Lambda was expecting was :
inputTransformer:
inputPathsMap:
expectedToken: '$detail.metadata.someToken'
data: '$.detail.body'
inputTemplate: '{"headers": {"Authorization": <expectedToken>}, "body": <data>}'

How to add a redrive policy (dead-letter queue / DLQ) to a SNS subscription, with Ansible and AWS

In an Ansible script I have:
- name: Subscribe lambda to SNS topic example1
sns_topic:
name: "example1-{{env_name}}"
purge_subscriptions: no
subscriptions:
- endpoint: "arn:aws:lambda:{{ aws.region }}:{{ aws.account }}:function:{{repo_name}}-{{env_name}}"
protocol: "lambda"
It works, and the result is that my lambda is subscribed to my SNS topic.
Now, I would want to add a DLQ to this subscription.
I already have a SQS and I want to state it as my DLQ.
So I rewrite my code like this:
- name: Subscribe lambda to SNS topic example1
sns_topic:
name: "example1-{{env_name}}"
purge_subscriptions: no
subscriptions:
- endpoint: "arn:aws:lambda:{{ aws.region }}:{{ aws.account }}:function:{{repo_name}}-{{env_name}}"
protocol: "lambda"
redrive_policy:
dead_letter_target_arn: "arn:aws:{{ aws.region }}:{{ aws.account }}:dlq-for-example1"
This does not work and I didn't find anything in Ansible or by googling...
What am I doing wrong?
Looks like you are missing sqs between arn:aws:{{aws.region}} on the last line.
dead_letter_target_arn: "arn:aws:sqs:{{ aws.region }}:{{ aws.account }}:dlq-for-example1"
The problem is that the Subscription property that is embedded in the SNS Topic only has two properties: Endpoint and Protocol (See Subscription Property).
For more advanced settings, like RedrivePolicy, you need to use the stand-alone AWS::SNS::Subscription resource (See Subscription Resource).
Since AWS::SNS::Subscription is stand-alone, you must include the TopicArn that the Subscription is bound to. Also note that the RedrivePolicy is in Json format.
Here's a simple example of the Cloud Formation syntax from Redrive Syntax:
{
"Resources": {
"mySubscription": {
"Type" : "AWS::SNS::Subscription",
"Properties" : {
"Protocol": "sqs",
"Endpoint": "arn:aws:sqs:us-east-2:123456789012:MyEndpoint",
"TopicArn": "arn:aws:sns:us-east-2:123456789012:MyTopic",
"RedrivePolicy": {
"deadLetterTargetArn":
"arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue"
}
}
}
}
}
But I don't know how Ansible makes these translations.

Access Event ID in a AWS RDS Event subscription

As described in the documentation, when creating a RDS Event subscription you can select any number Event categories that will produce specific Event messages.
Then you can choose to send a notification to an E-mail, SMS or, which is my case, to a SNS topic that triggers a Lambda execution.
How to access the RDS Event ID - i.e. RDS-EVENT-0006 - from the Lambda event parameter?
Add a trigger event like this cloudformation example :
DbRestoredEventRule:
Type: AWS::Events::Rule
Properties:
Name: "xyz-db-restored"
Description: "xyz restored"
EventPattern:
source:
- "aws.rds"
detail-type:
- "RDS DB Instance Event"
detail:
EventCategories:
- "availability"
Message:
- 'DB instance restarted'
Targets:
- Arn:
Fn::GetAtt:
- "MigrationDataFunction"
- "Arn"
Id: "TargetFunctionV1"

CloudFormation - Create SNS subscription in disabled state

Is there a way to create an SNS subscription in the disabled state? This is for a lambda if that makes a difference.
Example:
MySubscription:
Type: AWS::SNS::Subscription
Properties:
Endpoint: arn:aws:lambda:region:account-id:function:mylambda
Protocol: lambda
TopicArn: arn:aws:sns:region:account-id:topic
Enabled: false # like this
Couldn't find anything like this in the AWS CloudFormation documentation
You can create a condition on the subscription creation.
First add a parameter:
"CreateSubscription": {
"Type": "String",
"AllowedValues": [
"true",
"false"
],
"Description": "Create subscription to sns"
}
after the 'parameters' section, create a 'conditions' section:
"Conditions" : {
"CreateSubscription" : {"Fn::Equals" : [{"Ref" : "CreateSubscription"}, "true"]}
}
add the condition to your subscription
"Subscription": {
"Type": "AWS::SNS::Subscription",
"Condition" : "CreateSubscription",
[...]
}
when you want to "activate" you subscription, you just have to change the parameter value updating the stack using the same template
Conditions section reference
There isn't a way with Cloudformation which conforms to your example. According to the documentation, AWS::SNS::Subscription does not have 'Enabled' as a setting.
Although, the documentation does state that the owner of the endpoint must confirm the subscription before Amazon SNS creates the subscription. So, in a sense, it's already disabled because it doesn't exist until you confirm it on the SNS topic.