cfn-vpn 0.4.1 → 1.1.1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build-gem.yml +25 -0
  3. data/.github/workflows/release-gem.yml +34 -0
  4. data/.github/workflows/release-image.yml +33 -0
  5. data/Dockerfile +26 -0
  6. data/Gemfile.lock +30 -38
  7. data/README.md +1 -224
  8. data/cfn-vpn.gemspec +3 -5
  9. data/docs/README.md +44 -0
  10. data/docs/certificate-users.md +89 -0
  11. data/docs/getting-started.md +99 -0
  12. data/docs/modifying.md +67 -0
  13. data/docs/routes.md +84 -0
  14. data/docs/scheduling.md +32 -0
  15. data/docs/sessions.md +27 -0
  16. data/lib/cfnvpn.rb +32 -24
  17. data/lib/cfnvpn/{client.rb → actions/client.rb} +11 -8
  18. data/lib/cfnvpn/actions/embedded.rb +110 -0
  19. data/lib/cfnvpn/actions/init.rb +130 -0
  20. data/lib/cfnvpn/actions/modify.rb +149 -0
  21. data/lib/cfnvpn/actions/params.rb +73 -0
  22. data/lib/cfnvpn/{revoke.rb → actions/revoke.rb} +10 -8
  23. data/lib/cfnvpn/actions/routes.rb +144 -0
  24. data/lib/cfnvpn/{sessions.rb → actions/sessions.rb} +7 -6
  25. data/lib/cfnvpn/{share.rb → actions/share.rb} +10 -10
  26. data/lib/cfnvpn/actions/subnets.rb +78 -0
  27. data/lib/cfnvpn/certificates.rb +70 -20
  28. data/lib/cfnvpn/clientvpn.rb +34 -68
  29. data/lib/cfnvpn/compiler.rb +23 -0
  30. data/lib/cfnvpn/config.rb +34 -77
  31. data/lib/cfnvpn/{cloudformation.rb → deployer.rb} +48 -20
  32. data/lib/cfnvpn/globals.rb +16 -0
  33. data/lib/cfnvpn/log.rb +26 -26
  34. data/lib/cfnvpn/s3.rb +13 -3
  35. data/lib/cfnvpn/string.rb +29 -0
  36. data/lib/cfnvpn/templates/helper.rb +14 -0
  37. data/lib/cfnvpn/templates/vpn.rb +344 -0
  38. data/lib/cfnvpn/version.rb +1 -1
  39. metadata +56 -41
  40. data/lib/cfnvpn/cfhighlander.rb +0 -49
  41. data/lib/cfnvpn/init.rb +0 -107
  42. data/lib/cfnvpn/modify.rb +0 -102
  43. data/lib/cfnvpn/routes.rb +0 -83
  44. data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +0 -27
@@ -1,51 +1,90 @@
1
1
  require 'fileutils'
2
+ require 'mkmf'
2
3
  require 'cfnvpn/acm'
3
4
  require 'cfnvpn/s3'
4
5
  require 'cfnvpn/log'
5
6
 
6
7
  module CfnVpn
7
8
  class Certificates
8
- include CfnVpn::Log
9
+
9
10
 
10
- def initialize(build_dir,cfnvpn_name)
11
+ def initialize(build_dir, cfnvpn_name, easyrsa_local = false)
11
12
  @cfnvpn_name = cfnvpn_name
13
+ @easyrsa_local = easyrsa_local
14
+
15
+ if @easyrsa_local
16
+ unless which('easyrsa')
17
+ raise "Unable to find `easyrsa` in your path. Check your path or remove the `--easyrsa-local` flag to run from docker"
18
+ end
19
+ end
20
+
21
+ @build_dir = build_dir
12
22
  @config_dir = "#{build_dir}/config"
13
23
  @cert_dir = "#{build_dir}/certificates"
24
+ @pki_dir = "#{build_dir}/pki"
14
25
  @docker_cmd = %w(docker run -it --rm)
15
- @easyrsa_image = "base2/aws-client-vpn"
26
+ @easyrsa_image = " base2/aws-client-vpn"
16
27
  FileUtils.mkdir_p(@cert_dir)
28
+ FileUtils.mkdir_p(@pki_dir)
17
29
  end
18
30
 
19
31
  def generate_ca(server_cn,client_cn)
20
- @docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
21
- @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
22
- @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
23
- @docker_cmd << @easyrsa_image
24
- @docker_cmd << "sh -c 'create-ca'"
25
- return `#{@docker_cmd.join(' ')}`
32
+ if @easyrsa_local
33
+ ENV["EASYRSA_REQ_CN"] = server_cn
34
+ ENV["EASYRSA_PKI"] = @pki_dir
35
+ system("easyrsa init-pki")
36
+ system("easyrsa build-ca nopass")
37
+ system("easyrsa build-server-full server nopass")
38
+ system("easyrsa build-client-full #{client_cn} nopass")
39
+ FileUtils.cp(["#{@pki_dir}/ca.crt", "#{@pki_dir}/issued/server.crt", "#{@pki_dir}/private/server.key", "#{@pki_dir}/issued/#{client_cn}.crt", "#{@pki_dir}/private/#{client_cn}.key"], @cert_dir)
40
+ system("tar czfv #{@cert_dir}/ca.tar.gz -C #{@build_dir} pki/")
41
+ else
42
+ @docker_cmd << "-e EASYRSA_REQ_CN=#{server_cn}"
43
+ @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
44
+ @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
45
+ @docker_cmd << @easyrsa_image
46
+ @docker_cmd << "sh -c 'create-ca'"
47
+ CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
48
+ end
26
49
  end
27
50
 
28
51
  def generate_client(client_cn)
29
- @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
30
- @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
31
- @docker_cmd << @easyrsa_image
32
- @docker_cmd << "sh -c 'create-client'"
33
- return `#{@docker_cmd.join(' ')}`
52
+ if @easyrsa_local
53
+ ENV["EASYRSA_PKI"] = @pki_dir
54
+ system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}")
55
+ system("easyrsa build-client-full #{client_cn} nopass")
56
+ system("tar czfv #{@cert_dir}/#{client_cn}.tar.gz -C #{@build_dir} pki/issued/#{client_cn}.crt pki/private/#{client_cn}.key pki/reqs/#{client_cn}.req")
57
+ else
58
+ @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
59
+ @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
60
+ @docker_cmd << @easyrsa_image
61
+ @docker_cmd << "sh -c 'create-client'"
62
+ CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
63
+ end
34
64
  end
35
65
 
36
66
  def revoke_client(client_cn)
37
- @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
38
- @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
39
- @docker_cmd << @easyrsa_image
40
- @docker_cmd << "sh -c 'revoke-client'"
41
- return `#{@docker_cmd.join(' ')}`
67
+ if @easyrsa_local
68
+ ENV["EASYRSA_PKI"] = @pki_dir
69
+ system("tar xzfv #{@cert_dir}/ca.tar.gz --directory #{@build_dir}")
70
+ system("tar xzfv #{@cert_dir}/#{client_cn}.tar.gz --directory #{@build_dir}")
71
+ system("easyrsa revoke #{client_cn}")
72
+ system("easyrsa gen-crl")
73
+ FileUtils.cp("#{@pki_dir}/crl.pem", @cert_dir)
74
+ else
75
+ @docker_cmd << "-e EASYRSA_CLIENT_CN=#{client_cn}"
76
+ @docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
77
+ @docker_cmd << @easyrsa_image
78
+ @docker_cmd << "sh -c 'revoke-client'"
79
+ CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
80
+ end
42
81
  end
43
82
 
44
83
  def upload_certificates(region,cert,type,cn=nil)
45
84
  cn = cn.nil? ? cert : cn
46
85
  acm = CfnVpn::Acm.new(region, @cert_dir)
47
86
  arn = acm.import_certificate("#{cert}.crt", "#{cert}.key", "ca.crt")
48
- Log.logger.debug "Uploaded #{type} certificate to ACM #{arn}"
87
+ CfnVpn::Log.logger.debug "Uploaded #{type} certificate to ACM #{arn}"
49
88
  acm.tag_certificate(arn,cn,type,@cfnvpn_name)
50
89
  return arn
51
90
  end
@@ -65,6 +104,17 @@ module CfnVpn
65
104
  `tar xzfv #{tar} -C #{@config_dir} --strip 2`
66
105
  File.delete(tar) if File.exist?(tar)
67
106
  end
107
+
108
+ def which(cmd)
109
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
110
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
111
+ exts.each do |ext|
112
+ exe = File.join(path, "#{cmd}#{ext}")
113
+ return exe if File.executable?(exe) && !File.directory?(exe)
114
+ end
115
+ end
116
+ nil
117
+ end
68
118
 
69
119
  end
70
120
  end
@@ -4,7 +4,7 @@ require 'netaddr'
4
4
 
5
5
  module CfnVpn
6
6
  class ClientVpn
7
- include CfnVpn::Log
7
+
8
8
 
9
9
  def initialize(name,region)
10
10
  @client = Aws::EC2::Client.new(region: region)
@@ -16,7 +16,7 @@ module CfnVpn
16
16
  filters: [{ name: "tag:cfnvpn:name", values: [@name] }]
17
17
  })
18
18
  if resp.client_vpn_endpoints.empty?
19
- Log.logger.error "unable to find endpoint with tag Key: cfnvpn:name with Value: #{@name}"
19
+ CfnVpn::Log.logger.error "unable to find endpoint with tag Key: cfnvpn:name with Value: #{@name}"
20
20
  raise "Unable to find client vpn"
21
21
  end
22
22
  return resp.client_vpn_endpoints.first
@@ -68,53 +68,6 @@ module CfnVpn
68
68
  })
69
69
  end
70
70
 
71
- def get_target_networks(endpoint_id)
72
- resp = @client.describe_client_vpn_target_networks({
73
- client_vpn_endpoint_id: endpoint_id
74
- })
75
- return resp.client_vpn_target_networks.first
76
- end
77
-
78
- def add_route(cidr,description)
79
- endpoint_id = get_endpoint_id()
80
- subnet_id = get_target_networks(endpoint_id).target_network_id
81
-
82
- @client.create_client_vpn_route({
83
- client_vpn_endpoint_id: endpoint_id,
84
- destination_cidr_block: cidr,
85
- target_vpc_subnet_id: subnet_id,
86
- description: description
87
- })
88
-
89
- resp = @client.authorize_client_vpn_ingress({
90
- client_vpn_endpoint_id: endpoint_id,
91
- target_network_cidr: cidr,
92
- authorize_all_groups: true,
93
- description: description
94
- })
95
-
96
- return resp.status
97
- end
98
-
99
- def del_route(cidr)
100
- endpoint_id = get_endpoint_id()
101
- subnet_id = get_target_networks(endpoint_id).target_network_id
102
-
103
- revoke = @client.revoke_client_vpn_ingress({
104
- revoke_all_groups: true,
105
- client_vpn_endpoint_id: endpoint_id,
106
- target_network_cidr: cidr
107
- })
108
-
109
- route = @client.delete_client_vpn_route({
110
- client_vpn_endpoint_id: endpoint_id,
111
- target_vpc_subnet_id: subnet_id,
112
- destination_cidr_block: cidr
113
- })
114
-
115
- return route.status, revoke.status
116
- end
117
-
118
71
  def get_routes()
119
72
  endpoint_id = get_endpoint_id()
120
73
  resp = @client.describe_client_vpn_routes({
@@ -124,30 +77,43 @@ module CfnVpn
124
77
  return resp.routes
125
78
  end
126
79
 
127
- def route_exists?(cidr)
128
- routes = get_routes()
129
- resp = routes.select { |route| route if route.destination_cidr == cidr }
130
- return resp.any?
80
+ def get_groups_for_route(endpoint, cidr)
81
+ auth_resp = @client.describe_client_vpn_authorization_rules({
82
+ client_vpn_endpoint_id: endpoint,
83
+ filters: [
84
+ {
85
+ name: 'destination-cidr',
86
+ values: [cidr]
87
+ }
88
+ ]
89
+ })
90
+ return auth_resp.authorization_rules.map {|rule| rule.group_id }
131
91
  end
132
92
 
133
- def get_routes()
134
- endpoint_id = get_endpoint_id()
135
- resp = @client.describe_client_vpn_routes({
136
- client_vpn_endpoint_id: endpoint_id,
137
- max_results: 20
93
+ def get_associations(endpoint)
94
+ associations = []
95
+ resp = @client.describe_client_vpn_target_networks({
96
+ client_vpn_endpoint_id: endpoint
138
97
  })
139
- return resp.routes
140
- end
141
98
 
142
- def get_route_with_mask()
143
- routes = get_routes()
144
- routes
145
- .select { |r| r if r.destination_cidr != '0.0.0.0/0' }
146
- .collect { |r| { route: r.destination_cidr.split('/').first, mask: NetAddr::IPv4Net.parse(r.destination_cidr).netmask.extended }}
147
- end
99
+ resp.client_vpn_target_networks.each do |net|
100
+ subnet_resp = @client.describe_subnets({
101
+ subnet_ids: [net.target_network_id]
102
+ })
103
+ subnet = subnet_resp.subnets.first
104
+ groups = get_groups_for_route(endpoint, subnet.cidr_block)
105
+
106
+ associations.push({
107
+ association_id: net.association_id,
108
+ target_network_id: net.target_network_id,
109
+ status: net.status.code,
110
+ cidr: subnet.cidr_block,
111
+ az: subnet.availability_zone,
112
+ groups: groups.join(' ')
113
+ })
114
+ end
148
115
 
149
- def valid_cidr?(cidr)
150
- return !(cidr =~ /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/).nil?
116
+ return associations
151
117
  end
152
118
 
153
119
  end
@@ -0,0 +1,23 @@
1
+ require 'cfnvpn/log'
2
+ require 'cfnvpn/templates/vpn'
3
+
4
+ module CfnVpn
5
+ class Compiler
6
+
7
+ def initialize(name, config)
8
+ @name = name
9
+ @config = config
10
+ end
11
+
12
+ def compile
13
+ CfnVpn::Log.logger.debug "Compiling cloudformation"
14
+ template = CfnVpn::Templates::Vpn.new()
15
+ template.render(@name, @config)
16
+ CfnVpn::Log.logger.debug "Validating cloudformation"
17
+ valid = template.validate
18
+ CfnVpn::Log.logger.debug "Clouformation Template\n\n#{JSON.parse(valid.to_json).to_yaml}"
19
+ return JSON.parse(valid.to_json).to_yaml
20
+ end
21
+
22
+ end
23
+ end
data/lib/cfnvpn/config.rb CHANGED
@@ -1,88 +1,45 @@
1
- require 'cfnvpn/clientvpn'
2
- require 'cfnvpn/log'
1
+ require 'aws-sdk-ssm'
2
+ require 'json'
3
+ require 'cfnvpn/deployer'
3
4
 
4
5
  module CfnVpn
5
- class Config < Thor::Group
6
- include Thor::Actions
7
- include CfnVpn::Log
8
-
9
- argument :name
10
-
11
- class_option :profile, desc: 'AWS Profile'
12
- class_option :region, default: ENV['AWS_REGION'], desc: 'AWS Region'
13
- class_option :verbose, desc: 'set log level to debug', type: :boolean
14
- class_option :bucket, required: true, desc: 's3 bucket'
15
- class_option :client_cn, required: true, desc: "client certificates to download"
16
-
17
- class_option :ignore_routes, alias: :i, type: :boolean, desc: "Ignore client VPN pushed routes and set routes in config file"
18
-
19
- def self.source_root
20
- File.dirname(__FILE__)
21
- end
22
-
23
- def set_loglevel
24
- Log.logger.level = Logger::DEBUG if @options['verbose']
25
- end
26
-
27
- def create_config_directory
28
- @build_dir = "#{ENV['HOME']}/.cfnvpn/#{@name}"
29
- @config_dir = "#{@build_dir}/config"
30
- Log.logger.debug("Creating config directory #{@config_dir}")
31
- FileUtils.mkdir_p(@config_dir)
32
- end
33
-
34
- def download_config
35
- vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
36
- @endpoint_id = vpn.get_endpoint_id()
37
- Log.logger.info "downloading client config for #{@endpoint_id}"
38
- @config = vpn.get_config(@endpoint_id)
39
- end
40
-
41
- def download_certificates
42
- download = true
43
- if File.exists?("#{@config_dir}/#{@options['client_cn']}.crt")
44
- download = yes? "Certificates for #{@options['client_cn']} already exist in #{@config_dir}. Do you want to download again? ", :green
45
- end
46
-
47
- if download
48
- Log.logger.info "Downloading certificates for #{@options['client_cn']} to #{@config_dir}"
49
- s3 = CfnVpn::S3.new(@options['region'],@options['bucket'],@name)
50
- s3.get_object("#{@config_dir}/#{@options['client_cn']}.tar.gz")
51
- cert = CfnVpn::Certificates.new(@build_dir,@name)
52
- Log.logger.debug cert.extract_certificate(@options['client_cn'])
6
+ class Config
7
+
8
+ def self.get_config(region, name)
9
+ client = Aws::SSM::Client.new(region: region)
10
+ begin
11
+ resp = client.get_parameter({name: "/cfnvpn/config/#{name}"})
12
+ return JSON.parse(resp.parameter.value, {:symbolize_names => true})
13
+ rescue Aws::SSM::Errors::ParameterNotFound => e
14
+ return self.get_config_from_parameter(region, name)
53
15
  end
54
16
  end
55
17
 
56
- def alter_config
57
- string = (0...8).map { (65 + rand(26)).chr.downcase }.join
58
- @config.sub!(@endpoint_id, "#{string}.#{@endpoint_id}")
59
- @config.concat("\n\ncert #{@config_dir}/#{@options['client_cn']}.crt")
60
- @config.concat("\nkey #{@config_dir}/#{@options['client_cn']}.key\n")
18
+ # to support upgrade from <=0.5.1 to >1.0
19
+ def self.get_config_from_parameter(region, name)
20
+ deployer = CfnVpn::Deployer.new(region, name)
21
+ parameters = deployer.get_parameters_from_stack_hash()
22
+ {
23
+ type: 'certificate',
24
+ server_cert_arn: parameters[:ServerCertificateArn],
25
+ client_cert_arn: parameters[:ClientCertificateArn],
26
+ region: region,
27
+ subnet_ids: [parameters[:AssociationSubnetId]],
28
+ cidr: parameters[:ClientCidrBlock],
29
+ dns_servers: parameters[:DnsServers].split(','),
30
+ split_tunnel: parameters[:SplitTunnel] == "true",
31
+ internet_route: parameters[:InternetRoute] == "true" ? parameters[:AssociationSubnetId] : nil,
32
+ protocol: parameters[:Protocol],
33
+ routes: []
34
+ }
61
35
  end
62
36
 
63
- def add_routes
64
- if @options['ignore_routes']
65
- Log.logger.debug "Ignoring routes pushed by the client vpn"
66
- @config.concat("\nroute-nopull\n")
67
- vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
68
- routes = vpn.get_route_with_mask
69
- Log.logger.debug "Found routes #{routes}"
70
- routes.each do |r|
71
- @config.concat("route #{r[:route]} #{r[:mask]}\n")
72
- end
73
- dns_servers = vpn.get_dns_servers()
74
- if dns_servers.any?
75
- Log.logger.debug "Found DNS servers #{dns_servers.join(' ')}"
76
- @config.concat("dhcp-option DNS #{dns_servers.first}\n")
77
- end
78
- end
37
+ def self.get_config_from_yaml_file(file)
38
+ YAML.load(File.read(file), symbolize_names: true)
79
39
  end
80
40
 
81
- def write_config
82
- config_file = "#{@config_dir}/#{@name}.ovpn"
83
- File.write(config_file, @config)
84
- Log.logger.info "downloaded client config #{config_file}"
41
+ def self.dump_config_to_yaml_file(name, params)
42
+ File.write(File.join(Dir.pwd, "cfnvpn.#{name}.yaml"), Hash[params.collect{|k,v| [k.to_s, v]}].to_yaml)
85
43
  end
86
-
87
44
  end
88
- end
45
+ end
@@ -2,10 +2,10 @@ require 'aws-sdk-cloudformation'
2
2
  require 'fileutils'
3
3
  require 'cfnvpn/version'
4
4
  require 'cfnvpn/log'
5
+ require 'cfnvpn/string'
5
6
 
6
7
  module CfnVpn
7
- class Cloudformation
8
- include CfnVpn::Log
8
+ class Deployer
9
9
 
10
10
  def initialize(region,name)
11
11
  @name = name
@@ -29,28 +29,25 @@ module CfnVpn
29
29
  return does_cf_stack_exist() ? 'UPDATE' : 'CREATE'
30
30
  end
31
31
 
32
- def create_change_set(template_path,parameters)
32
+ def create_change_set(template_body: nil, parameters: {})
33
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
35
 
36
- if change_set_type == 'CREATE'
37
- params = get_parameters_from_template(template_path)
36
+ if !template_body.nil?
37
+ params = get_parameters_from_template(template_body)
38
38
  else
39
39
  params = get_parameters_from_stack()
40
40
  end
41
-
41
+
42
42
  params.each do |param|
43
43
  if !parameters[param[:parameter_key]].nil?
44
- param['parameter_value'] = parameters[param[:parameter_key]]
45
- param['use_previous_value'] = false
44
+ param[:parameter_value] = parameters[param[:parameter_key]]
45
+ param[:use_previous_value] = false
46
46
  end
47
47
  end
48
48
 
49
- template_body = File.read(template_path)
50
- Log.logger.debug "Creating changeset"
51
- change_set = @client.create_change_set({
49
+ changeset_args = {
52
50
  stack_name: @stack_name,
53
- template_body: template_body,
54
51
  parameters: params,
55
52
  tags: [
56
53
  {
@@ -63,18 +60,28 @@ module CfnVpn
63
60
  }
64
61
  ],
65
62
  change_set_name: change_set_name,
66
- change_set_type: change_set_type
67
- })
63
+ change_set_type: change_set_type,
64
+ capabilities: ['CAPABILITY_IAM']
65
+ }
66
+
67
+ if !template_body.nil?
68
+ changeset_args[:template_body] = template_body
69
+ else
70
+ changeset_args[:use_previous_template] = true
71
+ end
72
+
73
+ CfnVpn::Log.logger.debug "Creating changeset"
74
+ change_set = @client.create_change_set(changeset_args)
68
75
  return change_set, change_set_type
69
76
  end
70
77
 
71
78
  def wait_for_changeset(change_set_id)
72
- Log.logger.debug "Waiting for changeset to be created"
79
+ CfnVpn::Log.logger.debug "Waiting for changeset to be created"
73
80
  begin
74
81
  @client.wait_until :change_set_create_complete, change_set_name: change_set_id
75
82
  rescue Aws::Waiters::Errors::FailureStateError => e
76
83
  change_set = get_change_set(change_set_id)
77
- Log.logger.error("change set status: #{change_set.status} reason: #{change_set.status_reason}")
84
+ CfnVpn::Log.logger.error("change set status: #{change_set.status} reason: #{change_set.status_reason}")
78
85
  exit 1
79
86
  end
80
87
  end
@@ -86,7 +93,7 @@ module CfnVpn
86
93
  end
87
94
 
88
95
  def execute_change_set(change_set_id)
89
- Log.logger.debug "Executing the changeset"
96
+ CfnVpn::Log.logger.debug "Executing the changeset"
90
97
  stack = @client.execute_change_set({
91
98
  change_set_name: change_set_id
92
99
  })
@@ -94,7 +101,7 @@ module CfnVpn
94
101
 
95
102
  def wait_for_execute(change_set_type)
96
103
  waiter = change_set_type == 'CREATE' ? :stack_create_complete : :stack_update_complete
97
- Log.logger.info "Waiting for changeset to #{change_set_type}"
104
+ CfnVpn::Log.logger.info "Waiting for changeset to #{change_set_type}"
98
105
  resp = @client.wait_until waiter, stack_name: @stack_name
99
106
  end
100
107
 
@@ -103,11 +110,32 @@ module CfnVpn
103
110
  return resp.parameters.collect { |p| { parameter_key: p.parameter_key, use_previous_value: true } }
104
111
  end
105
112
 
106
- def get_parameters_from_template(template_path)
107
- template_body = File.read(template_path)
113
+ def get_parameters_from_template(template_body)
108
114
  resp = @client.get_template_summary({ template_body: template_body })
109
115
  return resp.parameters.collect { |p| { parameter_key: p.parameter_key, parameter_value: p.default_value } }
110
116
  end
111
117
 
118
+ def get_parameter_value(parameter)
119
+ resp = @client.describe_stacks({ stack_name: @stack_name })
120
+ stack = resp.stacks.first
121
+ parameter = stack.parameters.detect {|p| p.parameter_key == parameter}
122
+ return parameter ? parameter.parameter_value : nil
123
+ end
124
+
125
+ def get_parameters_from_stack_hash()
126
+ resp = @client.describe_stacks({
127
+ stack_name: @stack_name,
128
+ })
129
+ stack = resp.stacks.first
130
+ return Hash[stack.parameters.collect {|parameter| [parameter.parameter_key.to_sym, parameter.parameter_value]}]
131
+ end
132
+
133
+ def get_outputs_from_stack()
134
+ resp = @client.describe_stacks({
135
+ stack_name: @stack_name,
136
+ })
137
+ stack = resp.stacks.first
138
+ return Hash[stack.outputs.collect {|output| [output.output_key.underscore.to_sym, output.output_value]}]
139
+ end
112
140
  end
113
141
  end