Skip to content

Commit

Permalink
Merge branch 'main' into issue#822
Browse files Browse the repository at this point in the history
  • Loading branch information
jfan9 authored Nov 5, 2024
2 parents 26b5bc3 + a25bb9e commit e6315e9
Show file tree
Hide file tree
Showing 43 changed files with 2,686 additions and 0 deletions.
13 changes: 13 additions & 0 deletions java/cognito-api-lambda/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.classpath.txt
target
.classpath
.project
.idea
.settings
.vscode
*.iml

# CDK asset staging directory
.cdk.staging
cdk.out

55 changes: 55 additions & 0 deletions java/cognito-api-lambda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# APIGateway backed by Lambda and protected by a Cognito User Pool.


<!--BEGIN STABILITY BANNER-->

---

![Stability: Stable](https://img.shields.io/badge/stability-Stable-success.svg?style=for-the-badge)

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

This an example of an APIGateway that is protected with a Cognito User Pool, pointing to a Hello World Lambda.

## Build

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

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

This will install the necessary CDK, then this example's dependencies, and then build the CloudFormation template. The resulting CloudFormation template will be in the `cdk.out` directory.

## Deploy

Run `cdk deploy`.
This will deploy / redeploy the Stack to AWS.
After the deployment, the URL of the Rest API created will be available in the outputs of the CloudFormation stack and can be used to invoke the lambda function.
At this point, if an HTTP GET request is attempted on the Rest API without including and `Authorization` header, a `401 - Unauthorized` response will be returned.
In order for the authorization to succeed when the lambda function is invoked through the API Gateway, each request must include an `Authorization` HTTP header containing an access token obtained for the specific user from the user pool.

## The Component Structure

The main resources of the component are:

- A Lambda Function that returns the string "Hello world!"
- A Rest API with a GET method that points to the Lambda Function
- A Cognito User Pool
- An Authorizer for the Rest API with the User Pool attached.

## Useful commands

* `mvn package` compile and run tests
* `cdk ls` list all stacks in the app
* `cdk synth` emits the synthesized CloudFormation template
* `cdk deploy` deploy this stack to your default AWS account/region
* `cdk diff` compare deployed stack with current state
* `cdk docs` open CDK documentation
68 changes: 68 additions & 0 deletions java/cognito-api-lambda/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"app": "mvn -e -q compile exec:java",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"target",
"pom.xml",
"src/test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false
}
}
60 changes: 60 additions & 0 deletions java/cognito-api-lambda/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>

<groupId>com.myorg</groupId>
<artifactId>cognito-api-lambda</artifactId>
<version>0.1</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cdk.version>2.158.0</cdk.version>
<constructs.version>[10.0.0,11.0.0)</constructs.version>
<junit.version>5.7.1</junit.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>com.myorg.CognitoApiLambdaApp</mainClass>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<!-- AWS Cloud Development Kit -->
<dependency>
<groupId>software.amazon.awscdk</groupId>
<artifactId>aws-cdk-lib</artifactId>
<version>${cdk.version}</version>
</dependency>

<dependency>
<groupId>software.constructs</groupId>
<artifactId>constructs</artifactId>
<version>${constructs.version}</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.myorg;

import software.amazon.awscdk.App;
import software.amazon.awscdk.StackProps;

public class CognitoApiLambdaApp {
public static void main(final String... args) {
App app = new App();
StackProps stackProps = StackProps.builder().build();
new CognitoApiLambdaStack(app, "CognitoApiLambdaStack", stackProps);
app.synth();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.myorg;

import org.jetbrains.annotations.NotNull;
import software.amazon.awscdk.RemovalPolicy;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.apigateway.*;
import software.amazon.awscdk.services.cognito.SignInAliases;
import software.amazon.awscdk.services.cognito.UserPool;
import software.amazon.awscdk.services.lambda.InlineCode;
import software.amazon.awscdk.services.lambda.Runtime;
import software.amazon.awscdk.services.lambda.SingletonFunction;
import software.constructs.Construct;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public class CognitoApiLambdaStack extends Stack {

private record Authorizer(CfnAuthorizer authorizer) implements IAuthorizer {
@Override
public @NotNull String getAuthorizerId() {
return authorizer.getRef();
}
}

public CognitoApiLambdaStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
var helloWorldFunction = SingletonFunction.Builder.create(this, "helloWorldFunction")
.functionName("helloWorldFunction")
.code(InlineCode.fromInline(getInlineCode()))
.handler("index.handler")
.runtime(Runtime.PYTHON_3_12)
.uuid("")
.build();
var helloWorldLambdaRestApi = LambdaRestApi.Builder.create(this, "helloWorldLambdaRestApi")
.restApiName("Hello World API")
.cloudWatchRole(true)
.cloudWatchRoleRemovalPolicy(RemovalPolicy.DESTROY)
.handler(helloWorldFunction)
.proxy(false)
.build();
var signInAliases = SignInAliases.builder()
.email(true)
.build();
var userPool = UserPool.Builder.create(this, "userPool")
.signInAliases(signInAliases)
.removalPolicy(RemovalPolicy.DESTROY)
.build();
var authorizer = new Authorizer(
CfnAuthorizer.Builder.create(this, "cfnAuth")
.restApiId(helloWorldLambdaRestApi.getRestApiId())
.name("HelloWorldAPIAuthorizer")
.type("COGNITO_USER_POOLS")
.identitySource("method.request.header.Authorization")
.providerArns(List.of(userPool.getUserPoolArn()))
.build()
);
var helloResource = helloWorldLambdaRestApi.getRoot().addResource("HELLO");
var methodOptions = MethodOptions.builder()
.authorizationType(AuthorizationType.COGNITO)
.authorizer(authorizer)
.build();
helloResource.addMethod("GET", new LambdaIntegration(helloWorldFunction), methodOptions);
}

private String getInlineCode() {
try {
return new String(Files.readAllBytes(Path.of("src/main/resources/lambda/hello-world.py")));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import json

def handler(event, context):
print(event)
return {
'statusCode': 200,
'body': 'Hello world!'
}
Loading

0 comments on commit e6315e9

Please sign in to comment.