cfn-vpn 0.5.1 → 1.3.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.
- checksums.yaml +4 -4
- data/.github/workflows/build-gem.yml +25 -0
- data/.github/workflows/release-gem.yml +34 -0
- data/.github/workflows/release-image.yml +33 -0
- data/Gemfile.lock +33 -39
- data/README.md +1 -247
- data/cfn-vpn.gemspec +4 -4
- data/docs/README.md +44 -0
- data/docs/certificate-users.md +89 -0
- data/docs/getting-started.md +128 -0
- data/docs/modifying.md +67 -0
- data/docs/routes.md +98 -0
- data/docs/scheduling.md +32 -0
- data/docs/sessions.md +27 -0
- data/lib/cfnvpn.rb +31 -27
- data/lib/cfnvpn/{client.rb → actions/client.rb} +5 -6
- data/lib/cfnvpn/{embedded.rb → actions/embedded.rb} +15 -15
- data/lib/cfnvpn/actions/init.rb +144 -0
- data/lib/cfnvpn/actions/modify.rb +169 -0
- data/lib/cfnvpn/actions/params.rb +73 -0
- data/lib/cfnvpn/{revoke.rb → actions/revoke.rb} +6 -6
- data/lib/cfnvpn/actions/routes.rb +196 -0
- data/lib/cfnvpn/{sessions.rb → actions/sessions.rb} +5 -5
- data/lib/cfnvpn/{share.rb → actions/share.rb} +10 -10
- data/lib/cfnvpn/actions/subnets.rb +78 -0
- data/lib/cfnvpn/certificates.rb +5 -5
- data/lib/cfnvpn/clientvpn.rb +49 -65
- data/lib/cfnvpn/compiler.rb +23 -0
- data/lib/cfnvpn/config.rb +34 -78
- data/lib/cfnvpn/{cloudformation.rb → deployer.rb} +47 -19
- data/lib/cfnvpn/log.rb +26 -26
- data/lib/cfnvpn/s3.rb +34 -4
- data/lib/cfnvpn/s3_bucket.rb +48 -0
- data/lib/cfnvpn/string.rb +33 -0
- data/lib/cfnvpn/templates/helper.rb +14 -0
- data/lib/cfnvpn/templates/lambdas.rb +35 -0
- data/lib/cfnvpn/templates/lambdas/auto_route_populator/app.py +175 -0
- data/lib/cfnvpn/templates/lambdas/scheduler/app.py +36 -0
- data/lib/cfnvpn/templates/vpn.rb +449 -0
- data/lib/cfnvpn/version.rb +1 -1
- metadata +73 -23
- data/lib/cfnvpn/cfhighlander.rb +0 -49
- data/lib/cfnvpn/init.rb +0 -109
- data/lib/cfnvpn/modify.rb +0 -103
- data/lib/cfnvpn/routes.rb +0 -84
- data/lib/cfnvpn/templates/cfnvpn.cfhighlander.rb.tt +0 -27
data/lib/cfnvpn/certificates.rb
CHANGED
@@ -6,7 +6,7 @@ require 'cfnvpn/log'
|
|
6
6
|
|
7
7
|
module CfnVpn
|
8
8
|
class Certificates
|
9
|
-
|
9
|
+
|
10
10
|
|
11
11
|
def initialize(build_dir, cfnvpn_name, easyrsa_local = false)
|
12
12
|
@cfnvpn_name = cfnvpn_name
|
@@ -44,7 +44,7 @@ module CfnVpn
|
|
44
44
|
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
45
45
|
@docker_cmd << @easyrsa_image
|
46
46
|
@docker_cmd << "sh -c 'create-ca'"
|
47
|
-
Log.logger.debug `#{@docker_cmd.join(' ')}`
|
47
|
+
CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -59,7 +59,7 @@ module CfnVpn
|
|
59
59
|
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
60
60
|
@docker_cmd << @easyrsa_image
|
61
61
|
@docker_cmd << "sh -c 'create-client'"
|
62
|
-
Log.logger.debug `#{@docker_cmd.join(' ')}`
|
62
|
+
CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -76,7 +76,7 @@ module CfnVpn
|
|
76
76
|
@docker_cmd << "-v #{@cert_dir}:/easy-rsa/output"
|
77
77
|
@docker_cmd << @easyrsa_image
|
78
78
|
@docker_cmd << "sh -c 'revoke-client'"
|
79
|
-
Log.logger.debug `#{@docker_cmd.join(' ')}`
|
79
|
+
CfnVpn::Log.logger.debug `#{@docker_cmd.join(' ')}`
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
@@ -84,7 +84,7 @@ module CfnVpn
|
|
84
84
|
cn = cn.nil? ? cert : cn
|
85
85
|
acm = CfnVpn::Acm.new(region, @cert_dir)
|
86
86
|
arn = acm.import_certificate("#{cert}.crt", "#{cert}.key", "ca.crt")
|
87
|
-
Log.logger.debug "Uploaded #{type} certificate to ACM #{arn}"
|
87
|
+
CfnVpn::Log.logger.debug "Uploaded #{type} certificate to ACM #{arn}"
|
88
88
|
acm.tag_certificate(arn,cn,type,@cfnvpn_name)
|
89
89
|
return arn
|
90
90
|
end
|
data/lib/cfnvpn/clientvpn.rb
CHANGED
@@ -4,11 +4,12 @@ require 'netaddr'
|
|
4
4
|
|
5
5
|
module CfnVpn
|
6
6
|
class ClientVpn
|
7
|
-
|
7
|
+
|
8
8
|
|
9
9
|
def initialize(name,region)
|
10
10
|
@client = Aws::EC2::Client.new(region: region)
|
11
11
|
@name = name
|
12
|
+
@endpoint_id = self.get_endpoint_id()
|
12
13
|
end
|
13
14
|
|
14
15
|
def get_endpoint()
|
@@ -16,7 +17,7 @@ module CfnVpn
|
|
16
17
|
filters: [{ name: "tag:cfnvpn:name", values: [@name] }]
|
17
18
|
})
|
18
19
|
if resp.client_vpn_endpoints.empty?
|
19
|
-
Log.logger.error "unable to find endpoint with tag Key: cfnvpn:name with Value: #{@name}"
|
20
|
+
CfnVpn::Log.logger.error "unable to find endpoint with tag Key: cfnvpn:name with Value: #{@name}"
|
20
21
|
raise "Unable to find client vpn"
|
21
22
|
end
|
22
23
|
return resp.client_vpn_endpoints.first
|
@@ -68,86 +69,69 @@ module CfnVpn
|
|
68
69
|
})
|
69
70
|
end
|
70
71
|
|
71
|
-
def
|
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)
|
72
|
+
def get_routes()
|
79
73
|
endpoint_id = get_endpoint_id()
|
80
|
-
|
81
|
-
|
82
|
-
@client.create_client_vpn_route({
|
74
|
+
resp = @client.describe_client_vpn_routes({
|
83
75
|
client_vpn_endpoint_id: endpoint_id,
|
84
|
-
|
85
|
-
target_vpc_subnet_id: subnet_id,
|
86
|
-
description: description
|
76
|
+
max_results: 20
|
87
77
|
})
|
78
|
+
return resp.routes
|
79
|
+
end
|
88
80
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
81
|
+
def get_groups_for_route(endpoint, cidr)
|
82
|
+
auth_resp = @client.describe_client_vpn_authorization_rules({
|
83
|
+
client_vpn_endpoint_id: endpoint,
|
84
|
+
filters: [
|
85
|
+
{
|
86
|
+
name: 'destination-cidr',
|
87
|
+
values: [cidr]
|
88
|
+
}
|
89
|
+
]
|
94
90
|
})
|
95
|
-
|
96
|
-
return resp.status
|
91
|
+
return auth_resp.authorization_rules.map {|rule| rule.group_id }
|
97
92
|
end
|
98
93
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
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
|
94
|
+
def get_associations(endpoint)
|
95
|
+
associations = []
|
96
|
+
resp = @client.describe_client_vpn_target_networks({
|
97
|
+
client_vpn_endpoint_id: endpoint
|
107
98
|
})
|
108
99
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
100
|
+
resp.client_vpn_target_networks.each do |net|
|
101
|
+
subnet_resp = @client.describe_subnets({
|
102
|
+
subnet_ids: [net.target_network_id]
|
103
|
+
})
|
104
|
+
subnet = subnet_resp.subnets.first
|
105
|
+
groups = get_groups_for_route(endpoint, subnet.cidr_block)
|
106
|
+
|
107
|
+
associations.push({
|
108
|
+
association_id: net.association_id,
|
109
|
+
target_network_id: net.target_network_id,
|
110
|
+
status: net.status.code,
|
111
|
+
cidr: subnet.cidr_block,
|
112
|
+
az: subnet.availability_zone,
|
113
|
+
groups: groups.join(' ')
|
114
|
+
})
|
115
|
+
end
|
114
116
|
|
115
|
-
return
|
117
|
+
return associations
|
116
118
|
end
|
117
119
|
|
118
|
-
def
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
120
|
+
def delete_route(cidr, subnet)
|
121
|
+
@client.delete_client_vpn_route({
|
122
|
+
client_vpn_endpoint_id: @endpoint_id,
|
123
|
+
target_vpc_subnet_id: subnet,
|
124
|
+
destination_cidr_block: cidr
|
123
125
|
})
|
124
|
-
return resp.routes
|
125
|
-
end
|
126
|
-
|
127
|
-
def route_exists?(cidr)
|
128
|
-
routes = get_routes()
|
129
|
-
resp = routes.select { |route| route if route.destination_cidr == cidr }
|
130
|
-
return resp.any?
|
131
126
|
end
|
132
127
|
|
133
|
-
def
|
128
|
+
def revoke_auth(cidr)
|
134
129
|
endpoint_id = get_endpoint_id()
|
135
|
-
|
136
|
-
client_vpn_endpoint_id: endpoint_id,
|
137
|
-
|
130
|
+
@client.revoke_client_vpn_ingress({
|
131
|
+
client_vpn_endpoint_id: @endpoint_id,
|
132
|
+
target_network_cidr: cidr,
|
133
|
+
revoke_all_groups: true
|
138
134
|
})
|
139
|
-
return resp.routes
|
140
|
-
end
|
141
|
-
|
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
|
148
|
-
|
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?
|
151
135
|
end
|
152
136
|
|
153
137
|
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,89 +1,45 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'cfnvpn/
|
1
|
+
require 'aws-sdk-ssm'
|
2
|
+
require 'json'
|
3
|
+
require 'cfnvpn/deployer'
|
4
4
|
|
5
5
|
module CfnVpn
|
6
|
-
class Config
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
class_option :bucket, required: true, desc: 's3 bucket'
|
16
|
-
class_option :client_cn, required: true, desc: "client certificates to download"
|
17
|
-
class_option :easyrsa_local, type: :boolean, default: false, desc: 'run the easyrsa executable from your local rather than from docker'
|
18
|
-
class_option :ignore_routes, alias: :i, type: :boolean, desc: "Ignore client VPN pushed routes and set routes in config file"
|
19
|
-
|
20
|
-
def self.source_root
|
21
|
-
File.dirname(__FILE__)
|
22
|
-
end
|
23
|
-
|
24
|
-
def set_loglevel
|
25
|
-
Log.logger.level = Logger::DEBUG if @options['verbose']
|
26
|
-
end
|
27
|
-
|
28
|
-
def create_config_directory
|
29
|
-
@build_dir = "#{CfnVpn.cfnvpn_path}/#{@name}"
|
30
|
-
@config_dir = "#{@build_dir}/config"
|
31
|
-
Log.logger.debug("Creating config directory #{@config_dir}")
|
32
|
-
FileUtils.mkdir_p(@config_dir)
|
33
|
-
end
|
34
|
-
|
35
|
-
def download_config
|
36
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
37
|
-
@endpoint_id = vpn.get_endpoint_id()
|
38
|
-
Log.logger.info "downloading client config for #{@endpoint_id}"
|
39
|
-
@config = vpn.get_config(@endpoint_id)
|
40
|
-
end
|
41
|
-
|
42
|
-
def download_certificates
|
43
|
-
download = true
|
44
|
-
if File.exists?("#{@config_dir}/#{@options['client_cn']}.crt")
|
45
|
-
download = yes? "Certificates for #{@options['client_cn']} already exist in #{@config_dir}. Do you want to download again? ", :green
|
46
|
-
end
|
47
|
-
|
48
|
-
if download
|
49
|
-
Log.logger.info "Downloading certificates for #{@options['client_cn']} to #{@config_dir}"
|
50
|
-
s3 = CfnVpn::S3.new(@options['region'],@options['bucket'],@name)
|
51
|
-
s3.get_object("#{@config_dir}/#{@options['client_cn']}.tar.gz")
|
52
|
-
cert = CfnVpn::Certificates.new(@build_dir,@name,@options['easyrsa_local'])
|
53
|
-
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)
|
54
15
|
end
|
55
16
|
end
|
56
17
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
+
}
|
62
35
|
end
|
63
36
|
|
64
|
-
def
|
65
|
-
|
66
|
-
Log.logger.debug "Ignoring routes pushed by the client vpn"
|
67
|
-
@config.concat("\nroute-nopull\n")
|
68
|
-
vpn = CfnVpn::ClientVpn.new(@name,@options['region'])
|
69
|
-
routes = vpn.get_route_with_mask
|
70
|
-
Log.logger.debug "Found routes #{routes}"
|
71
|
-
routes.each do |r|
|
72
|
-
@config.concat("route #{r[:route]} #{r[:mask]}\n")
|
73
|
-
end
|
74
|
-
dns_servers = vpn.get_dns_servers()
|
75
|
-
if dns_servers.any?
|
76
|
-
Log.logger.debug "Found DNS servers #{dns_servers.join(' ')}"
|
77
|
-
@config.concat("dhcp-option DNS #{dns_servers.first}\n")
|
78
|
-
end
|
79
|
-
end
|
37
|
+
def self.get_config_from_yaml_file(file)
|
38
|
+
YAML.load(File.read(file), symbolize_names: true)
|
80
39
|
end
|
81
40
|
|
82
|
-
def
|
83
|
-
|
84
|
-
File.write(config_file, @config)
|
85
|
-
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)
|
86
43
|
end
|
87
|
-
|
88
44
|
end
|
89
|
-
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
|
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(
|
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
|
37
|
-
params = get_parameters_from_template(
|
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
44
|
param[:parameter_value] = parameters[param[:parameter_key]]
|
45
45
|
param[:use_previous_value] = false
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
49
|
-
|
50
|
-
Log.logger.debug "Creating changeset"
|
51
|
-
change_set = @client.create_change_set({
|
48
|
+
|
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(
|
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
|