1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'lib/puppet/functions/hiera_ssm_paramstore.rb', line 1
Puppet::Functions.create_function(:hiera_ssm_paramstore) do
begin
require 'aws-sdk-ssm'
rescue LoadError
raise Puppet::DataBinding::LookupError, 'Must install gem aws-sdk-ssm to use hiera_ssm_paramstore'
end
dispatch :lookup_key do
param 'Variant[String, Numeric]', :key
param 'Hash', :options
optional_param 'Puppet::LookupContext', :context
end
def lookup_key(key, options, context = nil)
key_path = options['uri'] + key.gsub('::', '/')
key_path = context.interpolate(key_path) if context
if options['get_all'] && context
if !context.cache_has_key('ssm_cached')
context.explain { 'No cache, caching...' }
get_all_parameters(options, context)
else
context.explain { 'Cache populated!!!' }
end
if context.cache_has_key(key)
context.explain { "Returning value for key #{key}" }
return context.cached_value(key)
elsif context.cache_has_key(key_path)
context.explain { "Returning value for #{key}" }
return context.cached_value(key_path)
else
context.explain { "Key #{key} not found" }
return context.not_found
end
else
result = get_parameter(key_path, options, context)
return result
end
end
def ssm_get_connection(options)
if options['region'].nil?
Aws::SSM::Client.new
else
Aws::SSM::Client.new(region: options['region'])
end
rescue Aws::SSM::Errors::ServiceError => e
raise Puppet::DataBinding::LookupError, "Fail to connect to aws ssm #{e.message}"
end
def get_all_parameters(options, context)
token = nil
options['recursive'] ||= false
ssmclient = ssm_get_connection(options)
loop do
begin
context.explain { "Getting keys on #{options['uri']} ..." }
data = ssmclient.get_parameters_by_path(path: options['uri'],
with_decryption: true,
recursive: options['recursive'],
next_token: token)
context.explain { 'Adding keys on cache ...' }
data['parameters'].each do |k|
context.cache(k['name'], k['value'])
end
context.explain { 'Marking cache as populated' }
context.cache('ssm_cached', 'true')
break if data.next_token.nil?
token = data.next_token
rescue Aws::SSM::Errors::ServiceError => e
raise Puppet::DataBinding::LookupError, "AWS SSM Service error #{e.message} with path: #{options['uri']}"
end
end
end
def get_parameter(key_path, options, context)
ssmclient = ssm_get_connection(options)
if context && context.cache_has_key(key_path)
context.explain { "Returning cached value for #{key_path}" }
return context.cached_value(key_path)
else
context.explain { "Looking for #{key_path}" } if context
begin
resp = ssmclient.get_parameters(names: [key_path],
with_decryption: true)
if !resp.parameters.empty?
value = resp.parameters[0].value
context.cache(key_path, value) if context
return value
elsif context
context.explain { "Key #{key_path} not found" }
context.not_found
else
return nil
end
rescue Aws::SSM::Errors::ServiceError => e
raise Puppet::DataBinding::LookupError, "AWS SSM Service error #{e.message} with names: [#{key_path}]"
end
end
end
end
|