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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e3b6334f24037b79137a09d3d93325a2513162f4e151b1e565875e74352aac7
4
- data.tar.gz: d0e7e304876a4bcccab2b082fc8c298f8fc74b0769b4eb9338fdc98b5d5842a1
3
+ metadata.gz: 14100a22fc434fa08bc329c9b37b3fd8c72a8b03825c0ae2ebbb8b008229711b
4
+ data.tar.gz: 72a211b53647c788bc149bca7c5c30d1f7ad6939f7c26573da4d483068fe2008
5
5
  SHA512:
6
- metadata.gz: c75ae0f97eb239c6db309b98d09d5b08a688bde621aa5f23b091face28fab3737369d67d6d40c9f13e7615ba8f58c4ee3553fe24a55715ac0282f889b72946fd
7
- data.tar.gz: d543e66f8ce62534e64de754d09be061c4a92b50bff6d8ddfbd0f8df03a48f830217c501024986e8810e4f2a300fa503a9631efb7ad0cb4a22c6c47019456df6
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]', 'Ciinabox configuration initialization'
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::Config, 'config', 'config [name]', 'Ciinabox configuration initialization'
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
- @client.wait_until :change_set_create_complete, change_set_name: change_set_id
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 #{@config_dir}/#{@name}.crt")
67
- @config.concat("\nkey #{@config_dir}/#{@name}.key\n")
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['subnet_id'] = @options['subnet_id']
44
- @config['cidr'] = @options['cidr']
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['server_cert_arn'] = cert.upload_certificates(@options['region'],'server','server',@options['server_cn'])
66
- @config['client_cert_arn'] = cert.upload_certificates(@options['region'],@client_cn,'client')
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', '<%= @name %>'
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: 'AssociationSubnetId', value: '<%= @config['subnet_id'] %>'
9
- parameter name: 'ClientCidrBlock', value: '<%= @config['cidr'] %>'
10
- parameter name: 'ClientCertificateArn', value: '<%= @config['client_cert_arn'] %>'
11
- parameter name: 'ServerCertificateArn', value: '<%= @config['server_cert_arn'] %>'
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
@@ -1,4 +1,4 @@
1
1
  module CfnVpn
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  CHANGE_SET_VERSION = VERSION.gsub('.', '-').freeze
4
4
  end
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.1.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-21 00:00:00.000000000 Z
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