Skip to content

Commit

Permalink
Merge pull request #452 from ericzbeard/webapp
Browse files Browse the repository at this point in the history
Webapp
  • Loading branch information
ericzbeard authored Oct 1, 2024
2 parents 00c51c8 + 1c88b0d commit 07c7cef
Show file tree
Hide file tree
Showing 13 changed files with 2,792 additions and 126 deletions.
43 changes: 43 additions & 0 deletions CloudWatch/CloudWatch_Dashboard_NAT_FlowLogs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Creates a CloudWatch Dashboard with four CloudWatch Logs Insights log widgets that query VPC flow logs for NAT Gateway, related to https://repost.aws/knowledge-center/vpc-find-traffic-sources-nat-gateway",
"Parameters": {
"NatGatewayPrivateIP": {
"Description": "The private IP address of the NAT Gateway",
"Type": "String"
},
"NatGatewayID": {
"Description": "The ID of the NAT Gateway",
"Type": "String"
},
"VpcCidr": {
"Description": "The CIDR block of the VPC",
"Type": "String"
},
"LogGroupName": {
"Description": "The ARN of the log group to query",
"Type": "String"
}
},
"Resources": {
"CloudWatchDashboard": {
"Type": "AWS::CloudWatch::Dashboard",
"Properties": {
"DashboardName": {
"Fn::Sub": "${NatGatewayID}-Traffic-Dashboard"
},
"DashboardBody": {
"Fn::Sub": "{\n \"widgets\": [\n {\n \"type\": \"log\",\n \"x\": 0,\n \"y\": 0,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Instances sending most traffic through NAT gateway ${NatGatewayID}\", \n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 12,\n \"y\": 0,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) or (srcAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(dstAddr, '${VpcCidr}'))| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Traffic To and from NAT gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 0,\n \"y\": 9,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (srcAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(dstAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Most often upload communication destinations through NAT Gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 12,\n \"y\": 9,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Most often download communication destinations through NAT Gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n }\n ]\n}\n"
}
}
}
},
"Outputs": {
"DashboardArn": {
"Description": "ARN of the created CloudWatch Dashboard",
"Value": {
"Ref": "CloudWatchDashboard"
}
}
}
}
77 changes: 10 additions & 67 deletions CloudWatch/CloudWatch_Dashboard_NAT_FlowLogs.yaml
Original file line number Diff line number Diff line change
@@ -1,89 +1,32 @@
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Creates a CloudWatch Dashboard with four CloudWatch Logs Insights log widgets that query VPC flow logs for NAT Gateway, related to https://repost.aws/knowledge-center/vpc-find-traffic-sources-nat-gateway'
AWSTemplateFormatVersion: "2010-09-09"

Description: Creates a CloudWatch Dashboard with four CloudWatch Logs Insights log widgets that query VPC flow logs for NAT Gateway, related to https://repost.aws/knowledge-center/vpc-find-traffic-sources-nat-gateway

Resources:
CloudWatchDashboard:
Type: 'AWS::CloudWatch::Dashboard'
Type: AWS::CloudWatch::Dashboard
Properties:
DashboardName: !Sub '${NatGatewayID}-Traffic-Dashboard'
DashboardBody:
Fn::Sub: |
{
"widgets": [
{
"type": "log",
"x": 0,
"y": 0,
"width": 12,
"height": 9,
"properties": {
"query": "SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10",
"region": "${AWS::Region}",
"stacked": false,
"title": "Top 10 - Instances sending most traffic through NAT gateway ${NatGatewayID}",
"view": "table"
}
},
{
"type": "log",
"x": 12,
"y": 0,
"width": 12,
"height": 9,
"properties": {
"query": "SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) or (srcAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(dstAddr, '${VpcCidr}'))| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10",
"region": "${AWS::Region}",
"stacked": false,
"title": "Top 10 - Traffic To and from NAT gateway ${NatGatewayID}",
"view": "table"
}
},
{
"type": "log",
"x": 0,
"y": 9,
"width": 12,
"height": 9,
"properties": {
"query": "SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (srcAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(dstAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10",
"region": "${AWS::Region}",
"stacked": false,
"title": "Top 10 - Most often upload communication destinations through NAT Gateway ${NatGatewayID}",
"view": "table"
}
},
{
"type": "log",
"x": 12,
"y": 9,
"width": 12,
"height": 9,
"properties": {
"query": "SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10",
"region": "${AWS::Region}",
"stacked": false,
"title": "Top 10 - Most often download communication destinations through NAT Gateway ${NatGatewayID}",
"view": "table"
}
}
]
}
DashboardName: !Sub ${NatGatewayID}-Traffic-Dashboard
DashboardBody: !Sub "{\n \"widgets\": [\n {\n \"type\": \"log\",\n \"x\": 0,\n \"y\": 0,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Instances sending most traffic through NAT gateway ${NatGatewayID}\", \n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 12,\n \"y\": 0,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(srcAddr, '${VpcCidr}')) or (srcAddr like '${NatGatewayPrivateIP}' and isIpv4InSubnet(dstAddr, '${VpcCidr}'))| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Traffic To and from NAT gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 0,\n \"y\": 9,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (srcAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(dstAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Most often upload communication destinations through NAT Gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n },\n {\n \"type\": \"log\",\n \"x\": 12,\n \"y\": 9,\n \"width\": 12,\n \"height\": 9,\n \"properties\": {\n \"query\": \"SOURCE '${LogGroupName}' | fields @timestamp, @message | filter (dstAddr like '${NatGatewayPrivateIP}' and not isIpv4InSubnet(srcAddr, '${VpcCidr}')) | stats sum(bytes) as bytesTransferred by srcAddr, dstAddr | sort bytesTransferred desc | limit 10\",\n \"region\": \"${AWS::Region}\",\n \"stacked\": false,\n \"title\": \"Top 10 - Most often download communication destinations through NAT Gateway ${NatGatewayID}\",\n \"view\": \"table\"\n }\n }\n ]\n}\n"

Parameters:
NatGatewayPrivateIP:
Type: String
Description: The private IP address of the NAT Gateway

NatGatewayID:
Type: String
Description: The ID of the NAT Gateway

VpcCidr:
Type: String
Description: The CIDR block of the VPC

LogGroupName:
Type: String
Description: The ARN of the log group to query

Outputs:
DashboardArn:
Description: ARN of the created CloudWatch Dashboard
Value: !Ref CloudWatchDashboard
Value: !Ref CloudWatchDashboard
111 changes: 111 additions & 0 deletions RainModules/api-resource.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
Description: This module contains a lambda handler and the API Gateway resource to proxy requests to the lambda. It is assumed that the lambda function can handle all HTTPMethods sent to the specified path, including the OPTIONS pre-flight request. The lambda function must also return the approppriate CORS headers with each response.

Parameters:

Name:
Type: String
Description: This name will be used for resource names and tags

RestApi:
Type: String

RestApiDeployment:
Type: String

BuildScript:
Type: String
Description: The name of the script to run before uploading the lambda handler to S3

CodePath:
Type: String
Description: The path of the packaged lambda function created by BuildScript

ResourcePath:
Type: String
Description: The URI path name for the resource, for example, "user" or "order"

AuthorizerId:
Type: String
Description: The Id of the APIGateway Authorizer

Resources:

Handler:
Type: AWS::Lambda::Function
Properties:
Handler: bootstrap
FunctionName: !Sub ${Name}-handler
Runtime: provided.al2023
Code: !Rain::S3
Run: !Ref BuildScript
Zip: false
Path: !Ref CodePath
KeyProperty: S3Key
BucketProperty: S3Bucket
Role: !GetAtt HandlerRole.Arn

HandlerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Resource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !Sub ${RestApi.RootResourceId}
PathPart: !Ref ResourcePath
RestApiId: !Ref RestApi

Permission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt Handler.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*/*"

RootPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt Handler.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*/*/"

Options:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: OPTIONS
ResourceId: !Ref Resource
RestApiId: !Ref RestApi
AuthorizationType: NONE
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Handler.Arn}/invocations"

Get:
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: GET
ResourceId: !Ref Resource
RestApiId: !Ref RestApi
AuthorizationType: COGNITO_USER_POOLS
AuthorizerId: !Ref AuthorizerId
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Handler.Arn}/invocations"



33 changes: 27 additions & 6 deletions RainModules/bucket.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ Description: |
by default. It also creates an associated log bucket and replica bucket.
Parameters:

AppName:
Type: String
Description: |
This string will serve as a prefix for all resource names, which have
the general form of AppName-ResourceName-Region-Account.
Content:
Type: String
Description: A local path to a directory that will be uploaded to the bucket
Default: RAIN_NO_CONTENT

EmptyOnDelete:
Type: Boolean
Description: If true, the contents of all buckets will be permanently deleted when the stack is deleted.
Default: false

Resources:

LogBucket:
Expand All @@ -23,6 +34,9 @@ Resources:
SuppressedRules:
- S3_BUCKET_LOGGING_ENABLED
- S3_BUCKET_REPLICATION_ENABLED
Rain:
Content: RAIN_NO_CONTENT
EmptyOnDelete: !Ref EmptyOnDelete
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
Expand All @@ -44,8 +58,8 @@ Resources:
VersioningConfiguration:
Status: Enabled

LogBucketPolicy:
Type: !Rain::Module "bucket-policy.yml"
LogBucketAccess:
Type: !Rain::Module "bucket-policy.yaml"
Properties:
PolicyBucketName: !Sub ${AppName}-logs-${AWS::Region}-${AWS::AccountId}

Expand All @@ -55,6 +69,10 @@ Resources:
guard:
SuppressedRules:
- S3_BUCKET_DEFAULT_LOCK_ENABLED
Rain:
Content: !Ref Content
EmptyOnDelete: !Ref EmptyOnDelete
DistributionLogicalId: NONE
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
Expand All @@ -78,8 +96,8 @@ Resources:
VersioningConfiguration:
Status: Enabled

BucketPolicy:
Type: !Rain::Module "bucket-policy.yml"
BucketAccess:
Type: !Rain::Module "bucket-policy.yaml"
Properties:
PolicyBucketName: !Sub ${AppName}-${AWS::Region}-${AWS::AccountId}

Expand All @@ -96,6 +114,9 @@ Resources:
- S3_BUCKET_DEFAULT_LOCK_ENABLED
- S3_BUCKET_REPLICATION_ENABLED
- S3_BUCKET_LOGGING_ENABLED
Rain:
Content: RAIN_NO_CONTENT
EmptyOnDelete: !Ref EmptyOnDelete
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
Expand All @@ -111,8 +132,8 @@ Resources:
VersioningConfiguration:
Status: Enabled

ReplicaBucketPolicy:
Type: !Rain::Module "bucket-policy.yml"
ReplicaBucketAccess:
Type: !Rain::Module "bucket-policy.yaml"
Properties:
PolicyBucketName: !Sub ${AppName}-replicas-${AWS::Region}-${AWS::AccountId}

Expand Down
53 changes: 53 additions & 0 deletions RainModules/cognito.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
Description: This module creates a simple Cognito User Pool, Domain, and App Client.

Parameters:

AppName:
Type: String

CallbackURL:
Type: String

Resources:

UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Ref AppName
AdminCreateUserConfig:
AllowAdminCreateUserOnly: true
AutoVerifiedAttributes:
- email
MfaConfiguration: "OFF"
Schema:
- Name: email
Required: true
- Name: given_name
Required: true
- Name: family_name
Required: true

Domain:
Type: AWS::Cognito::UserPoolDomain
Properties:
Domain: !Ref AppName
UserPoolId: !Ref UserPool

Client:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: !Ref AppName
GenerateSecret: false
UserPoolId: !Ref UserPool
CallbackURLs:
- !Ref CallbackURL
AllowedOAuthFlows:
- code
AllowedOAuthFlowsUserPoolClient: true
AllowedOAuthScopes:
- phone
- email
- openid
SupportedIdentityProviders:
- COGNITO

Loading

0 comments on commit 07c7cef

Please sign in to comment.