diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/Example12_README.md b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/Example12_README.md new file mode 100644 index 000000000..fa501e99a --- /dev/null +++ b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/Example12_README.md @@ -0,0 +1,80 @@ +# EventBridge API Destinations with OAuth and CMK Encryption + +Amazon EventBridge announces support for Amazon Key Management Service (KMS) Customer Managed Keys (CMK) in API destinations connections. This enhancement enables you to encrypt your HTTPS endpoint authentication credentials managed by API destinations with your own keys instead of an AWS owned key (which is used by default). With CMK support, you now have more granular security control over your authentication credentials used in API destinations, helping you meet your organization's security requirements and governance policies. + +This sample demonstrates how to use Amazon EventBridge API Destinations with OAuth authentication and AWS CMK encryption. + +## Overview + +- **EventBridge API Destinations**: Send events to external HTTP endpoints. +- **OAuth Authentication**: Secure API calls using OAuth 2.0. +- **CMK Encryption**: Protect sensitive data using a customer managed KMS key. + +## Architecture + +1. **EventBridge Rule** triggers on specific events. +2. **API Destination** sends the event to an external API using OAuth. +3. **KMS CMK** encrypts secrets and sensitive data. + +![alt EventBridge Rule with CMK integration](diagram.png "Architecture") + +## Prerequisites + +* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed + +* Also, run the below CloudFormation (CFN) command to create pre-requisit resources: +```bash +aws cloudformation create-stack --stack-name serverlessland-prerequisite --template-body file://prerequsite.yaml +``` +* Above command will create stack with the below resources, please goto the CFN console and select your pre-requisite stack. Copy the output in the notepad, we'll need this later. +- External API URL for HTTP API Endpoint. If you already have one you can also use that. +- Cognito Authorization Endpoint. If you have any external authorizer endpoint you can use that. +- Cognito OAuth Client ID. +- OAuth Client Secret. To get that you need to goto aws cognito console, goto your MyServerlessLandUserPool and click on your App Client -> MyWebClient and copy the Client secret, we'll need this later. +- CMK key in KMS. Please not the arn, we'll use this later. + +## Deployment + +* Run the below command and provide all the parameter details which we can saved previously. +```bash +sam deploy --guided +``` + +## Testing + +1. From a command line in this directory, send a test event to EventBridge simulating a \"EventBridge CMK Demo success\" event. +```bash +aws events put-events --entries file://testEvent.json +``` +2. To verify if everything works correctly, you can check the execution logs of your api. + +## Cleanup + +1. Delete the stack + ```bash + sam delete --stack-name STACK_NAME + ``` +2. Confirm the stack has been deleted + ```bash + aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus" + ``` + +## Resources + +- [Amazon EventBridge now supports Customer Managed Keys (CMK) in API destinations connections](https://aws.amazon.com/about-aws/whats-new/2025/04/amazon-eventbridge-customer-managed-keys-api/) + +- [Encrypting EventBridge connection authorization with AWS KMS keys](https://docs.aws.amazon.com/eventbridge/latest/userguide/encryption-connections.html) + +- [Using API destinations with Amazon EventBridge](https://aws.amazon.com/blogs/compute/using-api-destinations-with-amazon-eventbridge/) + +- [Use Amazon EventBridge to Build Decoupled, Event-Driven Architectures](https://serverlessland.com/learn/eventbridge) + + +---- + +Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/diagram.png b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/diagram.png new file mode 100644 index 000000000..ae2117305 Binary files /dev/null and b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/diagram.png differ diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/example-pattern.json b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/example-pattern.json new file mode 100644 index 000000000..771e3c679 --- /dev/null +++ b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/example-pattern.json @@ -0,0 +1,93 @@ +{ + "title": "EventBridge API Destinations with OAuth credentials using CMK encryption", + "description": "Create an EventBridge rule and API Destination with OAuth credentials using Customer Managed Key (CMK) encryption", + "language": "Node.js", + "level": "100", + "framework": "AWS SAM", + "services": { + "from": "eventbridge", + "to": "eventbridge" + }, + "introBox": { + "headline": "How it works", + "text": [ + "This pattern configures an EventBridge rule that routes to an API Destinations target using Oauth credentials with Customer Managed Key (CMK) encryption. It configures a Connection, which contains the authorization for the API endpoint with CMK encryption, and the API, which contains the URL, http method, and other configuration information." + ], + "test": "" + }, + "deploy": { + "text": [ + "cd ./12-oauth-api-with-cmk-encryption", + "sam deploy --guided" + ] + }, + "testing": { + "headline": "Testing", + "text": [ + "1. From a command line in this directory, send a test event to EventBridge simulating a \"EventBridge CMK Demo success\" event: aws events put-events --entries file://testEvent.json" + ] + }, + "cleanup": { + "headline": "Cleanup", + "text": [ + "1. Delete the stack: sam delete --stack-name STACK_NAME.", + "2. Confirm the stack has been deleted: aws cloudformation list-stacks --query \"StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus\"" + ] + }, + "gitHub": { + "template": { + "projectFolder": "eventbridge-api-destinations", + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption", + "templateURL": "serverless-patterns/eventbridge-api-destinations", + "templateFile": "12-oauth-api-with-cmk-encryption/template.yaml" + }, + "payloads": [ + { + "headline": "", + "payloadURL": "" + } + ] + }, + "resources": { + "headline": "Additional resources", + "bullets": [ + { + "text": "Amazon EventBridge now supports Customer Managed Keys (CMK) in API destinations connections", + "link": "https://aws.amazon.com/about-aws/whats-new/2025/04/amazon-eventbridge-customer-managed-keys-api/" + }, + { + "text": "Encrypting EventBridge connection authorization with AWS KMS keys", + "link": "https://docs.aws.amazon.com/eventbridge/latest/userguide/encryption-connections.html" + }, + { + "text": "Using API destinations with Amazon EventBridge", + "link": "https://aws.amazon.com/blogs/compute/using-api-destinations-with-amazon-eventbridge/" + }, + { + "text": "Use Amazon EventBridge to Build Decoupled, Event-Driven Architectures", + "link": "https://serverlessland.com/learn/eventbridge" + } + ] + }, + "authors": [ + { + "name": "Rajesh Kumar", + "image": "https://avatars.githubusercontent.com/u/4745639", + "bio": "Rajesh Kumar is a Technical Account Manager (TAM) at Amazon Web Services (AWS) and contributor to ServerlessLand. He is passionate about serverless and wants to help everyone get started with serverless and what can be done with it.", + "linkedin": "rajeshk1988" + }, + { + "name": "Biswanath Mukherjee", + "image": "https://d1rwvjey2iif32.cloudfront.net", + "bio": "I am a Sr. Solutions Architect working at AWS India.", + "linkedin": "biswanathmukherjee" + } + ], + "tags": [ + "EventBridge", + "API Destinations", + "OAuth", + "CMK Encryption", + "Serverless" + ] +} \ No newline at end of file diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/prerequsite.yaml b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/prerequsite.yaml new file mode 100644 index 000000000..28a7ab7fc --- /dev/null +++ b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/prerequsite.yaml @@ -0,0 +1,227 @@ +AWSTemplateFormatVersion: '2010-09-09' +Description: Creates a Cognito User Pool and associated machine to machine App Client and the CMK key in KMS + +Parameters: + # User Pool Parameters + UserPoolName: + Type: String + Description: Name of the User Pool + Default: "MyServerlessLandUserPool" + + UsernameAttributes: + Type: CommaDelimitedList + Description: Allowed attributes for usernames (e.g., email, phone_number) + Default: 'email' + + # App Client Parameters + ClientName: + Type: String + Description: Name of the App Client + Default: "MyWebClient" + + CallbackURLs: + Type: CommaDelimitedList + Description: Callback URLs for the App Client + Default: 'http://localhost:8080' + + LogoutURLs: + Type: CommaDelimitedList + Description: Logout URLs for the App Client + Default: 'http://localhost:8080/logout' + +Resources: + # User Pool Resource + MyUserPool: + Type: AWS::Cognito::UserPool + Properties: + UserPoolName: !Ref UserPoolName + UsernameAttributes: !Ref UsernameAttributes + # User Pool Domain Resource + # This will create a unique domain based on the stack name + # The domain will be in the format: svls- + # where is derived from the stack name + # This ensures that the domain is unique across different stacks + # and avoids conflicts when deploying multiple instances of the stack + # The unique value is derived from the stack ID and is used to create a unique domain + CognitoUserPoolDomain: + Type: AWS::Cognito::UserPoolDomain + Properties: + Domain: + !Sub + - 'svls-${selectedValue}' + - selectedValue: !Select [4, !Split ['-', !Select [2, !Split ['/', !Ref AWS::StackId]]]] # <-- getting a unique value + UserPoolId: !Ref MyUserPool + # Resource Server for M2M access + # This will create a resource server with the identifier 'petstore-api.example.com' + # and a scope 'domestic.read' for M2M access + # The resource server is associated with the User Pool created above + # This allows the App Client to request access to the 'domestic.read' scope + # when making API calls to the resource server + # The resource server is used to define the scopes that the App Client can request + # when making API calls to the resource server + MyResourceServer: + Type: AWS::Cognito::UserPoolResourceServer + Properties: + Identifier: petstore-api.example.com + Name: myapi_resource_server + UserPoolId: !Ref MyUserPool + Scopes: + - ScopeName: domestic.read + ScopeDescription: Read scope for M2M access + + + # App Client Resource + MyWebClient: + Type: AWS::Cognito::UserPoolClient + DependsOn: + - MyResourceServer + Properties: + ClientId: !Ref ClientName + ClientName: !Ref ClientName + GenerateSecret: true + AllowedOAuthFlows: + - client_credentials + AllowedOAuthFlowsUserPoolClient: true + AllowedOAuthScopes: + - petstore-api.example.com/domestic.read + CallbackURLs: !Ref CallbackURLs + LogoutURLs: !Ref LogoutURLs + UserPoolId: !Ref MyUserPool + + # CMK Key Resources + # This will create a CMK Key in KMS + # The CMK Key will be used to encrypt the OAuth credentials + MyCMKKey: + Type: AWS::KMS::Key + Properties: + Description: "CMK Key for encrypting OAuth credentials" + EnableKeyRotation: true + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: AllowRootUserToManageCMK + Effect: Allow + Principal: + AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' + Action: 'kms:*' + Resource: '*' + - Sid: AllowEventsServiceToUseCMK + Effect: Allow + Principal: + Service: events.amazonaws.com + Action: + - 'kms:GenerateDataKey' + - 'kms:Decrypt' + Resource: '*' + Tags: + - Key: 'EventBridgeApiDestinations' + Value: true + MyCMKKeyAlias: + Type: AWS::KMS::Alias + Properties: + AliasName: alias/MyCMKKey + TargetKeyId: !Ref MyCMKKey + + # Api Gateway Resources + # This will create an API Gateway with a Cognito Authorizer + # The API Gateway will use the Cognito User Pool created above + # The API Gateway will have a GET method that uses the Cognito Authorizer + # The API Gateway will be used to test the OAuth flow + # The logging level is set to INFO and data trace is enabled, so that we can see the logs in CloudWatch to verify + CogAuthorizer: + Type: AWS::ApiGateway::Authorizer + Properties: + Name: CognitoAuthorizer + RestApiId: + Ref: Api + Type: COGNITO_USER_POOLS + IdentitySource: method.request.header.Authorization + ProviderARNs: + - !GetAtt MyUserPool.Arn + Api: + Type: AWS::ApiGateway::RestApi + Properties: + Name: MyCogAuthApi + ApiDeployment: + Type: AWS::ApiGateway::Deployment + Properties: + RestApiId: + Ref: Api + DependsOn: + - CogAuthorizer + - ApiGET + ApiDeploymentStageprod: + Type: AWS::ApiGateway::Stage + Properties: + RestApiId: + Ref: Api + DeploymentId: + Ref: ApiDeployment + StageName: prod + MethodSettings: + - HttpMethod: '*' + ResourcePath: '/*' + LoggingLevel: INFO + DataTraceEnabled: true + ApiGET: + Type: AWS::ApiGateway::Method + Properties: + HttpMethod: POST + ResourceId: + Fn::GetAtt: + - Api + - RootResourceId + RestApiId: + Ref: Api + AuthorizationType: COGNITO_USER_POOLS + AuthorizationScopes: + - petstore-api.example.com/domestic.read + AuthorizerId: + Ref: CogAuthorizer + Integration: + IntegrationHttpMethod: GET + Type: HTTP + Uri: http://petstore-demo-endpoint.execute-api.com/petstore/pets + IntegrationResponses: + - StatusCode: 200 + MethodResponses: + - StatusCode: 200 + +Outputs: + UserPoolArn: + Description: User Pool ARN + Value: !GetAtt MyUserPool.Arn + + ApiEndpoint: + Value: + Fn::Join: + - "" + - - https:// + - Ref: Api + - .execute-api. + - Ref: AWS::Region + - "." + - Ref: AWS::URLSuffix + - / + - Ref: ApiDeploymentStageprod + + ClientId: + Description: App Client ID + Value: !Ref MyWebClient + + CMKKeyArn: + Description: CMK Key ARN + Value: !GetAtt MyCMKKey.Arn + + ExternalAuthEndpoint: + Description: User Pool Domain + Value: + !Join + - "" + - - "https://" + - !Ref CognitoUserPoolDomain + - ".auth." + - Ref: AWS::Region + - ".amazoncognito.com/oauth2/token" + diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/template.yaml b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/template.yaml new file mode 100644 index 000000000..b8f8c357f --- /dev/null +++ b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/template.yaml @@ -0,0 +1,173 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Create an API Destination in EventBridge with OAuth Credentials using Customer Managed Key (CMK) encryption + +Parameters: + ExternalAPIURL: + Type: String + Description: Enter External API URL + Default: '<>' + ExternalAuthEndpoint: + Type: String + Description: Enter Authorization Endpoint + Default: '<>' + ExternalAuthAPIClientID: + Type: String + Description: Enter OAuth Client ID + Default: '<>' + ExternalAuthAPIClientSecret: + Type: String + NoEcho: True + Description: Enter OAuth Client Secret + Default: '<>' + CMKKeyARN: + Type: String + Description: Enter CMK Key arn + Default: '<>' + + +Resources: + # Event Bus Resource + # This will create an Event Bus named 'ExternalOAuthEventBus' + # The Event Bus will be used to publish events that will trigger the API Destination + # The Event Bus will be used to route events to the API Destination + MyEventBus: + Type: AWS::Events::EventBus + Properties: + Name: "ExternalOAuthEventBus" + # Connection secret in Secrets Manager + # This will create a secret in Secrets Manager to store the OAuth credentials + ConnectionSecret: + Type: AWS::SecretsManager::Secret + Properties: + Name: "ExternalOAuthCredentials" + Description: "OAuth connection credential secret" + SecretString: !Sub >- + {"ClientID": "${ExternalAuthAPIClientID}", "ClientSecret": "${ExternalAuthAPIClientSecret}"} + # Connection Resource + # This will create a connection in EventBridge with OAuth Client Credentials + # The connection will use the OAuth credentials stored in the Secrets Manager secret created above + # The connection will use the CMK Key for encryption + # The connection will be used to invoke the API Destination with OAuth credentials + MyConnection: + Type: AWS::Events::Connection + Properties: + AuthorizationType: 'OAUTH_CLIENT_CREDENTIALS' + Description: 'My connection with an OAuth2 credentials using Customer Managed Key (CMK) encryption' + KmsKeyIdentifier: !Ref CMKKeyARN + AuthParameters: + OAuthParameters: + AuthorizationEndpoint: !Ref ExternalAuthEndpoint + ClientParameters: + ClientID: '{{resolve:secretsmanager:ExternalOAuthCredentials:SecretString:ClientID}}' + ClientSecret: '{{resolve:secretsmanager:ExternalOAuthCredentials:SecretString:ClientSecret}}' + HttpMethod: 'POST' + OAuthHttpParameters: + HeaderParameters: + - Key: 'Content_Type' + Value: 'application/x-www-form-urlencoded' + IsValueSecret: false + BodyParameters: + - Key: 'grant_type' + Value: 'client_credentials' + IsValueSecret: true + DependsOn: ConnectionSecret + + # Api Destination Resource + # This will create an API Destination in EventBridge + # The API Destination will use the connection created above + # The API Destination will invoke the external API endpoint with OAuth credentials + # The API Destination will use the CMK Key for encryption + # The API Destination will be used to route events from the Event Bus to the external API + MyApiDestination: + Type: AWS::Events::ApiDestination + Properties: + Name: 'ExternalApiDestination' + ConnectionArn: !GetAtt MyConnection.Arn + InvocationEndpoint: !Ref ExternalAPIURL + HttpMethod: POST + InvocationRateLimitPerSecond: 10 + # EventBridge Target Role + # This will create a role that EventBridge can assume to invoke the API Destination + # The role will have permissions to invoke the API Destination and access the Secrets Manager secret + # The role will be used by EventBridge to invoke the API Destination with OAuth credentials + EventBridgeTargetRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: + - events.amazonaws.com + Action: + - sts:AssumeRole + Policies: + - PolicyName: AllowAPIdestinationAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: 'events:InvokeApiDestination' + Resource: !GetAtt MyApiDestination.Arn + - Effect: Allow + Action: + - secretsmanager:CreateSecret + - secretsmanager:UpdateSecret + - secretsmanager:DescribeSecret + - secretsmanager:DeleteSecret + - secretsmanager:GetSecretValue + - secretsmanager:PutSecretValue + Resource: + - arn:aws:secretsmanager:*:*:secret:events!connection/* + + MyDLQueue: + Type: AWS::SQS::Queue + # Rule to trigger the API Destination + # This will create a rule that triggers the API Destination when an event is published to the Event Bus + # The rule will filter events based on the source and detail-type + # The rule will use the API Destination as the target + EventRule: + Type: AWS::Events::Rule + Properties: + Description: "EventRule" + State: "ENABLED" + EventBusName: !Ref MyEventBus + EventPattern: + source: + - "com.demo-event-bus.cmk" + detail-type: + - "demo-event-type" + Targets: + - Arn: !GetAtt MyApiDestination.Arn + RoleArn: !GetAtt EventBridgeTargetRole.Arn + Id: "MyAPIdestination" + InputPath: "$.detail.responsePayload" + DeadLetterConfig: + Arn: !GetAtt MyDLQueue.Arn + +Outputs: + MyEventBusName: + Description: Application EventBus Name + Value: !Ref MyEventBus + + MyEventBusArn: + Description: Application EventBus ARN + Value: !GetAtt MyEventBus.Arn + + MyConnectionName: + Value: !Ref MyConnection + MyConnectionArn: + Value: !GetAtt MyConnection.Arn + + MyApiDestinationName: + Value: !Ref MyApiDestination + MyApiDestinationArn: + Value: !GetAtt MyApiDestination.Arn + + EventBridgeTargetRoleArn: + Value: !GetAtt EventBridgeTargetRole.Arn + + MyDLQueue: + Value: !GetAtt MyDLQueue.Arn \ No newline at end of file diff --git a/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/testEvent.json b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/testEvent.json new file mode 100644 index 000000000..5e224254d --- /dev/null +++ b/eventbridge-api-destinations/12-oauth-api-with-cmk-encryption/testEvent.json @@ -0,0 +1,8 @@ +[ + { + "DetailType": "demo-event-type", + "EventBusName": "ExternalOAuthEventBus", + "Source": "com.demo-event-bus.cmk", + "Detail": "{\"responsePayload\":\"EventBridge CMK Demo success\"}" + } +] \ No newline at end of file diff --git a/eventbridge-api-destinations/README.md b/eventbridge-api-destinations/README.md index 6f03a959e..5bfcc5e21 100644 --- a/eventbridge-api-destinations/README.md +++ b/eventbridge-api-destinations/README.md @@ -24,6 +24,12 @@ Important: this application uses various AWS services and there are costs associ * To run example #9, an account with [Shopify](https://www.shopify.com/). Follow the instructions to [Create an app and configure Admin API Access scopes](https://shopify.dev/apps/auth/admin-app-access-tokens#step-1-create-and-install-the-app). Make sure to note the Admin Key. * To run example #10, an account with [Stripe](https://dashboard.stripe.com/login). Follow the instructions to [Set up your development environment](https://stripe.com/docs/development/quickstart) and note the api key. * To run example #11, an account with [Salesforce](https://login.salesforce.com/). Follow the Prerequisites to [Create an app and configure security token](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-tutorial-salesforce.html). Make sure to note the Authorization endpoint, Client ID, Client Secret and OAuth Http Parameters Key. +* To run example #12, please have the below things with you: + - HTTPS API endpoint url that you can invoke as the target of an event bus rule. Which uses the scope of 'myapi.example.com/domestic.read' to allow the request. + - Oauth Authorization Endpoint to get the auth token along with OAuth Client ID,OAuth Client Secret + In our deployment we'll use cognito /oauth2/token endpoint (https://tfc-m2m-managed-login-domain.auth.eu-west-1.amazoncognito.com/oauth2/token) + - CMK Key in your AWS KMS Service and get the arn of that CMK key + ## Deployment Instructions 1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: @@ -45,6 +51,7 @@ Important: this application uses various AWS services and there are costs associ - To run the Shopify API Destination example, cd to `9-shopify`. - To run the Stripe API Destination example, cd to `10-stripe`. - To run the API Destination with OAuth credentials example, cd to `11-oauth-api`. +- To run the API Destination with OAuth credentials using CMK encryption example, cd to `12-oauth-api-with-cmk-encryption`. And then follow the Example12_README.md file instructions. 1. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file: ``` sam deploy --guided @@ -74,8 +81,9 @@ aws events put-events --entries file://testEvent.json 9. For the shopify example use the testEvent.json within the 9-shopify directory 10. For the stripe example use the testEvent.json within the 10-stripe directory 11. For the OAuth example use the testEvent.json within the 11-oauth-api directory +12. For the OAuth with cmk encryption example use the testEvent.json within the 12-oauth-api-with-cmk-encryption ``` -aws events put-events --entries file://3-sumologic/testEvent.json +aws events put-events --entries file://testEvent.json ``` ## Cleanup