## File: README.md

# AWS CDK Examples

This repository contains a set of example projects for the [AWS Cloud Development
Kit](https://github.com/aws/aws-cdk).

## Table of Contents
1. [About this Repo](#About)
2. [Examples](#Examples)
3. [Learning Resources](#Learning)
4. [Additional Examples](#AddEx)
4. [License](#License)

## About this Repo <a name="About"></a>
This repo is our official list of CDK example code. The repo is subdivided into sections for each language (see ["Examples"](#Examples)). Each language has its own subsection of examples with the ultimate aim of complete language parity (same subset of examples exist in each language). These examples each provide a demonstration of a common service implementation, or infrastructure pattern that could be useful in your use of the CDK for building your own infrastructure.

We welcome contributions to this repo in the form of fixes to existing examples or addition of new examples. For more information on contributing, please see the [CONTRIBUTING](https://github.com/aws-samples/aws-cdk-examples/blob/master/CONTRIBUTING.md) guide.

This is considered an intermediate learning resource and should typically be referenced after reading the Developer Guide or CDK Workshop (please see [Learning Resources](#Learning) for more information on these resources).

## Examples <a name="Examples"></a>
This repo contains examples in each language supported by the CDK. Some languages are fully supported by [JSII](https://github.com/aws/jsii), but as additional languages are added, you will see those marked as `Developer Preview`. You can find the examples for each of those languages at the following links:

| Language | JSII Language-Stability |
|----------|-------------------------|
| [Typescript Examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript) | _Stable_ |
| [Python Examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/python) | _Stable_ |
| [.NET Examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/csharp) | _Stable_ |
| [Java Examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/java) | _Stable_ |
| [Go Examples](https://github.com/aws-samples/aws-cdk-examples/tree/master/go) | _Stable_ |


## Learning Resources <a name="Learning"></a>
While this is an excellent learning resource for the CDK, there are other resources that can be referenced to assist with your learning/development process.

### Official Resources
- [Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/home.html)
- [API Reference](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html)
- [CDK Repository](https://github.com/aws/aws-cdk)
- [CDK Construct Hub](https://constructs.dev/)
- [CDK Workshop](https://cdkworkshop.com/)

### Unofficial/Community Resources
- [AwesomeCDK](https://github.com/kolomied/awesome-cdk)

> If you have created a CDK learning resource and would like it to be listed here, please read the related [CONTRIBUTING](https://github.com/aws-samples/aws-cdk-examples/blob/master/CONTRIBUTING.md#Resources) section for more info.

## Additional Examples <a name="AddEx"></a>

The examples listed below are larger examples hosted in their own repositories that demonstrate more complex or complete CDK applications. 
>If you would like your repo to be listed here, please read the [CONTRIBUTING](https://github.com/aws-samples/aws-cdk-examples/blob/master/CONTRIBUTING.md#Resources) guide for more details.

| Example | Description | Owner |
|---------|-------------|-------|
| [aws-cdk-changelogs-demo](https://github.com/aws-samples/aws-cdk-changelogs-demo) | A full serverless Node.js application stack deployed using CDK. It uses AWS Lambda, AWS Fargate, DynamoDB, Elasticache, S3, and CloudFront. | AWS |


# License <a name="License"></a>

This library is licensed under the Apache 2.0 License.

---

## File: csharp/api-cors-lambda-crud-dynamodb/README.md

# APIGateway with CORS, Lambdas, and CRUD on DynamoDB




> **This is a stable example. It should successfully build out of the box**
>
> This examples is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.

---


This example deploys API Gateway, integrated with five Lambdas which perform CRUD operations against a DynamoDB table.

## Prerequisites
* Docker
* AWS CDK CLI

## Build
To build this app, you need to be in this example's root folder. Then run the following:


```bash
npm install aws-cdk
cdk synth
```

## Deploy
To deploy this app, you need to be in this example's root folder. Then run the following:


```bash
cdk bootstrap
cdk deploy
```

This will deploy / redeploy your Stack to your AWS Account. After the deployment you will see the API's URL, which represents the url you can then use.

---

## File: csharp/apigateway-cognito-lambda-dynamodb/README.md

# Fine-grained access control for API Gateway using Lambda Authorizer

## 



> **This is a stable example. It should successfully build out of the box**
>
> This examples is built on Construct Libraries marked "Stable" and does not have any infrastructure
> prerequisites to build.

---



This C# CDK example creates an Amazon Cognito user pool, Amazon API Gateway API, AWS Lambda function for authentication, Amazon DynamoDB table, and AWS Lambda function to act as a backend. The authentication function verifies a JWT token received in the request headers, then (if the token is valid) returns the access policy associated with the token's user group. Based on this access policy, API Gateway will to forward the request to the backend Lambda function or return a 401/403 http status.



Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred.

## Requirements

- [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
- [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/cli.html) installed and configured
- [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [.Net 6.0 SDK](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks) installed

## Deployment Instructions

1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
   ```
   git clone https://github.com/aws-samples/aws-cdk-examples.git
   ```
2. Change directory to this example's directory:
   ```
   cd csharp/apigateway-cognito-lambda-dynamodb
   ```
3. Build the application:
   ```
   dotnet build src
   ```
4. Create the necessary files for the backend function using `dotnet publish`:
   ```
   dotnet publish src/Lambda/BackendFunction/BackendFunction.csproj -c Release -o dist/BackendFunction
   ```
5. Repeat for the authentication function:
   ```
   dotnet publish src/Lambda/AuthFunction/AuthFunction.csproj -c Release -o dist/AuthFunction
   ```
6. Deploy the application using the AWS CDK:
   ```
   cdk deploy ApiGatewayAuthStack --app 'dotnet run --project src/CDK/cdk.csproj'
   ```
7. Note down the `CognitoHostedUIUrl` and `APIGWEndpoint` outputs from CloudFormation. You'll use them to test your function.

8. Populate the DynamoDB table used for authenticating requests. From the `apigateway-cognito-lambda-dynamodb` directory, run
   ```
   aws dynamodb batch-write-item --request-items file://src/DynamoDBData.json
   ```

## How it works

Users must present a JWT token from Cognito in the request to API Gateway. The AWS Cognito hosted UI, set up via the CDK, is the simplest way to interact with Cognito. If the header is not present in the request, API Gateway will return an HTTP401 Unauthorized status code. If a token is present in the request header then the request is passed on to the authentication lambda function for validation.

The token signature gets verified by the Auth lambda using JSON Web Keys (JWKs) provided by a Cognito User pool.

Once the token signature is verified (both in structure and expiry), code verifies the token's claims and retrieves the user group associated with the token. Based on that user group, the Lambda function reads the API Gateway access policy document from the DynamoDB table. If user group not present in DynamoDB table then the function returns a deny policy which will make API Gateway return an HTTP 403 Forbidden response to user. If user group is present in the DynamoDB table, the associated policy document will be return to API Gateway.

Based on the policy returned by Auth Lambda function, API Gateway decides either to forward the request to backend Lambda or return an HTTP 403 Forbidden response. If JWT token is invalid, in terms of JWT structure or signature, the authentication function raises an "Unauthorized" exception which in turns into 401 Unauthorized response back to the user.

As populated in DynamoDB as part of deployment steps, this configuration creates two user groups: `read-only` and `read-update-add`. `read-only` may only call GET on the backend, while `read-update-add` may make GET and POST operations against the backend.

## Testing

1. Login to the AWS console and navigate to Cognito service

2. Select User pool - `CognitoUserPool` and create a user. Remember the users email id and password -- you'll need it for testing
   

3. Add the newly created user to user group - "read-only"
   

4. Create another user and add it to user group `read-update-add`. Again, remember these credentials for testing.

5. Access the Cognito app client hosted UI - It's the `CognitoHostedUIUrl` from earlier.

6. Login to the Hosted UI with first user which is assigned to "read-only" user group. You may be asked to enter new password if this is the first login attempt. After a successful login, the UI will navigate user to a localhost URL with `access_token` in the url

7. Get the `access_token` (not id_token) from the localhost url

8. Use Postman or `curl` or REST client like `Yet Another Rest Client` chrome extension to invoke the GET endpoint in your API Gateway API (the `APIGWEndpoint` URL from CloudFormation), making sure to pass the value from access_token as the `Authorization` header. Make sure to include "Bearer " at the start of the token.
   

9. Confirm that you are returned an 200 Success response

10. Now invoke the same request with the POST verb and the same `access_token`.

11. Confirm that you are returned an HTTP 403 Unauthorized response.

12. Log into the Hosted UI as the second user you created following the steps previously described.

13. Make a GET request to the API Gateway HTTP Endpoint as you did previously, this time using the second user's `access_token` for the bearer token.

14. Confirm that you are returned a 200 Success response

15. Make a POST request to the API HTTP Endpoint

16. Confirm you are returned an HTTP 201 Created response

17. Try making a GET or POST request to the endpoint with invalid token

18. Observe that you're returned an HTTP 401 Unauthorized response

## Cleanup

Run the following commands at eventbridge-firehose-s3-cdk folder level

1. Delete the stack
   ```bash
   cdk destroy ApiGatewayAuthStack ---app 'dotnet run --project src/CDK/cdk.csproj'
   ```
1. Confirm the stack has been deleted
   ```bash
   aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'ApiGatewayAuthStack')].StackStatus"
   ```

## Related resources

[Verifying a JSON web token](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html)

[API GW Resource Policies](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-resource-policies.html)

[Control access for invoking an API](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html)

[API GW Policy statement resource expression format](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html#api-gateway-iam-policy-resource-format-for-executing-api)

[Lambda authorizer request format](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-input.html)

[Lambda authorizer response format](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html)

[Amazon Cognito hosted UI](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-integration.html)

[API Gateway Lambda authorizers](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)

---

## File: csharp/application-load-balancer/README.md

# Application Load Balancer

---



> **This is a stable example. It should successfully build out of the box**
>
> This examples es is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.

---


This example creates an AutoScalingGroup (containing a Micro-T2 EC2 machine running the Amazon Linux AMI), and an ApplicationLoadBalancer inside a shared VPC. It hooks up an open listener from the Load Balancer to the Scaling Group to indicate how many targets to balance between.

For more info on using Auto Scaling with Load Balancing see the AutoScaling guide [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-load-balancer.html).


## Build

To build this app, you need to be in this example's root folder. Then run the following:

```bash
npm install aws-cdk
dotnet build src
```

This will install the necessary CDK, then this example's dependencies, and then build your CloudFormation template.

## Deploy

Run `cdk deploy ApplicationLoadBalancerStack`. This will deploy / redeploy your Stack to your AWS Account.

After the deployment you will see the API's URL, which represents the url you can then use.

## Synthesize Cloudformation Template

To see the Cloudformation template generated by the CDK, run `cdk synth ApplicationLoadBalancerStack`, then check the output file in the "cdk.out" directory.

---

## File: csharp/appsync-graphql-dynamodb/README.md

# AppSync GraphQL API Acting on DynamoDB

---



> **This is an experimental example. It may not build out of the box**
>
> This examples is built on Construct Libraries marked "Experimental" and may not be updated for latest breaking changes.
>
> If build is unsuccessful, please create an [issue](https://github.com/aws-samples/aws-cdk-examples/issues/new) so that we may debug the problem 

---


This an example of an AppSync GraphQL API, pointing to four resolvers doing CRUD operations with a single DynamoDB table.

## Build

To build this app, you need to be in this example's root folder. Then run the following:

```bash
npm install aws-cdk
dotnet build src
```

This will install the necessary CDK, then this example's dependencies, and then build your .Net Project and your CloudFormation template.

## Deploy

Run `cdk deploy AppsyncGraphqlDynamodbStack`. This will deploy / redeploy your Stack to your AWS Account.

After the deployment you will see the API's URL, which represents the url you can then use.

## Synthesize Cloudformation Template

To see the Cloudformation template generated by the CDK, run `cdk synth AppsyncGraphqlDynamodbStack`, then check the output file in the "cdk.out" directory.

## The Component Structure

This Stack contains:

- a __GraphQL API__ with an API Key (Use with caution, each key is only valid for 7 days.)
- a __GraphQL Schema__ with Queries to get one and all items and two mutations to save and delete an item
- a __DynamoDB table__ `items` that stores the data with a Pay Per Request Billing Mode
- an __IAM Role__ that allows AppSync to invoke your DynamoDB table.
- an __AppSync DataSource__, connecting your API to the DynamoDB table with the previously specified role.
- a __AppSync Resolver__ for a Query `getOne` to get one item from the DynamoDB table.
- a __AppSync Resolver__ for a Query `all` to get all items from the DynamoDB table.
- a __AppSync Resolver__ for a Mutation `save` to put an item into the DynamoDB table (the id is autogenerated, you need only name).
- a __AppSync Resolver__ for a Mutation `delete` to delete one item from the DynamoDB table.

---

## File: csharp/capitalize-string/README.md

This package is an example on how to use AWS CDK to deploy a Lambda function handler.
Both the CDK app and the Lambda handler are written in C# and built using the `dotnet` CLI.

# This project

## Structure

In this project, `Program.cs` is the main entry point of the CDK app and the CDK construct
for the lambda function is configured in `CapitalizeStringStack.cs`.

The lambda function is another csharp project residing within the `CapitalizeStringHandler`
folder.

## Build & Deploy

Build -

```shell
cd CapitalizeStringHandler/src/CapitalizeStringHandler
dotnet build
dotnet tool install -g Amazon.Lambda.Tools # if not already
dotnet lambda package
cd ../../../
dotnet build src
```

Deploy & Test -

```shell
cdk deploy
dotnet lambda invoke-function <function-name> --payload "hello world"
```

# How to do this yourself?

## Pre-requisites

If you're unfamiliar with AWS Lambda functions in C#, read this first -
https://docs.aws.amazon.com/lambda/latest/dg/dotnet-programming-model.html

## Steps

1. Create the CDK app project folder -

    ```shell
    mkdir <cdk-project-folder> && cd <cdk-project-folder>
    cdk init -l=csharp
    ```

2. Modify the `.csproj` file to include the latest versions of the following NuGet packages -

    ```
    Amazon.CDK
    Amazon.CDK.AWS.Lambda
    Amazon.Jsii.Analyzers
    ```

3. Use the `dotnet` CLI to generate a c# project to manage the Lambda function handler -

    ```shell
    dotnet new -i Amazon.Lambda.Templates
    dotnet new lambda.EmptyFunction --name <handler-project-name>
    ```

    This should create a new folder with the same name as the project.
    For more details, see https://docs.aws.amazon.com/lambda/latest/dg/lambda-dotnet-coreclr-deployment-package.html

4. Look for the `.cs` file within the `src/` folder of the now created project folder.
    This is the entry point for your lambda function code. Modify the code as you see fit.

5. Now build and package the lambda function handler package -

    ```shell
    cd <handler-project-name>/src/<handler-project-name>
    dotnet build
    dotnet tool install -g Amazon.Lambda.Tools # if not already
    dotnet lambda package
    ```

    This should have created a folder `bin/Release/net6.0/publish/` which is the package
    that needs to be deployed to AWS Lambda as the function code.

6. In the CDK project, create an instance of `Function` class from the Lambda module.

    Specify the `Runtime` to be one of the `DOTNET_CORE` runtimes available and set the correct
    handler value based on the name of your lambda function project, namespaces and class name.

    Specify an `Asset` against the `Code` property, pointing to the location of the Lambda project
    on local disk. This must be the path to the `publish/` folder generated in the previous step,
    i.e., the relative path of the `publish/` folder from the CDK project root.

    See `LambdaCdkCsharpStack.cs` file in this project to see how this is done.
    See the lambda guide for more details -
    https://docs.aws.amazon.com/lambda/latest/dg/dotnet-programming-model-handler-types.html#dotnet-programming-model-handler-signatures

7. Build the CDK application and deploy -

    ```shell
    cd <cdk-project-folder>
    dotnet build src/
    cdk deploy
    ```

8. Invoke the lambda function using the `dotnet` CLI. The payload specified below works for the
   Lambda function configured in this project. Modify it per your lambda function.

    ```shell
    dotnet lambda invoke-function <function-name> --payload "hello world"
    ```

---

## File: csharp/classic-load-balancer/README.md

# Classic Load Balancer

---



> **This is a stable example. It should successfully build out of the box**
>
> This examples is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.

---


This example creates an AutoScalingGroup (containing a Micro-T3 EC2 machine running the Amazon Linux AMI), and a ClassicLoadBalancer inside a shared VPC. It hooks up an open listener from the Load Balancer to the Scaling Group to indicate how many targets to balance between.

For more info on using Auto Scaling with Load Balancing see the AutoScaling guide [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-load-balancer.html).

## Build

To build this app, you need to be in this example's root folder. Then run the following:

```bash
npm install aws-cdk
dotnet build src
```

This will install the necessary CDK, then this example's dependencies, and then build your .Net Project files and your CloudFormation template.

## Deploy

Run `cdk deploy ClassicLoadBalancerStack`. This will deploy / redeploy your Stack to your AWS Account.

After the deployment you will see the API's URL, which represents the url you can then use.

## Synthesize Cloudformation Template

To see the Cloudformation template generated by the CDK, run `cdk synth ClassicLoadBalancerStack`, then check the output file in the "cdk.out" directory.

---

## File: csharp/CloudFront-S3-WAF/README.md

# CloudFront-S3-WAF

---



> **This is a stable example. It should successfully build out of the box**
>
> This examples is built on Construct Libraries marked "Stable" and does not have any infrastructure
prerequisites to build.

---


This example creates S3 bucket, CloudFront distribution to host S3 static Website, and WAF Web ACL to restrict access to CloudFront distribution based on IP set.

## Build

To build this app, you need to be in this example's root folder. Then run the following:

```bash
npm install aws-cdk
dotnet build
```

This will install the necessary CDK, then this example's dependencies, and then build your .Net
Project files and your CloudFormation template.

## Deploy

Run `cdk deploy CloudFrontS3WafStack`. This will deploy / redeploy your Stack to your AWS Account.

After the deployment you will see the CloudFront URL, which represents the url you can then use.

## Synthesize Cloudformation Template

To see the Cloudformation template generated by the CDK, run `cdk synth CloudFrontS3WafStack`, then check
the output file in the"cdk.out" directory.

---

## File: csharp/custom-resource-cloudfront-invalidate/README.md

# Custom Resource CloudFront Invalidate

This example uses an [AwsCustomResource](https://docs.aws.amazon.com/cdk/api/v2/dotnet/api/Amazon.CDK.CustomResources.AwsCustomResource.html) to produce an invalidation on an Amazon CloudFront Distribution. A CloudFront Invalidation wipes away the cached content so that new changes in the distribution's origin can be seen immediately.

The `AwsCustomResource` CDK construct is an [L3 Construct](https://docs.aws.amazon.com/prescriptive-guidance/latest/aws-cdk-layers/layer-3.html) that can be used to create an AWS CloudFormation Custom Resource without having to directly create the AWS Lambda Function to support it.

An `AwsCustomResource` is appropriate to use when you have exactly one AWS SDK call to make per [stack task](https://docs.aws.amazon.com/vsts/latest/userguide/cloudformation-create-update.html): `onCreate`, `onUpdate`, and `onDelete`.

## Build

To build this app, you need to be in this example's root folder. Then run the following:

```bash
npm install aws-cdk
dotnet build src
```

This will install the necessary CDK, then this example's dependencies, and then build your csharp files and your CloudFormation template.

## Deploy

Run `cdk deploy CustomResourceCloudFrontInvalidateStack`. This will deploy / redeploy your Stack to your AWS Account.

After the deployment you will see the API's URL, which represents the url you can then use.


## Synthesize Cloudformation Template

To see the Cloudformation template generated by the CDK, run `cdk synth CustomResourceCloudFrontInvalidateStack`, then check the output file in the "cdk.out" directory.

---

## File: csharp/ec2-instance/README.md

# EC2 Instance Creation with CDK

This example will create:

- A new VPC
- Two public subnets
- A security group
- An EC2 instance in one of the subnets

The `/src/config.sh` file is used as [user-data](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html) for the EC2 instance. Update this with any commands you'd like to be executed when the EC2 instance first boots.

[_learn more about user-data_](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)

## To Build and Deploy

```bash
$ dotnet build
$ cdk bootstrap
$ cdk deploy
```

## To Destroy

```bash
# Destroy all project resources.
$ cdk destroy