-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcdk.go
166 lines (141 loc) · 5.07 KB
/
cdk.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package main
import (
"fmt"
"os"
"github.com/aws/aws-cdk-go/awscdk/v2"
apigateway "github.com/aws/aws-cdk-go/awscdk/v2/awsapigatewayv2"
authorizers "github.com/aws/aws-cdk-go/awscdk/v2/awsapigatewayv2authorizers"
integrations "github.com/aws/aws-cdk-go/awscdk/v2/awsapigatewayv2integrations"
dynamodb "github.com/aws/aws-cdk-go/awscdk/v2/awsdynamodb"
"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
"github.com/aws/aws-cdk-go/awscdk/v2/awss3assets"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
)
const (
prefix = "jwt-"
defaultRegion = "eu-west-1"
burstLimit = 50 // Limit concurrent requests processing
rateLimit = 100 // Limit incoming requests when burst is taking an effect
)
type CdkStackProps struct {
awscdk.StackProps
}
func NewCdkStack(scope constructs.Construct, id string, props *CdkStackProps) awscdk.Stack {
var stackProps awscdk.StackProps
if props != nil {
stackProps = props.StackProps
}
stack := awscdk.NewStack(scope, &id, &stackProps)
// Create DynamoTable for storing auth request
table := dynamodb.NewTableV2(stack, jsii.String(prefix+"history"), &dynamodb.TablePropsV2{
PartitionKey: &dynamodb.Attribute{
Name: jsii.String("RequestId"),
Type: dynamodb.AttributeType_STRING,
},
RemovalPolicy: "DESTROY",
})
envVars := map[string]*string{
"JWTTABLE": table.TableName(),
}
// Create Http Apigateway
apigw := apigateway.NewHttpApi(stack, jsii.String(prefix+"authorized-http-apigateway"), &apigateway.HttpApiProps{
CreateDefaultStage: jsii.Bool(false), // Create own stage below
})
// Add new stage with custom throttling parameter, instead of default one
stage := apigw.AddStage(jsii.String(prefix+"stage"), &apigateway.HttpStageOptions{
StageName: jsii.String("prod"),
AutoDeploy: jsii.Bool(true),
Description: jsii.String("Production stage"),
Throttle: &apigateway.ThrottleSettings{
BurstLimit: jsii.Number(burstLimit),
RateLimit: jsii.Number(rateLimit),
},
})
// Create lambda authorizer function
authorizer := createFunc(stack, "authorizer", &envVars)
lambdaAUthorizer := authorizers.NewHttpLambdaAuthorizer(jsii.String("authorizer-func"), authorizer,
&authorizers.HttpLambdaAuthorizerProps{ResponseTypes: &[]authorizers.HttpLambdaResponseType{
authorizers.HttpLambdaResponseType_SIMPLE,
}})
// Create lambda handler function
handler := createFunc(stack, "handler", &envVars)
functionIntg := integrations.NewHttpLambdaIntegration(jsii.String(prefix+"integration"), handler,
&integrations.HttpLambdaIntegrationProps{
Timeout: awscdk.Duration_Seconds(jsii.Number(25)),
})
apigw.AddRoutes(&apigateway.AddRoutesOptions{
Path: jsii.String("/"),
Methods: &[]apigateway.HttpMethod{apigateway.HttpMethod_GET, apigateway.HttpMethod_POST},
Integration: functionIntg,
Authorizer: lambdaAUthorizer,
})
// Allow full access for funtions to dynamodb
table.GrantReadWriteData(authorizer)
table.GrantReadWriteData(handler)
// Output API gateway URL
awscdk.NewCfnOutput(
stack, jsii.String(prefix+"apigw URL"),
&awscdk.CfnOutputProps{Value: stage.Url(),
Description: jsii.String("API Gateway endpoint")},
)
// Output DynamoDB name
awscdk.NewCfnOutput(
stack, jsii.String(prefix+"dynamodb-name"),
&awscdk.CfnOutputProps{Value: table.TableName(),
Description: jsii.String("DynamoDB name")},
)
return stack
}
// Create aws lambda function from given source adn with given name
func createFunc(stack awscdk.Stack, name string, env *map[string]*string) awslambda.Function {
// Build functions using AL docker image locally
bundleOptions := awscdk.BundlingOptions{
Image: awslambda.Runtime_PROVIDED_AL2023().BundlingImage(),
Environment: &map[string]*string{
"GOCACHE": jsii.String("/tmp/.cache"),
"GOPATH": jsii.String("/tmp/go"),
},
Command: &[]*string{
jsii.String("bash"),
jsii.String("-c"),
jsii.String("cd " + name + " && go build -o /asset-output"),
},
}
// Set function's runtime properties
functionProps := awslambda.FunctionProps{
Runtime: awslambda.Runtime_PROVIDED_AL2023(),
Code: awslambda.Code_FromAsset(jsii.String("./"), &awss3assets.AssetOptions{
Bundling: &bundleOptions,
}),
Handler: jsii.String("index.main"),
Timeout: awscdk.Duration_Seconds(jsii.Number(30)),
Environment: env,
}
id := jsii.String(prefix + name)
return awslambda.NewFunction(stack, id, &functionProps)
}
func main() {
defer jsii.Close()
app := awscdk.NewApp(&awscdk.AppProps{})
NewCdkStack(app, prefix+"stack", &CdkStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
// env determines the AWS environment region in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
// Read region from custom environment variable AWS_REGION
region, isPresent := os.LookupEnv("AWS_REGION")
if !isPresent {
// Read region of chosen cdk CLI profile or fallback to default profile
region = defaultRegion
}
fmt.Println("Applying to region: ", region)
return &awscdk.Environment{
Region: jsii.String(region),
}
}