cfn-vpn 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/cfnvpn.rb +6 -2
- data/lib/cfnvpn/cloudformation.rb +41 -3
- data/lib/cfnvpn/config.rb +5 -27
- data/lib/cfnvpn/init.rb +11 -8
- data/lib/cfnvpn/modify.rb +95 -0
- data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +13 -6
- data/lib/cfnvpn/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14100a22fc434fa08bc329c9b37b3fd8c72a8b03825c0ae2ebbb8b008229711b
|
4
|
+
data.tar.gz: 72a211b53647c788bc149bca7c5c30d1f7ad6939f7c26573da4d483068fe2008
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23f99dfeda3e9508f75b3fd8af5aa2a16f9062d96ba4a6a1c12b8cde8517c42c9a76e8b99e20c790972529870c588ef9c966b23d30b7f587697c2315355eabe2
|
7
|
+
data.tar.gz: 86b27e631221e973769d2b61f98637a90e63b4c9fd4a463a540b0ee843c412bd66f3953fdb52cf96d488b4cf2c4ec60478936d978e606e1dd23413c3cc0a8f90
|
data/lib/cfnvpn.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'cfnvpn/version'
|
3
3
|
require 'cfnvpn/init'
|
4
|
+
require 'cfnvpn/modify'
|
4
5
|
require 'cfnvpn/config'
|
5
6
|
|
6
7
|
module CfnVpn
|
@@ -13,10 +14,13 @@ module CfnVpn
|
|
13
14
|
end
|
14
15
|
|
15
16
|
# Initializes ciinabox configuration
|
16
|
-
register CfnVpn::Init, 'init', 'init [name]', '
|
17
|
+
register CfnVpn::Init, 'init', 'init [name]', 'Create a AWS Client VPN'
|
17
18
|
tasks["init"].options = CfnVpn::Init.class_options
|
18
19
|
|
19
|
-
register CfnVpn::
|
20
|
+
register CfnVpn::Modify, 'modify', 'modify [name]', 'Modify your AWS Client VPN'
|
21
|
+
tasks["modify"].options = CfnVpn::Modify.class_options
|
22
|
+
|
23
|
+
register CfnVpn::Config, 'config', 'config [name]', 'Retrieve the config for the AWS Client VPN'
|
20
24
|
tasks["config"].options = CfnVpn::Config.class_options
|
21
25
|
|
22
26
|
end
|
@@ -29,14 +29,29 @@ module CfnVpn
|
|
29
29
|
return does_cf_stack_exist() ? 'UPDATE' : 'CREATE'
|
30
30
|
end
|
31
31
|
|
32
|
-
def create_change_set(template_path)
|
33
|
-
change_set_name = "#{@stack_name}-#{CfnVpn::CHANGE_SET_VERSION}"
|
32
|
+
def create_change_set(template_path,parameters)
|
33
|
+
change_set_name = "#{@stack_name}-#{CfnVpn::CHANGE_SET_VERSION}-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
|
34
34
|
change_set_type = get_change_set_type()
|
35
|
+
|
36
|
+
if change_set_type == 'CREATE'
|
37
|
+
params = get_parameters_from_template(template_path)
|
38
|
+
else
|
39
|
+
params = get_parameters_from_stack()
|
40
|
+
end
|
41
|
+
|
42
|
+
params.each do |param|
|
43
|
+
if !parameters[param[:parameter_key]].nil?
|
44
|
+
param['parameter_value'] = parameters[param[:parameter_key]]
|
45
|
+
param['use_previous_value'] = false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
35
49
|
template_body = File.read(template_path)
|
36
50
|
Log.logger.debug "Creating changeset"
|
37
51
|
change_set = @client.create_change_set({
|
38
52
|
stack_name: @stack_name,
|
39
53
|
template_body: template_body,
|
54
|
+
parameters: params,
|
40
55
|
tags: [
|
41
56
|
{
|
42
57
|
key: "cfnvpn:version",
|
@@ -55,7 +70,19 @@ module CfnVpn
|
|
55
70
|
|
56
71
|
def wait_for_changeset(change_set_id)
|
57
72
|
Log.logger.debug "Waiting for changeset to be created"
|
58
|
-
|
73
|
+
begin
|
74
|
+
@client.wait_until :change_set_create_complete, change_set_name: change_set_id
|
75
|
+
rescue Aws::Waiters::Errors::FailureStateError => e
|
76
|
+
change_set = get_change_set(change_set_id)
|
77
|
+
Log.logger.error("change set status: #{change_set.status} reason: #{change_set.status_reason}")
|
78
|
+
exit 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def get_change_set(change_set_id)
|
83
|
+
@client.describe_change_set({
|
84
|
+
change_set_name: change_set_id,
|
85
|
+
})
|
59
86
|
end
|
60
87
|
|
61
88
|
def execute_change_set(change_set_id)
|
@@ -71,5 +98,16 @@ module CfnVpn
|
|
71
98
|
resp = @client.wait_until waiter, stack_name: @stack_name
|
72
99
|
end
|
73
100
|
|
101
|
+
def get_parameters_from_stack()
|
102
|
+
resp = @client.get_template_summary({ stack_name: @stack_name })
|
103
|
+
return resp.parameters.collect { |p| { parameter_key: p.parameter_key, use_previous_value: true } }
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_parameters_from_template(template_path)
|
107
|
+
template_body = File.read(template_path)
|
108
|
+
resp = @client.get_template_summary({ template_body: template_body })
|
109
|
+
return resp.parameters.collect { |p| { parameter_key: p.parameter_key, parameter_value: p.default_value } }
|
110
|
+
end
|
111
|
+
|
74
112
|
end
|
75
113
|
end
|
data/lib/cfnvpn/config.rb
CHANGED
@@ -11,9 +11,11 @@ module CfnVpn
|
|
11
11
|
|
12
12
|
class_option :profile, desc: 'AWS Profile'
|
13
13
|
class_option :region, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
14
|
-
class_option :force, default: false, type: :boolean, desc: 'AWS Region'
|
15
14
|
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
16
15
|
|
16
|
+
class_option :key_path, required: true, desc: 'full file path to the client vpn key'
|
17
|
+
class_option :crt_path, required: true, desc: 'full file path to the client vpn certificate'
|
18
|
+
|
17
19
|
def self.source_root
|
18
20
|
File.dirname(__FILE__)
|
19
21
|
end
|
@@ -36,35 +38,11 @@ module CfnVpn
|
|
36
38
|
@config = vpn.get_config(@endpoint_id)
|
37
39
|
end
|
38
40
|
|
39
|
-
def download_certificate
|
40
|
-
ssm = CfnVpn::SSM.new(@name,@options['region'],@home_dir)
|
41
|
-
cert_body = ssm.get_parameter("#{@name}.crt")
|
42
|
-
if cert_body
|
43
|
-
cert = CfnVpn::Certificates.new(@home_dir,@name)
|
44
|
-
cert.write_certificate(cert_body,"#{@name}.crt",@options['force'])
|
45
|
-
Log.logger.info "downloaded client certificate #{@name}.crt"
|
46
|
-
else
|
47
|
-
Log.logger.error "unable to find client certificate #{@name}.crt"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def download_key
|
52
|
-
ssm = CfnVpn::SSM.new(@name,@options['region'],@home_dir)
|
53
|
-
cert_body = ssm.get_parameter("#{@name}.key")
|
54
|
-
if cert_body
|
55
|
-
cert = CfnVpn::Certificates.new(@home_dir,@name)
|
56
|
-
cert.write_certificate(cert_body,"#{@name}.key",@options['force'])
|
57
|
-
Log.logger.info "downloaded client key #{@name}.key"
|
58
|
-
else
|
59
|
-
Log.logger.error "unable to find client certificate #{@name}.crt"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
41
|
def alter_config
|
64
42
|
string = (0...8).map { (65 + rand(26)).chr.downcase }.join
|
65
43
|
@config.sub!(@endpoint_id, "#{string}.#{@endpoint_id}")
|
66
|
-
@config.concat("\n\ncert #{@
|
67
|
-
@config.concat("\nkey #{@
|
44
|
+
@config.concat("\n\ncert #{@options['crt_path']}")
|
45
|
+
@config.concat("\nkey #{@options['key_path']}\n")
|
68
46
|
end
|
69
47
|
|
70
48
|
def write_config
|
data/lib/cfnvpn/init.rb
CHANGED
@@ -23,6 +23,7 @@ module CfnVpn
|
|
23
23
|
|
24
24
|
class_option :subnet_id, required: true, desc: 'subnet id to associate your vpn with'
|
25
25
|
class_option :cidr, default: '10.250.0.0/16', desc: 'cidr from which to assign client IP addresses'
|
26
|
+
class_option :dns_servers, desc: 'DNS Servers to push to clients.'
|
26
27
|
|
27
28
|
def self.source_root
|
28
29
|
File.dirname(__FILE__)
|
@@ -40,8 +41,12 @@ module CfnVpn
|
|
40
41
|
|
41
42
|
def initialize_config
|
42
43
|
@config = {}
|
43
|
-
@config['
|
44
|
-
@config['
|
44
|
+
@config['parameters'] = {}
|
45
|
+
@config['parameters']['EnvironmentName'] = @name
|
46
|
+
@config['parameters']['AssociationSubnetId'] = @options['subnet_id']
|
47
|
+
@config['parameters']['ClientCidrBlock'] = @options['cidr']
|
48
|
+
@config['parameters']['DnsServers'] = @options['dns_servers']
|
49
|
+
@config['template_version'] = '0.1.1'
|
45
50
|
end
|
46
51
|
|
47
52
|
def stack_exist
|
@@ -62,21 +67,19 @@ module CfnVpn
|
|
62
67
|
|
63
68
|
def upload_certificates
|
64
69
|
cert = CfnVpn::Certificates.new(@build_dir,@name)
|
65
|
-
@config['
|
66
|
-
@config['
|
67
|
-
cert.store_certificate(@options['region'],"#{@client_cn}.crt")
|
68
|
-
cert.store_certificate(@options['region'],"#{@client_cn}.key")
|
70
|
+
@config['parameters']['ServerCertificateArn'] = cert.upload_certificates(@options['region'],'server','server',@options['server_cn'])
|
71
|
+
@config['parameters']['ClientCertificateArn'] = cert.upload_certificates(@options['region'],@client_cn,'client')
|
69
72
|
end
|
70
73
|
|
71
74
|
def deploy_vpn
|
72
|
-
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config)
|
75
|
+
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config, force: true)
|
73
76
|
Log.logger.debug "Generating cloudformation from #{@build_dir}/#{@name}.cfhighlander.rb"
|
74
77
|
cfhl = CfnVpn::CfHiglander.new(@options['region'],@name,@config,@build_dir)
|
75
78
|
template_path = cfhl.render()
|
76
79
|
Log.logger.debug "Cloudformation template #{template_path} generated and validated"
|
77
80
|
Log.logger.info "Launching cloudformation stack #{@name}-cfnvpn in #{@options['region']}"
|
78
81
|
cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
79
|
-
change_set, change_set_type = cfn.create_change_set(template_path)
|
82
|
+
change_set, change_set_type = cfn.create_change_set(template_path, @config['parameters'])
|
80
83
|
cfn.wait_for_changeset(change_set.id)
|
81
84
|
cfn.execute_change_set(change_set.id)
|
82
85
|
cfn.wait_for_execute(change_set_type)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfnvpn/cloudformation'
|
4
|
+
require 'cfnvpn/certificates'
|
5
|
+
require 'cfnvpn/cfhighlander'
|
6
|
+
require 'cfnvpn/cloudformation'
|
7
|
+
require 'cfnvpn/log'
|
8
|
+
require 'cfnvpn/clientvpn'
|
9
|
+
|
10
|
+
module CfnVpn
|
11
|
+
class Modify < Thor::Group
|
12
|
+
include Thor::Actions
|
13
|
+
include CfnVpn::Log
|
14
|
+
|
15
|
+
argument :name
|
16
|
+
|
17
|
+
class_option :profile, aliases: :p, desc: 'AWS Profile'
|
18
|
+
class_option :region, aliases: :r, default: ENV['AWS_REGION'], desc: 'AWS Region'
|
19
|
+
class_option :verbose, desc: 'set log level to debug', type: :boolean
|
20
|
+
|
21
|
+
class_option :subnet_id, desc: 'subnet id to associate your vpn with'
|
22
|
+
class_option :cidr, desc: 'cidr from which to assign client IP addresses'
|
23
|
+
class_option :dns_servers, desc: 'DNS Servers to push to clients.'
|
24
|
+
|
25
|
+
def self.source_root
|
26
|
+
File.dirname(__FILE__)
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_loglevel
|
30
|
+
Log.logger.level = Logger::DEBUG if @options['verbose']
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_build_directory
|
34
|
+
@build_dir = "#{ENV['HOME']}/.cfnvpn/#{@name}"
|
35
|
+
Log.logger.debug "creating directory #{@build_dir}"
|
36
|
+
FileUtils.mkdir_p(@build_dir)
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize_config
|
40
|
+
@config = {}
|
41
|
+
@config['parameters'] = {}
|
42
|
+
@config['parameters']['AssociationSubnetId'] = @options['subnet_id']
|
43
|
+
@config['parameters']['ClientCidrBlock'] = @options['cidr']
|
44
|
+
@config['parameters']['DnsServers'] = @options['dns_servers']
|
45
|
+
@config['template_version'] = '0.1.1'
|
46
|
+
end
|
47
|
+
|
48
|
+
def stack_exist
|
49
|
+
@cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
50
|
+
if !@cfn.does_cf_stack_exist()
|
51
|
+
Log.logger.error "#{@name}-cfnvpn stack doesn't exists in this account in region #{@options['region']}\n Try running `cfn-vpn init #{@name}` to setup the stack"
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def deploy_vpn
|
57
|
+
template('templates/cfnvpn.cfhighlander.rb.tt', "#{@build_dir}/#{@name}.cfhighlander.rb", @config, force: true)
|
58
|
+
Log.logger.debug "Generating cloudformation from #{@build_dir}/#{@name}.cfhighlander.rb"
|
59
|
+
cfhl = CfnVpn::CfHiglander.new(@options['region'],@name,@config,@build_dir)
|
60
|
+
template_path = cfhl.render()
|
61
|
+
Log.logger.debug "Cloudformation template #{template_path} generated and validated"
|
62
|
+
|
63
|
+
Log.logger.info "Modifying cloudformation stack #{@name}-cfnvpn in #{@options['region']}"
|
64
|
+
cfn = CfnVpn::Cloudformation.new(@options['region'],@name)
|
65
|
+
change_set, change_set_type = cfn.create_change_set(template_path,@config['parameters'])
|
66
|
+
cfn.wait_for_changeset(change_set.id)
|
67
|
+
changes = cfn.get_change_set(change_set.id)
|
68
|
+
|
69
|
+
Log.logger.warn("The following changes to the cfnvpn stack will be made")
|
70
|
+
changes.changes.each do |change|
|
71
|
+
Log.logger.warn("ID: #{change.resource_change.logical_resource_id} Action: #{change.resource_change.action}")
|
72
|
+
change.resource_change.details.each do |details|
|
73
|
+
Log.logger.warn("Name: #{details.target.name} Attribute: #{details.target.attribute} Cause: #{details.causing_entity}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
continue = yes? "Continue?", :green
|
78
|
+
if !continue
|
79
|
+
Log.logger.error("Cancelled cfn-vpn modifiy #{@name}")
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
|
83
|
+
cfn.execute_change_set(change_set.id)
|
84
|
+
cfn.wait_for_execute(change_set_type)
|
85
|
+
Log.logger.debug "Changeset #{change_set_type} complete"
|
86
|
+
end
|
87
|
+
|
88
|
+
def finish
|
89
|
+
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
90
|
+
@endpoint_id = vpn.get_endpoint_id()
|
91
|
+
Log.logger.info "Client VPN #{@endpoint_id} modified."
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -1,14 +1,21 @@
|
|
1
1
|
CfhighlanderTemplate do
|
2
2
|
|
3
3
|
Parameters do
|
4
|
-
ComponentParam 'EnvironmentName'
|
4
|
+
ComponentParam 'EnvironmentName'
|
5
|
+
ComponentParam 'AssociationSubnetId'
|
6
|
+
ComponentParam 'ClientCidrBlock'
|
7
|
+
ComponentParam 'ClientCertificateArn'
|
8
|
+
ComponentParam 'ServerCertificateArn'
|
9
|
+
ComponentParam 'DnsServers'
|
5
10
|
end
|
6
11
|
|
7
|
-
Component template: 'client-vpn', name: 'vpn', render: Inline do
|
8
|
-
parameter name: '
|
9
|
-
parameter name: '
|
10
|
-
parameter name: '
|
11
|
-
parameter name: '
|
12
|
+
Component template: 'client-vpn@<%= @config['template_version'] %>', name: 'vpn', render: Inline do
|
13
|
+
parameter name: 'EnvironmentName', value: Ref('EnvironmentName')
|
14
|
+
parameter name: 'AssociationSubnetId', value: Ref('AssociationSubnetId')
|
15
|
+
parameter name: 'ClientCidrBlock', value: Ref('ClientCidrBlock')
|
16
|
+
parameter name: 'ClientCertificateArn', value: Ref('ClientCertificateArn')
|
17
|
+
parameter name: 'ServerCertificateArn', value: Ref('ServerCertificateArn')
|
18
|
+
parameter name: 'DnsServers', value: Ref('DnsServers')
|
12
19
|
end
|
13
20
|
|
14
21
|
end
|
data/lib/cfnvpn/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfn-vpn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guslington
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -198,6 +198,7 @@ files:
|
|
198
198
|
- lib/cfnvpn/config.rb
|
199
199
|
- lib/cfnvpn/init.rb
|
200
200
|
- lib/cfnvpn/log.rb
|
201
|
+
- lib/cfnvpn/modify.rb
|
201
202
|
- lib/cfnvpn/ssm.rb
|
202
203
|
- lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt
|
203
204
|
- lib/cfnvpn/version.rb
|