Skip to content

Commit 6c91b9e

Browse files
committed
initial code
1 parent bdd824d commit 6c91b9e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+7049
-21
lines changed

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
*.js
2+
!jest.config.js
3+
*.d.ts
4+
node_modules
5+
6+
# CDK asset staging directory
7+
.cdk.staging
8+
cdk.out
9+
tmp/*
10+
11+
**/node_modules
12+
13+
# Java bundles
14+
target/
15+
.aws-sam/
16+
17+
# .DS_Store files
18+
.DS_Store
19+
**/.DS_Store
20+
21+
22+
.idea/

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
## Code of Conduct
22
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
33
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4-
opensource-codeofconduct@amazon.com with any additional questions or comments.
4+
opensource-codeofconduct@amazon.com with any additional questions or comments.

CONTRIBUTING.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,9 @@ GitHub provides additional document on [forking a repository](https://help.githu
4343
## Finding contributions to work on
4444
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
4545

46-
47-
## Code of Conduct
48-
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49-
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50-
opensource-codeofconduct@amazon.com with any additional questions or comments.
51-
52-
5346
## Security issue notifications
5447
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
5548

5649

5750
## Licensing
58-
59-
See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
51+
See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
MIT No Attribution
1+
MIT License
22

3-
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy of
66
this software and associated documentation files (the "Software"), to deal in

README.md

Lines changed: 150 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,158 @@
1-
## My Project
1+
# AWS Lambda Actions for AWS FIS
22

3-
TODO: Fill this README out!
3+
## Introduction
4+
The AWS Fault Injection Service (FIS) supports AWS Lambda Actions which allows you to inject faults into
5+
the Lambda execution environments. As part of their resilience plan, Lambda fault actions
6+
enable you, our AWS customers, to demonstrate that their Lambda-based applications operate
7+
as expected during periods of AWS impairment, in response to misconfigurations, or in
8+
response to bad data.
49

5-
Be sure to:
10+
## Prerequisites
11+
- [CDK Toolkit](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) & bootstrapped AWS environment
12+
- [docker](https://docs.docker.com/engine/install/)
13+
- [mvn](https://maven.apache.org/run.html)
614

7-
* Change the title in this README
8-
* Edit your repository description on GitHub
15+
> **[!IMPORTANT]**
16+
> You need to deploy the stack to an AWS Region where [AWS FIS is supported](https://docs.aws.amazon.com/general/latest/gr/fis.html).
917
10-
## Security
18+
> **[!IMPORTANT]**
19+
> This application deploy publicly available endpoints you'll use to interact with the application. Don't forget to cleanup the deployment following steps below to avoid unnecessary costs.
1120
12-
See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
21+
## Solution Overview
1322

14-
## License
23+
### Sample Application
1524

16-
This library is licensed under the MIT-0 License. See the LICENSE file.
25+
This repository contains three (3) serverless applications and FIS experiment templates using FIS Lambda Actions.
26+
27+
Sample applications are simple CRUD APIs that allow you to manage orders. They are built using Amazon API Gateway, AWS Lambda, and Amazon DynamoDB. It provides simple Create, Read, Update, and Delete (CRUD) functionality to manage orders.
28+
29+
![Application Architecture](./images/FISLambdaActionsemoEnvronment.png)
30+
31+
The different APIs and its Lambda functions are implemented using three different runtimes: Node.js, Python and Java.
32+
33+
### FIS Templates
34+
This repository also deploys the FIS experiment templates which carry out the Lambda actions. Separate experiment templates will be deployed for each of the sample applications. There will be two FIS templates per sample application.
35+
36+
1. **Lambda Latency Injection Fault** - this FIS template utilize the *[aws:lambda:invocation-add-delay](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#invocation-add-delay)* action.
37+
It is configured to inject 2000ms (2 seconds) latency into 100% of the request for 10 minutes.
38+
39+
![FISLambda_Actions](./images/FISLambda_Latency_Actions.png)
40+
41+
2. **Lambda Http Integration Response Fault** - FIS template utilize the*[aws:lambda:invocation-http-integration-response](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#invocation-http-integration-response)*.
42+
43+
It is configured to inject error responses of status code 500 for 100% of the request for 10 minutes. It will also prevent the actual execution of the Lambda Function.
44+
45+
![FISLambda_Actions](./images/FISLambda_Integration_Actions.png)
46+
47+
### Observability Dashboards
48+
Repository also implements observability dashboards for each of the CRUD applications deployed.
49+
50+
51+
## Getting started
52+
53+
The CDK code deploys all necessary resources for the experiments.
54+
55+
See the official [AWS FIS Actions](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html) documentation page for more information.
56+
57+
### Setup
58+
59+
#### Deploy resources
60+
To deploy resources, please execute the following command in the CLI environment, where you have already logged into the AWS account.
61+
62+
```
63+
cd cdk-lambda-chaos
64+
npm ci
65+
cdk deploy --all --parameters FisLambdaAPIs:fisLambdaLayerARN='arn:aws:lambda:us-east-1:211125607513:layer:aws-fis-extension-x86_64:9'
66+
cd ..
67+
```
68+
69+
Once deployment is completed - you'll be presented with the API endpoints. Please make a note of them.
70+
![API Endpoints output](/images/cdk_output.png)
71+
72+
73+
#### Install dependencies for load generation
74+
Please execute the following command in the CLI environment
75+
76+
```
77+
cd load-generation
78+
npm install -g artillery@latest
79+
npm ci
80+
81+
```
82+
83+
#### Configure Variables for the experiment
84+
<!-- FisLambdaAPIs stack outputs the URL of deployed API which is exposing the AWS Lambda functions that you want to run the chaos experiments on. The screenshot below shows the output from FisLambdaAPIs stack. You can take the URL as highlighted in the screenshot as an example:
85+
![Retrieving API URL from 'Outputs' of FisLambdaAPIs Stack](./images/fisapistack-output-app-url.png) -->
86+
87+
As the next step, you need to configure environment variable API_URL with the API endpoint of the CRUD application that you want to run the chaos experiment for.
88+
89+
Use the API endpoint you've captured before and remove the trailing "/" from the url. Then set this as an environment variable as shown below.
1790

91+
```
92+
export API_URL='https://<api_id>.execute-api.<region>.amazonaws.com/prod'
93+
```
94+
95+
This would be used by the Artillery load generation script.
96+
97+
**NOTE:** *You just have to set the base path without leading '/' as '/' is added within the load generation configuration.*
98+
99+
### Run the experiment
100+
101+
#### Generate load
102+
**Note!** *Make sure to you have set the API_URL environment variable as shown above.*
103+
104+
Before you run the chaos engineering experiments using FIS, ensure that your application has reached steady state. See [Basic principles and guidelines](https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html#planning-basic-principles) to learn more on this. In this example, you can run load generation using following command to achieve steady state:
105+
106+
```
107+
artillery run load-generation-config.yml
108+
```
109+
110+
By default, this sends 4 requests per second for 10 minutes. You can change the during as well as number of requests for load generation in ``load-generation-config.yml`` file. See [Artillery documentation](https://www.artillery.io/docs/get-started/first-test#define-load-phases) for more details.
111+
112+
Go to the [AWS CloudWatch Console](https://console.aws.amazon.com/cloudwatch/) where you'll find three dashboards.
113+
![CloudWatchDashboard](./images/CloudWatchDashboard.png)
114+
115+
Select the dashboard for the the application you are testing and observe the steady state.
116+
117+
118+
#### Start the experiment
119+
Go to the [AWS Resilience HUB Console](https://console.aws.amazon.com/resiliencehub/home). Navigate to the **Resilience testing** and select **Experiment templates**. You'll see the list of the FIS Experiment Templates deployed for you.
120+
121+
![FIS_List_of_experments](./images/FIS_List_of_experments.png)
122+
123+
Select FIS experiment template for the experiment and integration you'd like execute and press **Start Experiment** again press on **Start Experiment** button on the next screen to run the experiments.
124+
125+
![FIS_List_of_experments_start](./images/FIS_List_of_experments_start.png)
126+
127+
128+
#### Monitor results
129+
130+
Once you have run the load generation script and started the experiment, you can observe your application's behavior by looking at different metrics included in the [CloudWatch Dashboards](https://console.aws.amazon.com/cloudwatch/). To get a holistic view of your application behavior, this dashboard includes
131+
* metrics from Artillery load generation including number of requests and corresponding responses received, latency of response, any errors recorded by load generation script. This represents the user's perspective of your application.
132+
* corresponding metrics from API Gateway and Lambda Function that comprise the API we are invoking from load generation script and,
133+
* metrics from FIS extension showing the number of faults injected by the experiment.
134+
135+
Below is an example of running the 'Lambda Latency Injection Fault' experiment template.
136+
137+
![](./images/CloudWatchDashboard-TypeScript-AddDelay-Experiment.png)
138+
139+
The Dashboard is organized in four rows three columns:
140+
* First row represents the requests from load generation, corresponding API Gateway request count and corresponding Lambda invocations. They should represent and same count for steady state.
141+
* Second row shows response times recorded by load generation, latency from API Gateway and Lambda duration. You should see a correlation among these metrics when you run *aws:lambda:invocation-add-delay* experiment.
142+
* Third row shows API errors recorded by the load generation script, errors reported by API Gateway and errors in Lambda function invocations. If you run *aws:lambda:invocation-http-integration-response* experiment, you should see correlation in metrics in this row.
143+
* The last row represents *FaultInjected* metric. Based on the experiment you are running, you should see a correlation with either "FIS FaultInjected Invocation Delay" or "FIS FaultInjected HTTP Integration Response" graph.
144+
145+
NOTE: This dashboard includes only *FaultInjected* metric. You can explore [all EMF metrics emitted by AWS FIS Extension](https://docs.aws.amazon.com/fis/latest/userguide/use-lambda-actions.html) in *aws-fis-extension* Custom namespace in CloudWatch.
146+
147+
148+
### Cleanup
149+
Run the following command from the `cdk-lambda-chaos` folder.
150+
```
151+
cdk destroy --all
152+
```
153+
154+
## Contributing
155+
See [CONTRIBUTING](CONTRIBUTING.md) for more information.
156+
157+
## License
158+
This library is licensed under the MIT-0 License. See the LICENSE file.

cdk-lambda-chaos/.npmignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
*.ts
2+
!*.d.ts
3+
4+
# CDK asset staging directory
5+
.cdk.staging
6+
cdk.out
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env node
2+
import 'source-map-support/register';
3+
import * as cdk from 'aws-cdk-lib';
4+
import { Aspects, CfnParameter } from 'aws-cdk-lib';
5+
import { FisExperimentsStack } from '../lib/fis-experiments-stack';
6+
import { ServerlessApiStack } from '../lib/serverless-api-stack';
7+
import { TargetTag } from '../lib/shared/fis-lambda-chaos-shared';
8+
import { AwsSolutionsChecks } from 'cdk-nag';
9+
10+
const stackName = "FisLambda";
11+
const app = new cdk.App();
12+
// Aspects.of(app).add(new AwsSolutionsChecks({verbose: true}))
13+
14+
let apiResourceName = 'Orders';
15+
// TODO get lambda arn from SSM
16+
let fisLambdaLayerARN = 'arn:aws:lambda:us-east-1:211125607513:layer:aws-fis-extension-x86_64:9';
17+
let fisLambdaTagName = 'FISExperimentReady'
18+
let fisLambdaTagValue = 'Yes'
19+
let fisResourceTag: TargetTag = {
20+
TagName: fisLambdaTagName,
21+
TagValue: fisLambdaTagValue
22+
}
23+
let fisExperimentDuration = 10 // Duration of the Fault. Measured in minutes
24+
let fisInvocationPercentage = 100 // Percentage of the Invocation impacted by the Fault. Measured in %
25+
let fisStartupLatencyMilliseconds = 2000 // Latency startup delay for the latency injection experiment in milliseconds
26+
let fisHTTPIntegrationResponseCode = 500 // HTTP response code for the experiment with response code faults
27+
// Proxy response structure: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
28+
29+
const fisExperimentStack = new FisExperimentsStack(app, `${stackName}Experiments`, {
30+
env: {
31+
account: process.env.CDK_DEFAULT_ACCOUNT,
32+
region: process.env.AWS_REGION ?? process.env.CDK_DEFAULT_REGION,
33+
},
34+
ResourceTag: fisResourceTag, // This is only partially in use. Experiment template ignores tag name which is set already
35+
InvocationPercentage: fisInvocationPercentage,
36+
DurationMinutes: fisExperimentDuration,
37+
StartupLatencyMilliseconds: fisStartupLatencyMilliseconds,
38+
InvocationStatusCode: fisHTTPIntegrationResponseCode,
39+
StackName: stackName,
40+
});
41+
42+
const lambdaStack = new ServerlessApiStack(app, `${stackName}APIs`, {
43+
env: {
44+
account: process.env.CDK_DEFAULT_ACCOUNT,
45+
region: process.env.AWS_REGION ?? process.env.CDK_DEFAULT_REGION,
46+
},
47+
StackName: stackName,
48+
FisLambdaLayerARN: fisLambdaLayerARN,
49+
ResourceTag: fisResourceTag,
50+
ApiResourceName: apiResourceName
51+
});

cdk-lambda-chaos/cdk.json

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/fis-lambda-chaos.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
21+
"@aws-cdk/core:checkSecretUsage": true,
22+
"@aws-cdk/core:target-partitions": [
23+
"aws",
24+
"aws-cn"
25+
],
26+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
29+
"@aws-cdk/aws-iam:minimizePolicies": true,
30+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
31+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
32+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
33+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
34+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
35+
"@aws-cdk/core:enablePartitionLiterals": true,
36+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
37+
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
38+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
39+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
40+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
41+
"@aws-cdk/aws-route53-patters:useCertificate": true,
42+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
43+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
44+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
45+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
46+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
47+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
48+
"@aws-cdk/aws-redshift:columnId": true,
49+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
50+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
51+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
52+
"@aws-cdk/aws-kms:aliasNameRef": true,
53+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
54+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
55+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
56+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
57+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
58+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
59+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
60+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
61+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
62+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
63+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
64+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
65+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
66+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
67+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
68+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
69+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
70+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
71+
"@aws-cdk/aws-stepfunctions-tasks:ecsReduceRunTaskPermissions": true
72+
}
73+
}

cdk-lambda-chaos/jest.config.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
roots: ['<rootDir>/test'],
4+
testMatch: ['**/*.test.ts'],
5+
transform: {
6+
'^.+\\.tsx?$': 'ts-jest'
7+
}
8+
};

0 commit comments

Comments
 (0)