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 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