cfn-vpn 0.5.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/build-gem.yml +25 -0
- data/.github/workflows/release-gem.yml +34 -0
- data/.github/workflows/release-image.yml +33 -0
- data/Gemfile.lock +33 -39
- data/README.md +1 -247
- data/cfn-vpn.gemspec +4 -4
- data/docs/README.md +44 -0
- data/docs/certificate-users.md +89 -0
- data/docs/getting-started.md +128 -0
- data/docs/modifying.md +67 -0
- data/docs/routes.md +98 -0
- data/docs/scheduling.md +32 -0
- data/docs/sessions.md +27 -0
- data/lib/cfnvpn.rb +31 -27
- data/lib/cfnvpn/{client.rb → actions/client.rb} +5 -6
- data/lib/cfnvpn/{embedded.rb → actions/embedded.rb} +15 -15
- data/lib/cfnvpn/actions/init.rb +144 -0
- data/lib/cfnvpn/actions/modify.rb +169 -0
- data/lib/cfnvpn/actions/params.rb +73 -0
- data/lib/cfnvpn/{revoke.rb → actions/revoke.rb} +6 -6
- data/lib/cfnvpn/actions/routes.rb +196 -0
- data/lib/cfnvpn/{sessions.rb → actions/sessions.rb} +5 -5
- data/lib/cfnvpn/{share.rb → actions/share.rb} +10 -10
- data/lib/cfnvpn/actions/subnets.rb +78 -0
- data/lib/cfnvpn/certificates.rb +5 -5
- data/lib/cfnvpn/clientvpn.rb +49 -65
- data/lib/cfnvpn/compiler.rb +23 -0
- data/lib/cfnvpn/config.rb +34 -78
- data/lib/cfnvpn/{cloudformation.rb → deployer.rb} +47 -19
- data/lib/cfnvpn/log.rb +26 -26
- data/lib/cfnvpn/s3.rb +34 -4
- data/lib/cfnvpn/s3_bucket.rb +48 -0
- data/lib/cfnvpn/string.rb +33 -0
- data/lib/cfnvpn/templates/helper.rb +14 -0
- data/lib/cfnvpn/templates/lambdas.rb +35 -0
- data/lib/cfnvpn/templates/lambdas/auto_route_populator/app.py +175 -0
- data/lib/cfnvpn/templates/lambdas/scheduler/app.py +36 -0
- data/lib/cfnvpn/templates/vpn.rb +449 -0
- data/lib/cfnvpn/version.rb +1 -1
- metadata +73 -23
- data/lib/cfnvpn/cfhighlander.rb +0 -49
- data/lib/cfnvpn/init.rb +0 -109
- data/lib/cfnvpn/modify.rb +0 -103
- data/lib/cfnvpn/routes.rb +0 -84
- data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +0 -27
@@ -0,0 +1,36 @@
|
|
1
|
+
import boto3
|
2
|
+
import logging
|
3
|
+
|
4
|
+
logger = logging.getLogger()
|
5
|
+
logger.setLevel(logging.INFO)
|
6
|
+
|
7
|
+
def handler(event, context):
|
8
|
+
|
9
|
+
logger.info(f"updating cfn-vpn stack {event['StackName']} parameter AssociateSubnets with value {event['AssociateSubnets']}")
|
10
|
+
|
11
|
+
if event['AssociateSubnets'] == 'false':
|
12
|
+
logger.info(f"terminating current vpn sessions to {event['ClientVpnEndpointId']}")
|
13
|
+
ec2 = boto3.client('ec2')
|
14
|
+
resp = ec2.describe_client_vpn_connections(ClientVpnEndpointId=event['ClientVpnEndpointId'])
|
15
|
+
for conn in resp['Connections']:
|
16
|
+
if conn['Status']['Code'] == 'active':
|
17
|
+
ec2.terminate_client_vpn_connections(
|
18
|
+
ClientVpnEndpointId=event['ClientVpnEndpointId'],
|
19
|
+
ConnectionId=conn['ConnectionId']
|
20
|
+
)
|
21
|
+
logger.info(f"terminated session {conn['ConnectionId']}")
|
22
|
+
|
23
|
+
client = boto3.client('cloudformation')
|
24
|
+
logger.info(client.update_stack(
|
25
|
+
StackName=event['StackName'],
|
26
|
+
UsePreviousTemplate=True,
|
27
|
+
Capabilities=['CAPABILITY_IAM'],
|
28
|
+
Parameters=[
|
29
|
+
{
|
30
|
+
'ParameterKey': 'AssociateSubnets',
|
31
|
+
'ParameterValue': event['AssociateSubnets']
|
32
|
+
}
|
33
|
+
]
|
34
|
+
))
|
35
|
+
|
36
|
+
return 'OK'
|
@@ -0,0 +1,449 @@
|
|
1
|
+
require 'cfndsl'
|
2
|
+
require 'cfnvpn/templates/helper'
|
3
|
+
require 'cfnvpn/templates/lambdas'
|
4
|
+
|
5
|
+
module CfnVpn
|
6
|
+
module Templates
|
7
|
+
class Vpn < CfnDsl::CloudFormationTemplate
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(name, config)
|
14
|
+
Description "cfnvpn #{name} AWS Client-VPN"
|
15
|
+
Parameter(:AssociateSubnets) {
|
16
|
+
Type 'String'
|
17
|
+
Default 'true'
|
18
|
+
AllowedValues ['true', 'false']
|
19
|
+
Description 'Toggle to false to disassociate all Client VPN subnet associations'
|
20
|
+
}
|
21
|
+
|
22
|
+
Condition(:EnableSubnetAssociation, FnEquals(Ref(:AssociateSubnets), 'true'))
|
23
|
+
|
24
|
+
Logs_LogGroup(:ClientVpnLogGroup) {
|
25
|
+
LogGroupName FnSub("#{name}-ClientVpn")
|
26
|
+
RetentionInDays 30
|
27
|
+
}
|
28
|
+
|
29
|
+
EC2_ClientVpnEndpoint(:ClientVpnEndpoint) {
|
30
|
+
Description FnSub("cfnvpn #{name} AWS Client-VPN")
|
31
|
+
AuthenticationOptions([
|
32
|
+
if config[:type] == 'federated'
|
33
|
+
{
|
34
|
+
FederatedAuthentication: {
|
35
|
+
SAMLProviderArn: config[:saml_arn],
|
36
|
+
SelfServiceSAMLProviderArn: config[:saml_arn]
|
37
|
+
},
|
38
|
+
Type: 'federated-authentication'
|
39
|
+
}
|
40
|
+
elsif config[:type] == 'active-directory'
|
41
|
+
{
|
42
|
+
ActiveDirectory: {
|
43
|
+
DirectoryId: config[:directory_id]
|
44
|
+
},
|
45
|
+
Type: 'directory-service-authentication'
|
46
|
+
}
|
47
|
+
else
|
48
|
+
{
|
49
|
+
MutualAuthentication: {
|
50
|
+
ClientRootCertificateChainArn: config[:client_cert_arn]
|
51
|
+
},
|
52
|
+
Type: 'certificate-authentication'
|
53
|
+
}
|
54
|
+
end
|
55
|
+
])
|
56
|
+
ServerCertificateArn config[:server_cert_arn]
|
57
|
+
ClientCidrBlock config[:cidr]
|
58
|
+
ConnectionLogOptions({
|
59
|
+
CloudwatchLogGroup: Ref(:ClientVpnLogGroup),
|
60
|
+
Enabled: true
|
61
|
+
})
|
62
|
+
DnsServers config[:dns_servers].any? ? config[:dns_servers] : Ref('AWS::NoValue')
|
63
|
+
TagSpecifications([{
|
64
|
+
ResourceType: "client-vpn-endpoint",
|
65
|
+
Tags: [
|
66
|
+
{ Key: 'Name', Value: name }
|
67
|
+
]
|
68
|
+
}])
|
69
|
+
TransportProtocol config[:protocol]
|
70
|
+
SplitTunnel config[:split_tunnel]
|
71
|
+
}
|
72
|
+
|
73
|
+
network_assoc_dependson = []
|
74
|
+
config[:subnet_ids].each_with_index do |subnet, index|
|
75
|
+
suffix = index == 0 ? "" : "For#{subnet.resource_safe}"
|
76
|
+
|
77
|
+
EC2_ClientVpnTargetNetworkAssociation(:"ClientVpnTargetNetworkAssociation#{suffix}") {
|
78
|
+
Condition(:EnableSubnetAssociation)
|
79
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
80
|
+
SubnetId subnet
|
81
|
+
}
|
82
|
+
|
83
|
+
network_assoc_dependson << "ClientVpnTargetNetworkAssociation#{suffix}"
|
84
|
+
end
|
85
|
+
|
86
|
+
if config[:default_groups].any?
|
87
|
+
config[:default_groups].each do |group|
|
88
|
+
EC2_ClientVpnAuthorizationRule(:"TargetNetworkAuthorizationRule#{group.resource_safe}"[0..255]) {
|
89
|
+
Condition(:EnableSubnetAssociation)
|
90
|
+
DependsOn network_assoc_dependson if network_assoc_dependson.any?
|
91
|
+
Description FnSub("#{name} client-vpn auth rule for subnet association")
|
92
|
+
AccessGroupId group
|
93
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
94
|
+
TargetNetworkCidr CfnVpn::Templates::Helper.get_auth_cidr(config[:region], config[:subnet_ids].first)
|
95
|
+
}
|
96
|
+
end
|
97
|
+
else
|
98
|
+
EC2_ClientVpnAuthorizationRule(:"TargetNetworkAuthorizationRule") {
|
99
|
+
Condition(:EnableSubnetAssociation)
|
100
|
+
DependsOn network_assoc_dependson if network_assoc_dependson.any?
|
101
|
+
Description FnSub("#{name} client-vpn auth rule for subnet association")
|
102
|
+
AuthorizeAllGroups true
|
103
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
104
|
+
TargetNetworkCidr CfnVpn::Templates::Helper.get_auth_cidr(config[:region], config[:subnet_ids].first)
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
if !config[:internet_route].nil?
|
109
|
+
EC2_ClientVpnRoute(:RouteToInternet) {
|
110
|
+
Condition(:EnableSubnetAssociation)
|
111
|
+
DependsOn network_assoc_dependson if network_assoc_dependson.any?
|
112
|
+
Description "Route to the internet through subnet #{config[:internet_route]}"
|
113
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
114
|
+
DestinationCidrBlock '0.0.0.0/0'
|
115
|
+
TargetVpcSubnetId config[:internet_route]
|
116
|
+
}
|
117
|
+
|
118
|
+
EC2_ClientVpnAuthorizationRule(:RouteToInternetAuthorizationRule) {
|
119
|
+
Condition(:EnableSubnetAssociation)
|
120
|
+
DependsOn network_assoc_dependson if network_assoc_dependson.any?
|
121
|
+
Description "Internet route authorization from subnet #{config[:internet_route]}"
|
122
|
+
AuthorizeAllGroups true
|
123
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
124
|
+
TargetNetworkCidr '0.0.0.0/0'
|
125
|
+
}
|
126
|
+
|
127
|
+
output(:InternetRoute, config[:internet_route])
|
128
|
+
end
|
129
|
+
|
130
|
+
dns_routes = config[:routes].select {|route| route.has_key?(:dns)}
|
131
|
+
cidr_routes = config[:routes].select {|route| route.has_key?(:cidr)}
|
132
|
+
|
133
|
+
if dns_routes.any?
|
134
|
+
auto_route_populator(name, config[:bucket])
|
135
|
+
|
136
|
+
dns_routes.each do |route|
|
137
|
+
input = {
|
138
|
+
Record: route[:dns],
|
139
|
+
ClientVpnEndpointId: "${ClientVpnEndpoint}",
|
140
|
+
TargetSubnet: route[:subnet],
|
141
|
+
Description: route[:desc]
|
142
|
+
}
|
143
|
+
|
144
|
+
if route[:groups].any?
|
145
|
+
input[:Groups] = route[:groups]
|
146
|
+
end
|
147
|
+
|
148
|
+
Events_Rule(:"CfnVpnAutoRoutePopulatorEvent#{route[:dns].resource_safe}"[0..255]) {
|
149
|
+
State 'ENABLED'
|
150
|
+
Description "cfnvpn auto route populator schedule for #{route[:dns]}"
|
151
|
+
ScheduleExpression "rate(5 minutes)"
|
152
|
+
Targets([
|
153
|
+
{
|
154
|
+
Arn: FnGetAtt(:CfnVpnAutoRoutePopulator, :Arn),
|
155
|
+
Id: "cfnvpnautoroutepopulator#{route[:dns].event_id_safe}",
|
156
|
+
Input: FnSub(input.to_json)
|
157
|
+
}
|
158
|
+
])
|
159
|
+
}
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
if cidr_routes.any?
|
164
|
+
cidr_routes.each do |route|
|
165
|
+
EC2_ClientVpnRoute(:"#{route[:cidr].resource_safe}VpnRoute") {
|
166
|
+
Description "cfnvpn static route for #{route[:cidr]}. #{route[:desc]}".strip
|
167
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
168
|
+
DestinationCidrBlock route[:cidr]
|
169
|
+
TargetVpcSubnetId route[:subnet]
|
170
|
+
}
|
171
|
+
|
172
|
+
if route[:groups].any?
|
173
|
+
route[:groups].each do |group|
|
174
|
+
EC2_ClientVpnAuthorizationRule(:"#{route[:cidr].resource_safe}AuthorizationRule#{group.resource_safe}"[0..255]) {
|
175
|
+
Description "cfnvpn static authorization rule for group #{group} to route #{route[:cidr]}. #{route[:desc]}".strip
|
176
|
+
AccessGroupId group
|
177
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
178
|
+
TargetNetworkCidr route[:cidr]
|
179
|
+
}
|
180
|
+
end
|
181
|
+
else
|
182
|
+
EC2_ClientVpnAuthorizationRule(:"#{route[:cidr].resource_safe}AllowAllAuthorizationRule") {
|
183
|
+
Description "cfnvpn static allow all authorization rule to route #{route[:cidr]}. #{route[:desc]}".strip
|
184
|
+
AuthorizeAllGroups true
|
185
|
+
ClientVpnEndpointId Ref(:ClientVpnEndpoint)
|
186
|
+
TargetNetworkCidr route[:cidr]
|
187
|
+
}
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
SSM_Parameter(:CfnVpnConfig) {
|
193
|
+
Description "#{name} cfnvpn config"
|
194
|
+
Name "/cfnvpn/config/#{name}"
|
195
|
+
Tier 'Standard'
|
196
|
+
Type 'String'
|
197
|
+
Value config.to_json
|
198
|
+
Tags({
|
199
|
+
Name: "#{name}-cfnvpn-config",
|
200
|
+
Environment: 'cfnvpn'
|
201
|
+
})
|
202
|
+
}
|
203
|
+
|
204
|
+
if config[:start] || config[:stop]
|
205
|
+
scheduler(name, config[:start], config[:stop], config[:bucket])
|
206
|
+
output(:Start, config[:start]) if config[:start]
|
207
|
+
output(:Stop, config[:stop]) if config[:stop]
|
208
|
+
end
|
209
|
+
|
210
|
+
output(:ServerCertArn, config[:server_cert_arn])
|
211
|
+
output(:Cidr, config[:cidr])
|
212
|
+
output(:DnsServers, config.fetch(:dns_servers, []).join(','))
|
213
|
+
output(:SubnetIds, config[:subnet_ids].join(','))
|
214
|
+
output(:SplitTunnel, config[:split_tunnel])
|
215
|
+
output(:Protocol, config[:protocol])
|
216
|
+
output(:Type, config[:type])
|
217
|
+
|
218
|
+
if config[:type] == 'federated'
|
219
|
+
output(:SamlArn, config[:saml_arn])
|
220
|
+
elsif config[:type] == 'active-directory'
|
221
|
+
output(:DirectoryId, config[:directory_id])
|
222
|
+
else
|
223
|
+
output(:ClientCertArn, config[:client_cert_arn])
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def output(name, value)
|
228
|
+
Output(name) { Value value }
|
229
|
+
end
|
230
|
+
|
231
|
+
def auto_route_populator(name, bucket)
|
232
|
+
IAM_Role(:CfnVpnAutoRoutePopulatorRole) {
|
233
|
+
AssumeRolePolicyDocument({
|
234
|
+
Version: '2012-10-17',
|
235
|
+
Statement: [{
|
236
|
+
Effect: 'Allow',
|
237
|
+
Principal: { Service: [ 'lambda.amazonaws.com' ] },
|
238
|
+
Action: [ 'sts:AssumeRole' ]
|
239
|
+
}]
|
240
|
+
})
|
241
|
+
Path '/cfnvpn/'
|
242
|
+
Policies([
|
243
|
+
{
|
244
|
+
PolicyName: 'client-vpn',
|
245
|
+
PolicyDocument: {
|
246
|
+
Version: '2012-10-17',
|
247
|
+
Statement: [{
|
248
|
+
Effect: 'Allow',
|
249
|
+
Action: [
|
250
|
+
'ec2:AuthorizeClientVpnIngress',
|
251
|
+
'ec2:RevokeClientVpnIngress',
|
252
|
+
'ec2:DescribeClientVpnAuthorizationRules',
|
253
|
+
'ec2:DescribeClientVpnEndpoints',
|
254
|
+
'ec2:DescribeClientVpnRoutes',
|
255
|
+
'ec2:CreateClientVpnRoute',
|
256
|
+
'ec2:DeleteClientVpnRoute'
|
257
|
+
],
|
258
|
+
Resource: '*'
|
259
|
+
}]
|
260
|
+
}
|
261
|
+
},
|
262
|
+
{
|
263
|
+
PolicyName: 'logging',
|
264
|
+
PolicyDocument: {
|
265
|
+
Version: '2012-10-17',
|
266
|
+
Statement: [{
|
267
|
+
Effect: 'Allow',
|
268
|
+
Action: [
|
269
|
+
'logs:DescribeLogGroups',
|
270
|
+
'logs:CreateLogGroup',
|
271
|
+
'logs:CreateLogStream',
|
272
|
+
'logs:DescribeLogStreams',
|
273
|
+
'logs:PutLogEvents'
|
274
|
+
],
|
275
|
+
Resource: '*'
|
276
|
+
}]
|
277
|
+
}
|
278
|
+
}
|
279
|
+
])
|
280
|
+
Tags([
|
281
|
+
{ Key: 'Name', Value: "#{name}-cfnvpn-auto-route-populator-role" },
|
282
|
+
{ Key: 'Environment', Value: 'cfnvpn' }
|
283
|
+
])
|
284
|
+
}
|
285
|
+
|
286
|
+
s3_key = CfnVpn::Templates::Lambdas.package_lambda(name: name, bucket: bucket, func: 'auto_route_populator', files: ['app.py'])
|
287
|
+
|
288
|
+
Lambda_Function(:CfnVpnAutoRoutePopulator) {
|
289
|
+
Runtime 'python3.8'
|
290
|
+
Role FnGetAtt(:CfnVpnAutoRoutePopulatorRole, :Arn)
|
291
|
+
MemorySize '128'
|
292
|
+
Handler 'app.handler'
|
293
|
+
Timeout 60
|
294
|
+
Code({
|
295
|
+
S3Bucket: bucket,
|
296
|
+
S3Key: s3_key
|
297
|
+
})
|
298
|
+
Tags([
|
299
|
+
{ Key: 'Name', Value: "#{name}-cfnvpn-auto-route-populator" },
|
300
|
+
{ Key: 'Environment', Value: 'cfnvpn' }
|
301
|
+
])
|
302
|
+
}
|
303
|
+
|
304
|
+
Logs_LogGroup(:CfnVpnAutoRoutePopulatorLogGroup) {
|
305
|
+
LogGroupName FnSub("/aws/lambda/${CfnVpnAutoRoutePopulator}")
|
306
|
+
RetentionInDays 30
|
307
|
+
}
|
308
|
+
|
309
|
+
Lambda_Permission(:CfnVpnAutoRoutePopulatorFunctionPermissions) {
|
310
|
+
FunctionName Ref(:CfnVpnAutoRoutePopulator)
|
311
|
+
Action 'lambda:InvokeFunction'
|
312
|
+
Principal 'events.amazonaws.com'
|
313
|
+
}
|
314
|
+
end
|
315
|
+
|
316
|
+
def scheduler(name, start, stop, bucket)
|
317
|
+
IAM_Role(:ClientVpnSchedulerRole) {
|
318
|
+
AssumeRolePolicyDocument({
|
319
|
+
Version: '2012-10-17',
|
320
|
+
Statement: [{
|
321
|
+
Effect: 'Allow',
|
322
|
+
Principal: { Service: [ 'lambda.amazonaws.com' ] },
|
323
|
+
Action: [ 'sts:AssumeRole' ]
|
324
|
+
}]
|
325
|
+
})
|
326
|
+
Path '/cfnvpn/'
|
327
|
+
Policies([
|
328
|
+
{
|
329
|
+
PolicyName: 'cloudformation',
|
330
|
+
PolicyDocument: {
|
331
|
+
Version: '2012-10-17',
|
332
|
+
Statement: [{
|
333
|
+
Effect: 'Allow',
|
334
|
+
Action: [
|
335
|
+
'cloudformation:UpdateStack'
|
336
|
+
],
|
337
|
+
Resource: FnSub("arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/#{name}-cfnvpn/*")
|
338
|
+
}]
|
339
|
+
}
|
340
|
+
},
|
341
|
+
{
|
342
|
+
PolicyName: 'client-vpn',
|
343
|
+
PolicyDocument: {
|
344
|
+
Version: '2012-10-17',
|
345
|
+
Statement: [{
|
346
|
+
Effect: 'Allow',
|
347
|
+
Action: [
|
348
|
+
'ec2:AssociateClientVpnTargetNetwork',
|
349
|
+
'ec2:DisassociateClientVpnTargetNetwork',
|
350
|
+
'ec2:DescribeClientVpnTargetNetworks',
|
351
|
+
'ec2:AuthorizeClientVpnIngress',
|
352
|
+
'ec2:RevokeClientVpnIngress',
|
353
|
+
'ec2:DescribeClientVpnAuthorizationRules',
|
354
|
+
'ec2:DescribeClientVpnEndpoints',
|
355
|
+
'ec2:DescribeClientVpnConnections',
|
356
|
+
'ec2:TerminateClientVpnConnections'
|
357
|
+
],
|
358
|
+
Resource: '*'
|
359
|
+
}]
|
360
|
+
}
|
361
|
+
},
|
362
|
+
{
|
363
|
+
PolicyName: 'logging',
|
364
|
+
PolicyDocument: {
|
365
|
+
Version: '2012-10-17',
|
366
|
+
Statement: [{
|
367
|
+
Effect: 'Allow',
|
368
|
+
Action: [
|
369
|
+
'logs:DescribeLogGroups',
|
370
|
+
'logs:CreateLogGroup',
|
371
|
+
'logs:CreateLogStream',
|
372
|
+
'logs:DescribeLogStreams',
|
373
|
+
'logs:PutLogEvents'
|
374
|
+
],
|
375
|
+
Resource: '*'
|
376
|
+
}]
|
377
|
+
}
|
378
|
+
}
|
379
|
+
])
|
380
|
+
Tags([
|
381
|
+
{ Key: 'Name', Value: "#{name}-cfnvpn-scheduler-role" },
|
382
|
+
{ Key: 'Environment', Value: 'cfnvpn' }
|
383
|
+
])
|
384
|
+
}
|
385
|
+
|
386
|
+
s3_key = CfnVpn::Templates::Lambdas.package_lambda(name: name, bucket: bucket, func: 'scheduler', files: ['app.py'])
|
387
|
+
|
388
|
+
Lambda_Function(:ClientVpnSchedulerFunction) {
|
389
|
+
Runtime 'python3.8'
|
390
|
+
Role FnGetAtt(:ClientVpnSchedulerRole, :Arn)
|
391
|
+
MemorySize '128'
|
392
|
+
Handler 'app.handler'
|
393
|
+
Timeout 60
|
394
|
+
Code({
|
395
|
+
S3Bucket: bucket,
|
396
|
+
S3Key: s3_key
|
397
|
+
})
|
398
|
+
Tags([
|
399
|
+
{ Key: 'Name', Value: "#{name}-cfnvpn-scheduler-function" },
|
400
|
+
{ Key: 'Environment', Value: 'cfnvpn' }
|
401
|
+
])
|
402
|
+
}
|
403
|
+
|
404
|
+
Logs_LogGroup(:ClientVpnSchedulerLogGroup) {
|
405
|
+
LogGroupName FnSub("/aws/lambda/${ClientVpnSchedulerFunction}")
|
406
|
+
RetentionInDays 30
|
407
|
+
}
|
408
|
+
|
409
|
+
Lambda_Permission(:ClientVpnSchedulerFunctionPermissions) {
|
410
|
+
FunctionName Ref(:ClientVpnSchedulerFunction)
|
411
|
+
Action 'lambda:InvokeFunction'
|
412
|
+
Principal 'events.amazonaws.com'
|
413
|
+
}
|
414
|
+
|
415
|
+
if start
|
416
|
+
Events_Rule(:ClientVpnSchedulerStart) {
|
417
|
+
State 'ENABLED'
|
418
|
+
Description "cfnvpn start schedule"
|
419
|
+
ScheduleExpression "cron(#{start})"
|
420
|
+
Targets([
|
421
|
+
{
|
422
|
+
Arn: FnGetAtt(:ClientVpnSchedulerFunction, :Arn),
|
423
|
+
Id: 'cfnvpnschedulerstart',
|
424
|
+
Input: FnSub({ StackName: "#{name}-cfnvpn", AssociateSubnets: 'true', ClientVpnEndpointId: "${ClientVpnEndpoint}" }.to_json)
|
425
|
+
}
|
426
|
+
])
|
427
|
+
}
|
428
|
+
end
|
429
|
+
|
430
|
+
if stop
|
431
|
+
Events_Rule(:ClientVpnSchedulerStop) {
|
432
|
+
State 'ENABLED'
|
433
|
+
Description "cfnvpn stop schedule"
|
434
|
+
ScheduleExpression "cron(#{stop})"
|
435
|
+
Targets([
|
436
|
+
{
|
437
|
+
Arn: FnGetAtt(:ClientVpnSchedulerFunction, :Arn),
|
438
|
+
Id: 'cfnvpnschedulerstop',
|
439
|
+
Input: FnSub({ StackName: "#{name}-cfnvpn", AssociateSubnets: 'false', ClientVpnEndpointId: "${ClientVpnEndpoint}" }.to_json)
|
440
|
+
}
|
441
|
+
])
|
442
|
+
}
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|