cfn-vpn 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/docs/README.md +2 -1
- data/docs/certificate-users.md +1 -1
- data/docs/getting-started.md +35 -32
- data/docs/routes.md +48 -0
- data/docs/slack-notifications.md +35 -0
- data/lib/cfnvpn/actions/embedded.rb +3 -4
- data/lib/cfnvpn/actions/init.rb +8 -4
- data/lib/cfnvpn/actions/modify.rb +4 -2
- data/lib/cfnvpn/actions/revoke.rb +2 -3
- data/lib/cfnvpn/actions/routes.rb +20 -16
- data/lib/cfnvpn/actions/sessions.rb +4 -5
- data/lib/cfnvpn/actions/share.rb +3 -4
- data/lib/cfnvpn/actions/subnets.rb +2 -6
- data/lib/cfnvpn/clientvpn.rb +38 -22
- data/lib/cfnvpn/templates/lambdas/auto_route_populator/app.py +177 -92
- data/lib/cfnvpn/templates/lambdas/auto_route_populator/quotas.py +37 -0
- data/lib/cfnvpn/templates/lambdas/auto_route_populator/states.py +21 -0
- data/lib/cfnvpn/templates/lambdas/lib/slack.py +66 -0
- data/lib/cfnvpn/templates/lambdas/scheduler/app.py +42 -24
- data/lib/cfnvpn/templates/lambdas/scheduler/states.py +13 -0
- data/lib/cfnvpn/templates/lambdas.rb +10 -1
- data/lib/cfnvpn/templates/vpn.rb +81 -19
- data/lib/cfnvpn/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa61bd2028397a6a6becb482a6c8ec7a76122779672ea0b58c3f4b6d9fd50b03
|
4
|
+
data.tar.gz: 324fa44d60e5f92e1d2fc06dc008c6b1856ec289f09e9a935778bfb41a316b8d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c86170a4dc9643618677b3fcef80ebfb426d6c07fc0ecbc875fc1190c051b21eef7b6514824c0ac0afc89e2f05a1113942577752529c5397d3ed11d0d5dc5e61
|
7
|
+
data.tar.gz: 7f9061f8ffebbf703084b8100df2952a3d041525703b6ed9b6749d62d5ecf0332e06c3e9793486cd987614559b4c8207c63f9b2150b4cbee3c22e101309c333d
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cfn-vpn (1.
|
4
|
+
cfn-vpn (1.3.4)
|
5
5
|
aws-sdk-acm (~> 1, < 2)
|
6
6
|
aws-sdk-cloudformation (~> 1, < 2)
|
7
7
|
aws-sdk-ec2 (~> 1.95, < 2)
|
@@ -24,7 +24,7 @@ GEM
|
|
24
24
|
aws-sdk-cloudformation (1.49.0)
|
25
25
|
aws-sdk-core (~> 3, >= 3.112.0)
|
26
26
|
aws-sigv4 (~> 1.1)
|
27
|
-
aws-sdk-core (3.
|
27
|
+
aws-sdk-core (3.119.0)
|
28
28
|
aws-eventstream (~> 1, >= 1.0.2)
|
29
29
|
aws-partitions (~> 1, >= 1.239.0)
|
30
30
|
aws-sigv4 (~> 1.1)
|
data/docs/README.md
CHANGED
@@ -41,4 +41,5 @@ For further information on the authentication types please visit https://docs.aw
|
|
41
41
|
3. [Managing Certificate Users](certificate-users.md)
|
42
42
|
4. [Managing Routes](routes.md)
|
43
43
|
5. [Stop and Start Client-VPN](scheduling.md)
|
44
|
-
6. [Managing Sessions](sessions.md)
|
44
|
+
6. [Managing Sessions](sessions.md)
|
45
|
+
7. [Slack Notifications](slack-notifications.md)
|
data/docs/certificate-users.md
CHANGED
@@ -85,5 +85,5 @@ Modify base2-ciinabox.config.ovpn to include the full location of your extracted
|
|
85
85
|
echo "key /<path>/user1.key" >> myvpn.config.ovpn
|
86
86
|
echo "cert /<path>/user1.crt" >> myvpn.config.ovpn
|
87
87
|
|
88
|
-
Open myvpn.config.ovpn with your
|
88
|
+
Open myvpn.config.ovpn with your favorite openvpn client.
|
89
89
|
```
|
data/docs/getting-started.md
CHANGED
@@ -50,7 +50,7 @@ This is the default option when launching a ClientVPN using certificated based a
|
|
50
50
|
The following command and required options will launch a new certificate based Client-VPN
|
51
51
|
|
52
52
|
```sh
|
53
|
-
cfn-vpn init [name] --bucket [s3-bucket] --server-cn [server certificate name] --subnet-ids [list of
|
53
|
+
cfn-vpn init [name] --bucket [s3-bucket] --server-cn [server certificate name] --subnet-ids [list of subnets to associate with the vpn]
|
54
54
|
```
|
55
55
|
|
56
56
|
|
@@ -64,15 +64,15 @@ The following command and required option will launch a new federated based Clie
|
|
64
64
|
|
65
65
|
```sh
|
66
66
|
cfn-vpn init [name] --server-cn [server certificate name] \
|
67
|
-
--subnet-ids [list of
|
68
|
-
--saml-arn [identity
|
67
|
+
--subnet-ids [list of subnets to associate with the vpn] \
|
68
|
+
--saml-arn [identity provider arn]
|
69
69
|
```
|
70
70
|
|
71
71
|
The default authorization rule for the associated subnets allows all. You can optionally change this by using the `--default-groups` flag to set groups on the default authorization rule.
|
72
72
|
|
73
73
|
```diff
|
74
|
-
! Group id's must be used if creating
|
75
|
-
! Each SAML
|
74
|
+
! Group id's must be used if creating authorization rules.
|
75
|
+
! Each SAML provider will have different group id's and means of retrieving them.
|
76
76
|
```
|
77
77
|
|
78
78
|
```sh
|
@@ -104,16 +104,16 @@ The following command and required option will launch a new directory service ba
|
|
104
104
|
|
105
105
|
```sh
|
106
106
|
cfn-vpn init simple-ad --server-cn [server certificate name] \
|
107
|
-
--subnet-ids [list of
|
108
|
-
--directory-id [aws
|
107
|
+
--subnet-ids [list of subnets to associate with the vpn] \
|
108
|
+
--directory-id [aws directory service id]
|
109
109
|
```
|
110
110
|
|
111
111
|
The default authorization rule for the associated subnets allows all. You can optionally change this by using the `--default-groups` flag to set groups on the default authorization rule. The group Id is the Active Directory Group ID or SID.
|
112
112
|
|
113
113
|
```sh
|
114
114
|
cfn-vpn init simple-ad --server-cn [server certificate name] \
|
115
|
-
--subnet-ids [list of
|
116
|
-
--directory-id [aws
|
115
|
+
--subnet-ids [list of subnets to associate with the vpn] \
|
116
|
+
--directory-id [aws directory service id] \
|
117
117
|
--default-groups [list of group ids]
|
118
118
|
```
|
119
119
|
|
@@ -128,27 +128,30 @@ When using a federated ClientVPN you can modify the default auth to only allow s
|
|
128
128
|
|
129
129
|
```
|
130
130
|
Options:
|
131
|
-
r, [--region=REGION]
|
132
|
-
|
133
|
-
[--verbose], [--no-verbose]
|
134
|
-
--server-cn=SERVER_CN
|
135
|
-
[--client-cn=CLIENT_CN]
|
136
|
-
[--easyrsa-local], [--no-easyrsa-local]
|
137
|
-
[--bucket=BUCKET]
|
138
|
-
--subnet-ids=one two three
|
139
|
-
[--default-groups=one two three]
|
140
|
-
[--cidr=CIDR]
|
141
|
-
|
142
|
-
[--dns-servers=one two three]
|
143
|
-
[--split-tunnel], [--no-split-tunnel]
|
144
|
-
|
145
|
-
[--internet-route=INTERNET_ROUTE]
|
146
|
-
[--protocol=PROTOCOL]
|
147
|
-
|
148
|
-
|
149
|
-
[--start=START]
|
150
|
-
[--stop=STOP]
|
151
|
-
[--saml-arn=SAML_ARN]
|
152
|
-
[--saml-self-service-arn=SAML_SELF_SERVICE_ARN]
|
153
|
-
[--directory-id=DIRECTORY_ID]
|
131
|
+
r, [--region=REGION] # AWS Region
|
132
|
+
# Default: ap-southeast-2
|
133
|
+
[--verbose], [--no-verbose] # set log level to debug
|
134
|
+
--server-cn=SERVER_CN # server certificate common name
|
135
|
+
[--client-cn=CLIENT_CN] # client certificate common name
|
136
|
+
[--easyrsa-local], [--no-easyrsa-local] # run the easyrsa executable from your local rather than from docker
|
137
|
+
[--bucket=BUCKET] # s3 bucket, if not set one will be generated for you
|
138
|
+
--subnet-ids=one two three # subnet id to associate your vpn with
|
139
|
+
[--default-groups=one two three] # groups to allow through the subnet associations when using federated auth
|
140
|
+
[--cidr=CIDR] # cidr from which to assign client IP addresses
|
141
|
+
# Default: 10.250.0.0/16
|
142
|
+
[--dns-servers=one two three] # DNS Servers to push to clients.
|
143
|
+
[--split-tunnel], [--no-split-tunnel] # only push routes to the client on the vpn endpoint
|
144
|
+
# Default: true
|
145
|
+
[--internet-route=INTERNET_ROUTE] # [subnet-id] create a default route to the internet through a subnet
|
146
|
+
[--protocol=PROTOCOL] # set the protocol for the vpn connections
|
147
|
+
# Default: udp
|
148
|
+
# Possible values: udp, tcp
|
149
|
+
[--start=START] # cloudwatch event cron schedule in UTC to associate subnets to the client vpn
|
150
|
+
[--stop=STOP] # cloudwatch event cron schedule in UTC to disassociate subnets to the client vpn
|
151
|
+
[--saml-arn=SAML_ARN] # IAM SAML identity provider arn if using SAML federated authentication
|
152
|
+
[--saml-self-service-arn=SAML_SELF_SERVICE_ARN] # IAM SAML identity provider arn for the self service portal
|
153
|
+
[--directory-id=DIRECTORY_ID] # AWS Directory Service directory id if using Active Directory authentication
|
154
|
+
[--slack-webhook-url=SLACK_WEBHOOK_URL] # slack webhook url to send notifications from the scheduler and route populator
|
155
|
+
[--auto-limit-increase], [--no-auto-limit-increase] # automatically request a AWS service quota increase if limits are hit for route entry and authorization rule limits
|
156
|
+
# Default: true
|
154
157
|
```
|
data/docs/routes.md
CHANGED
@@ -96,3 +96,51 @@ run the `modify` command and supply the yaml file to apply the changes
|
|
96
96
|
```sh
|
97
97
|
cfn-vpn routes [name] --params-yaml cfnvpn.[name].yaml
|
98
98
|
```
|
99
|
+
|
100
|
+
## Route Limits
|
101
|
+
|
102
|
+
Client VPN have a number of service limits associated with it some of which can be increased and may need to be increased by default.
|
103
|
+
|
104
|
+
| Name | Default | Adjustable |
|
105
|
+
| --- | --- | --- |
|
106
|
+
| Authorization rules per Client VPN endpoint | 50 | [Yes](https://console.aws.amazon.com/servicequotas/home/services/ec2/quotas/L-9A1BC94B) |
|
107
|
+
| Client VPN disconnect timeout | 24 hours | No |
|
108
|
+
| Client VPN endpoints per Region | 5 | [Yes](https://console.aws.amazon.com/servicequotas/home/services/ec2/quotas/L-8EA77D34) |
|
109
|
+
| Concurrent client connections per Client VPN endpoint | This value depends on the number of subnet associations per endpoint\. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/vpn/latest/clientvpn-admin/limits.html) | [Yes](https://console.aws.amazon.com/servicequotas/home/services/ec2/quotas/L-C4B238BF) |
|
110
|
+
| Concurrent operations per Client VPN endpoint † | 10 | No |
|
111
|
+
| Entries in a client certificate revocation list for Client VPN endpoints | 20,000 | No |
|
112
|
+
| Routes per Client VPN endpoint | 10 | [Yes](https://console.aws.amazon.com/servicequotas/home/services/ec2/quotas/L-401D78F7) |
|
113
|
+
|
114
|
+
† Operations include:
|
115
|
+
+ Associate or disassociate subnets
|
116
|
+
+ Create or delete routes
|
117
|
+
+ Create or delete inbound and outbound rules
|
118
|
+
+ Create or delete security groups
|
119
|
+
|
120
|
+
Check out the AWS [docs](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/limits.html) for up to date details
|
121
|
+
|
122
|
+
### Increasing Limits
|
123
|
+
|
124
|
+
**Automatic**
|
125
|
+
|
126
|
+
cfn-vpn supports automatically creating requests to increase the limits for `Routes per Client VPN endpoint` (by 10) and `Authorization rules per Client VPN endpoint` (by 20).
|
127
|
+
|
128
|
+
This functionality is enabled by default but can be disabled by modifying the vpn setting the `--no-auto-limit-increase` flag
|
129
|
+
|
130
|
+
```sh
|
131
|
+
cfn-vpn modify [name] --no-auto-limit-increase
|
132
|
+
```
|
133
|
+
|
134
|
+
**Manual**
|
135
|
+
|
136
|
+
`Routes per Client VPN endpoint`
|
137
|
+
|
138
|
+
```sh
|
139
|
+
aws service-quotas request-service-quota-increase --service-code ec2 --quota-code L-401D78F7 --desired-value [value]
|
140
|
+
```
|
141
|
+
|
142
|
+
`Authorization rules per Client VPN endpoint`
|
143
|
+
|
144
|
+
```sh
|
145
|
+
aws service-quotas request-service-quota-increase --service-code ec2 --quota-code L-9A1BC94B --desired-value [value]
|
146
|
+
```
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Slack Notifications
|
2
|
+
|
3
|
+
Slack notifications can be enabled for both the [dynamic route populator](routes.md#dynamic-dns-routes) and the [scheduler](scheduling.md) to show events.
|
4
|
+
|
5
|
+
## Enable
|
6
|
+
|
7
|
+
Setup a Slack [incoming-webhook](https://api.slack.com/messaging/webhooks#getting_started) in your desired slack channel and grab the webhook url that'll look something like this:
|
8
|
+
|
9
|
+
```
|
10
|
+
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
|
11
|
+
```
|
12
|
+
|
13
|
+
Next modify your VPN stack using the modify command and pass in url
|
14
|
+
|
15
|
+
```sh
|
16
|
+
cfn-vpn modify [name] --slack-webhook-url "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
|
17
|
+
```
|
18
|
+
|
19
|
+
## Route Events
|
20
|
+
|
21
|
+
- `FAILED`: general failure
|
22
|
+
- `NEW_ROUTE`: new route added to route table
|
23
|
+
- `EXPIRED_ROUTE`: CIDR is no longer associated with DNS entry and is removed from the route table
|
24
|
+
- `ROUTE_LIMIT_EXCEEDED`: no new routes can be added to the route table due to AWS route table limit
|
25
|
+
- `AUTH_RULE_LIMIT_EXCEEDED`: no new authorization rules can be added to the rule list due to AWS auth rule limit
|
26
|
+
- `RESOLVE_FAILED`: failed to resolve the provided dns entry
|
27
|
+
- `SUBNET_NOT_ASSOCIATED`: no subnets are associated with the Client VPN
|
28
|
+
- `QUOTA_INCREASE_REQUEST`: automatic quota increase made
|
29
|
+
|
30
|
+
## Scheduler Events
|
31
|
+
|
32
|
+
- `START_IN_PROGRESS`: associating subnets with the Client VPN
|
33
|
+
- `STOP_IN_PROGRESS`: disassociating subnets with the Client VPN
|
34
|
+
- `START_FAILED`: failed to associated subnets with the Client VPN
|
35
|
+
- `STOP_FAILED`: failed to disassociated subnets with the Client VPN
|
@@ -50,11 +50,10 @@ module CfnVpn::Actions
|
|
50
50
|
|
51
51
|
def download_config
|
52
52
|
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
53
|
-
|
54
|
-
|
55
|
-
@config = vpn.get_config(@endpoint_id)
|
53
|
+
CfnVpn::Log.logger.debug "downloading client config for #{vpn.endpoint_id}"
|
54
|
+
@config = vpn.get_config()
|
56
55
|
string = (0...8).map { (65 + rand(26)).chr.downcase }.join
|
57
|
-
@config.sub!(
|
56
|
+
@config.sub!(vpn.endpoint_id, "#{string}.#{vpn.endpoint_id}")
|
58
57
|
end
|
59
58
|
|
60
59
|
def add_routes
|
data/lib/cfnvpn/actions/init.rb
CHANGED
@@ -35,10 +35,13 @@ module CfnVpn::Actions
|
|
35
35
|
class_option :start, type: :string, desc: 'cloudwatch event cron schedule in UTC to associate subnets to the client vpn'
|
36
36
|
class_option :stop, type: :string, desc: 'cloudwatch event cron schedule in UTC to disassociate subnets to the client vpn'
|
37
37
|
|
38
|
-
class_option :saml_arn, desc: 'IAM SAML
|
39
|
-
class_option :saml_self_service_arn, desc: 'IAM SAML
|
38
|
+
class_option :saml_arn, desc: 'IAM SAML identity provider arn if using SAML federated authentication'
|
39
|
+
class_option :saml_self_service_arn, desc: 'IAM SAML identity provider arn for the self service portal'
|
40
40
|
class_option :directory_id, desc: 'AWS Directory Service directory id if using Active Directory authentication'
|
41
41
|
|
42
|
+
class_option :slack_webhook_url, type: :string, desc: 'slack webhook url to send notifications from the scheduler and route populator'
|
43
|
+
class_option :auto_limit_increase, type: :boolean, default: true, desc: 'automatically request a AWS service quota increase if limits are hit for route entry and authorization rule limits'
|
44
|
+
|
42
45
|
def self.source_root
|
43
46
|
File.dirname(__FILE__)
|
44
47
|
end
|
@@ -67,6 +70,8 @@ module CfnVpn::Actions
|
|
67
70
|
saml_arn: @options['saml_arn'],
|
68
71
|
saml_self_service_arn: @options['saml_self_service_arn'],
|
69
72
|
directory_id: @options['directory_id'],
|
73
|
+
slack_webhook_url: @options['slack_webhook_url'],
|
74
|
+
auto_limit_increase: @options['auto_limit_increase'],
|
70
75
|
routes: []
|
71
76
|
}
|
72
77
|
end
|
@@ -138,8 +143,7 @@ module CfnVpn::Actions
|
|
138
143
|
|
139
144
|
def finish
|
140
145
|
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
141
|
-
|
142
|
-
CfnVpn::Log.logger.info "Client VPN #{@endpoint_id} created. Run `cfn-vpn config #{@name}` to setup the client config"
|
146
|
+
CfnVpn::Log.logger.info "Client VPN #{vpn.endpoint_id} created. Run `cfn-vpn config #{@name}` to setup the client config"
|
143
147
|
end
|
144
148
|
|
145
149
|
end
|
@@ -37,6 +37,9 @@ module CfnVpn::Actions
|
|
37
37
|
class_option :start, type: :string, desc: 'cloudwatch event cron schedule in UTC to associate subnets to the client vpn'
|
38
38
|
class_option :stop, type: :string, desc: 'cloudwatch event cron schedule in UTC to disassociate subnets to the client vpn'
|
39
39
|
|
40
|
+
class_option :slack_webhook_url, type: :string, desc: 'slack webhook url to send notifications from the scheduler and route populator'
|
41
|
+
class_option :auto_limit_increase, type: :boolean, desc: 'automatically request a AWS service quota increase if limits are hit for route entry and authorization rule limits'
|
42
|
+
|
40
43
|
class_option :param_yaml, type: :string, desc: 'pass in cfnvpn params through YAML file'
|
41
44
|
|
42
45
|
class_option :bucket, desc: 's3 bucket'
|
@@ -161,8 +164,7 @@ module CfnVpn::Actions
|
|
161
164
|
|
162
165
|
def finish
|
163
166
|
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
164
|
-
|
165
|
-
CfnVpn::Log.logger.info "Client VPN #{@endpoint_id} modified."
|
167
|
+
CfnVpn::Log.logger.info "Client VPN #{vpn.endpoint_id} modified."
|
166
168
|
end
|
167
169
|
|
168
170
|
end
|
@@ -42,9 +42,8 @@ module CfnVpn::Actions
|
|
42
42
|
|
43
43
|
def apply_rekocation_list
|
44
44
|
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
45
|
-
|
46
|
-
|
47
|
-
CfnVpn::Log.logger.info("revoked client #{@options['client_cn']} from #{endpoint_id}")
|
45
|
+
vpn.put_revoke_list("#{@cert_dir}/crl.pem")
|
46
|
+
CfnVpn::Log.logger.info("revoked client #{@options['client_cn']} from #{vpn.endpoint_id}")
|
48
47
|
end
|
49
48
|
|
50
49
|
end
|
@@ -14,7 +14,7 @@ module CfnVpn::Actions
|
|
14
14
|
|
15
15
|
class_option :cidr, desc: 'cidr range'
|
16
16
|
class_option :dns, desc: 'dns record to auto lookup ip'
|
17
|
-
class_option :
|
17
|
+
class_option :subnets, type: :array, desc: 'target vpc subnets to route through, if none is supplied the default subnets are used'
|
18
18
|
class_option :desc, desc: 'description of the route'
|
19
19
|
|
20
20
|
class_option :groups, type: :array, desc: 'override all authorised groups on thr route'
|
@@ -83,15 +83,15 @@ module CfnVpn::Actions
|
|
83
83
|
CfnVpn::Log.logger.warn "description for this route cannot be updated in place. To alter delete the route and add with the new description"
|
84
84
|
end
|
85
85
|
|
86
|
-
if @options[:
|
87
|
-
CfnVpn::Log.logger.warn "the target
|
86
|
+
if @options[:subnets]
|
87
|
+
CfnVpn::Log.logger.warn "the target subnets for this route cannot be updated in place. To alter delete the route and add with the new target subnet"
|
88
88
|
end
|
89
89
|
elsif !@route && @options[:cidr]
|
90
90
|
CfnVpn::Log.logger.info "adding new route for #{@options[:cidr]}"
|
91
91
|
@config[:routes] << {
|
92
92
|
cidr: @options[:cidr],
|
93
93
|
desc: @options.fetch(:desc, ""),
|
94
|
-
|
94
|
+
subnets: @options.fetch(:subnets, @config[:subnet_ids]),
|
95
95
|
groups: @options.fetch(:groups, []) + @options.fetch(:add_groups, [])
|
96
96
|
}
|
97
97
|
elsif !@route && @options[:dns]
|
@@ -99,7 +99,7 @@ module CfnVpn::Actions
|
|
99
99
|
@config[:routes] << {
|
100
100
|
dns: @options[:dns],
|
101
101
|
desc: @options.fetch(:desc, ""),
|
102
|
-
|
102
|
+
subnets: @options.fetch(:subnets, @config[:subnet_ids]),
|
103
103
|
groups: @options.fetch(:groups, []) + @options.fetch(:add_groups, [])
|
104
104
|
}
|
105
105
|
else
|
@@ -163,27 +163,31 @@ module CfnVpn::Actions
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
+
def get_routes
|
167
|
+
@vpn = CfnVpn::ClientVpn.new(@name, @options['region'])
|
168
|
+
end
|
169
|
+
|
166
170
|
def cleanup_dns_routes
|
167
|
-
@vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
168
171
|
unless @dns_route_cleanup.nil?
|
169
|
-
routes = @vpn.get_routes()
|
170
172
|
CfnVpn::Log.logger.info("Cleaning up expired routes for #{@dns_route_cleanup}")
|
171
|
-
expired_routes =
|
173
|
+
expired_routes = @vpn.get_routes(@dns_route_cleanup)
|
172
174
|
expired_routes.each do |route|
|
175
|
+
CfnVpn::Log.logger.info("Removing expired route #{route.destination_cidr} for target subnet #{route.target_subnet}")
|
173
176
|
@vpn.delete_route(route.destination_cidr, route.target_subnet)
|
174
|
-
@vpn.revoke_auth(route.destination_cidr)
|
175
177
|
end
|
176
|
-
end
|
177
|
-
end
|
178
178
|
|
179
|
-
|
180
|
-
|
181
|
-
|
179
|
+
expired_rules = @vpn.get_auth_rules(@dns_route_cleanup)
|
180
|
+
expired_rules.each do |rule|
|
181
|
+
CfnVpn::Log.logger.info("Removing expired auth rule for route #{route.destination_cidr}")
|
182
|
+
@vpn.revoke_auth(rule.destination_cidr)
|
183
|
+
end
|
184
|
+
end
|
182
185
|
end
|
183
186
|
|
184
187
|
def display_routes
|
185
|
-
|
186
|
-
|
188
|
+
routes = @vpn.get_routes()
|
189
|
+
rows = routes.collect do |s|
|
190
|
+
groups = @vpn.get_groups_for_route(s.destination_cidr)
|
187
191
|
[ s.destination_cidr, s.description, s.status.code, s.target_subnet, s.type, s.origin, (!groups.join("").empty? ? groups.join(' ') : 'AllowAll') ]
|
188
192
|
end
|
189
193
|
table = Terminal::Table.new(
|
@@ -29,20 +29,19 @@ module CfnVpn::Actions
|
|
29
29
|
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def setup
|
33
33
|
@vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
34
|
-
@endpoint_id = @vpn.get_endpoint_id()
|
35
34
|
end
|
36
35
|
|
37
36
|
def kill_session
|
38
37
|
if !@options['kill'].nil?
|
39
|
-
sessions = @vpn.get_sessions(
|
38
|
+
sessions = @vpn.get_sessions()
|
40
39
|
session = sessions.select { |s| s if s.connection_id == @options['kill'] }.first
|
41
40
|
if session.any? && session.status.code == "active"
|
42
41
|
terminate = yes? "Terminate connection #{@options['kill']} for #{session.common_name}?", :yellow
|
43
42
|
if terminate
|
44
43
|
CfnVpn::Log.logger.info "Terminating connection #{@options['kill']} for #{session.common_name}"
|
45
|
-
@vpn.kill_session(@
|
44
|
+
@vpn.kill_session(@options['kill'])
|
46
45
|
end
|
47
46
|
else
|
48
47
|
CfnVpn::Log.logger.error "Connection id #{@options['kill']} doesn't exist or is not active"
|
@@ -51,7 +50,7 @@ module CfnVpn::Actions
|
|
51
50
|
end
|
52
51
|
|
53
52
|
def display_sessions
|
54
|
-
sessions = @vpn.get_sessions(
|
53
|
+
sessions = @vpn.get_sessions()
|
55
54
|
rows = sessions.collect do |s|
|
56
55
|
[ s.common_name, s.connection_established_time, s.status.code, s.client_ip, s.connection_id, s.ingress_bytes, s.egress_bytes ]
|
57
56
|
end
|
data/lib/cfnvpn/actions/share.rb
CHANGED
@@ -26,11 +26,10 @@ module CfnVpn::Actions
|
|
26
26
|
|
27
27
|
def copy_config_to_s3
|
28
28
|
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
29
|
-
|
30
|
-
|
31
|
-
@config = vpn.get_config(@endpoint_id)
|
29
|
+
CfnVpn::Log.logger.debug "downloading client config for #{vpn.endpoint_id}"
|
30
|
+
@config = vpn.get_config()
|
32
31
|
string = (0...8).map { (65 + rand(26)).chr.downcase }.join
|
33
|
-
@config.sub!(
|
32
|
+
@config.sub!(vpn.endpoint_id, "#{string}.#{vpn.endpoint_id}")
|
34
33
|
end
|
35
34
|
|
36
35
|
def add_routes
|
@@ -61,13 +61,9 @@ module CfnVpn::Actions
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
def get_endpoint
|
65
|
-
@vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
66
|
-
@endpoint_id = @vpn.get_endpoint_id()
|
67
|
-
end
|
68
|
-
|
69
64
|
def associations
|
70
|
-
|
65
|
+
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
66
|
+
associations = vpn.get_associations()
|
71
67
|
table = Terminal::Table.new(
|
72
68
|
:headings => ['ID', 'Subnet', 'Status', 'CIDR', 'AZ', 'Groups'],
|
73
69
|
:rows => associations.map {|ass| ass.values})
|
data/lib/cfnvpn/clientvpn.rb
CHANGED
@@ -5,6 +5,7 @@ require 'netaddr'
|
|
5
5
|
module CfnVpn
|
6
6
|
class ClientVpn
|
7
7
|
|
8
|
+
attr_reader :endpoint_id
|
8
9
|
|
9
10
|
def initialize(name,region)
|
10
11
|
@client = Aws::EC2::Client.new(region: region)
|
@@ -31,56 +32,71 @@ module CfnVpn
|
|
31
32
|
return get_endpoint().dns_servers
|
32
33
|
end
|
33
34
|
|
34
|
-
def get_config(
|
35
|
+
def get_config()
|
35
36
|
resp = @client.export_client_vpn_client_configuration({
|
36
|
-
client_vpn_endpoint_id: endpoint_id
|
37
|
+
client_vpn_endpoint_id: @endpoint_id
|
37
38
|
})
|
38
39
|
return resp.client_configuration
|
39
40
|
end
|
40
41
|
|
41
|
-
def get_rekove_list(
|
42
|
+
def get_rekove_list()
|
42
43
|
resp = @client.export_client_vpn_client_certificate_revocation_list({
|
43
|
-
client_vpn_endpoint_id: endpoint_id
|
44
|
+
client_vpn_endpoint_id: @endpoint_id
|
44
45
|
})
|
45
46
|
return resp.certificate_revocation_list
|
46
47
|
end
|
47
48
|
|
48
|
-
def put_revoke_list(
|
49
|
+
def put_revoke_list(revoke_list)
|
49
50
|
list = File.read(revoke_list)
|
50
51
|
@client.import_client_vpn_client_certificate_revocation_list({
|
51
|
-
client_vpn_endpoint_id: endpoint_id,
|
52
|
+
client_vpn_endpoint_id: @endpoint_id,
|
52
53
|
certificate_revocation_list: list
|
53
54
|
})
|
54
55
|
end
|
55
56
|
|
56
|
-
def get_sessions(
|
57
|
+
def get_sessions()
|
57
58
|
params = {
|
58
|
-
client_vpn_endpoint_id: endpoint_id,
|
59
|
+
client_vpn_endpoint_id: @endpoint_id,
|
59
60
|
max_results: 20
|
60
61
|
}
|
61
62
|
resp = @client.describe_client_vpn_connections(params)
|
62
63
|
return resp.connections
|
63
64
|
end
|
64
65
|
|
65
|
-
def kill_session(
|
66
|
+
def kill_session(connection_id)
|
66
67
|
@client.terminate_client_vpn_connections({
|
67
|
-
client_vpn_endpoint_id: endpoint_id,
|
68
|
+
client_vpn_endpoint_id: @endpoint_id,
|
68
69
|
connection_id: connection_id
|
69
70
|
})
|
70
71
|
end
|
71
72
|
|
72
|
-
def get_routes()
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
def get_routes(dns_route=nil)
|
74
|
+
routes = []
|
75
|
+
@client.describe_client_vpn_routes({client_vpn_endpoint_id: @endpoint_id}).each do |resp|
|
76
|
+
if dns_route
|
77
|
+
routes.concat resp.routes.select {|route| route.description.include?(dns_route) }
|
78
|
+
else
|
79
|
+
routes.concat resp.routes
|
80
|
+
end
|
81
|
+
end
|
82
|
+
return routes
|
79
83
|
end
|
80
84
|
|
81
|
-
def
|
85
|
+
def get_auth_rules(dns_route=nil)
|
86
|
+
rules = []
|
87
|
+
@client.describe_client_vpn_authorization_rules({client_vpn_endpoint_id: @endpoint_id}) do |resp|
|
88
|
+
if dns_route
|
89
|
+
rules.concat resp.authorization_rules.select {|rule| rule.description.include?(dns_route) }
|
90
|
+
else
|
91
|
+
rules.concat resp.routes
|
92
|
+
end
|
93
|
+
end
|
94
|
+
return rules
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_groups_for_route(cidr)
|
82
98
|
auth_resp = @client.describe_client_vpn_authorization_rules({
|
83
|
-
client_vpn_endpoint_id:
|
99
|
+
client_vpn_endpoint_id: @endpoint_id,
|
84
100
|
filters: [
|
85
101
|
{
|
86
102
|
name: 'destination-cidr',
|
@@ -91,10 +107,10 @@ module CfnVpn
|
|
91
107
|
return auth_resp.authorization_rules.map {|rule| rule.group_id }
|
92
108
|
end
|
93
109
|
|
94
|
-
def get_associations(
|
110
|
+
def get_associations()
|
95
111
|
associations = []
|
96
112
|
resp = @client.describe_client_vpn_target_networks({
|
97
|
-
client_vpn_endpoint_id:
|
113
|
+
client_vpn_endpoint_id: @endpoint_id
|
98
114
|
})
|
99
115
|
|
100
116
|
resp.client_vpn_target_networks.each do |net|
|
@@ -102,7 +118,7 @@ module CfnVpn
|
|
102
118
|
subnet_ids: [net.target_network_id]
|
103
119
|
})
|
104
120
|
subnet = subnet_resp.subnets.first
|
105
|
-
groups = get_groups_for_route(
|
121
|
+
groups = get_groups_for_route(subnet.cidr_block)
|
106
122
|
|
107
123
|
associations.push({
|
108
124
|
association_id: net.association_id,
|