cfn-vpn 0.1.0 → 0.2.0
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/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
|