jerakia 1.2.1 → 2.0.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.
data/lib/jerakia/log.rb CHANGED
@@ -2,12 +2,12 @@ class Jerakia::Log < Jerakia
2
2
  require 'logger'
3
3
  def initialize(level = :info, file = '/var/log/jerakia.log')
4
4
  begin
5
- @@logger ||= Logger.new(file)
5
+ @@logger = Logger.new(file)
6
6
  rescue Errno::EACCES => e
7
7
  raise Jerakia::Error, "Error opening log file, #{e.message}"
8
8
  end
9
9
 
10
- @@level ||= level
10
+ @@level = level
11
11
  case @@level
12
12
  when :verbose
13
13
  @@logger.level = Logger::INFO
@@ -42,20 +42,4 @@ class Jerakia::Log < Jerakia
42
42
  @@logger.fatal msg
43
43
  end
44
44
 
45
- # def self.fatal(msg)
46
- # self.new.fatal msg
47
- # end
48
- #
49
- # def self.error(msg)
50
- # self.new.error msg
51
- # end
52
- #
53
- # def self.debug(msg)
54
- # self.new.debug msg
55
- # end
56
- #
57
- ## def self.info(msg)
58
- # puts @@logger
59
- # self.new.info msg
60
- # end
61
45
  end
@@ -14,7 +14,6 @@ class Jerakia::Lookup
14
14
  attr_reader :output_filters
15
15
  attr_reader :name
16
16
  attr_reader :pluginfactory
17
- attr_reader :datasource
18
17
 
19
18
  def initialize(name, opts, req, scope)
20
19
  @name = name
@@ -58,18 +57,6 @@ class Jerakia::Lookup
58
57
  pluginfactory
59
58
  end
60
59
 
61
- def get_datasource
62
- @datasource
63
- end
64
-
65
- def datasource(source, opts = {})
66
- @datasource = Jerakia::Datasource.new(source, self, opts)
67
- end
68
-
69
- # If set, Jerakia will pass each Jerakia::Response object
70
- # to an output filter plugin
71
- #
72
-
73
60
  def scope
74
61
  scope_object.value
75
62
  end
@@ -131,15 +118,4 @@ class Jerakia::Lookup
131
118
  end
132
119
  end
133
120
 
134
- def run
135
- Jerakia.log.verbose("lookup: #{@name} key: #{@request.key} namespace: #{@request.namespace.join('/')}")
136
- @datasource.run
137
- response = @datasource.response
138
- @output_filters.each do |filter|
139
- response.filter! filter[:name], filter[:opts]
140
- end
141
- response
142
- end
143
-
144
- private
145
121
  end
@@ -1,85 +1,58 @@
1
1
  require 'jerakia/launcher'
2
2
  require 'jerakia/answer'
3
3
  require 'jerakia/schema'
4
+ require 'jerakia/datasource'
4
5
 
5
6
  class Jerakia
6
7
  class Policy
7
8
  attr_accessor :lookups
8
- attr_reader :answer
9
- attr_reader :scope
10
- attr_reader :lookup_proceed
11
- attr_reader :schema
12
- attr_reader :request
9
+ attr_reader :name
10
+ attr_reader :datasources
13
11
 
14
12
  # _opts currently does not get used, but is included here as a placeholder
15
13
  # for allowing policies to be declared with options;
16
14
  # policy :foo, :option => :value do
17
15
  #
18
- def initialize(_name, _opts, req)
19
- if req.use_schema && Jerakia.config[:enable_schema]
20
- schema_config = Jerakia.config[:schema] || {}
21
- @schema = Jerakia::Schema.new(req, schema_config)
22
- end
23
-
16
+ def initialize(name, _opts)
17
+ @name = name
24
18
  @lookups = []
25
- @request = req
26
- @answer = Jerakia::Answer.new(req.lookup_type)
27
- @scope = Jerakia::Scope.new(req)
28
- @lookup_proceed = true
19
+ @datasources = {}
29
20
  end
30
21
 
31
- def clone_request
32
- Marshal.load(Marshal.dump(request))
33
- end
22
+ def run(request)
34
23
 
35
- def submit_lookup(lookup)
36
- raise Jerakia::PolicyError, "Lookup #{lookup.name} has no datasource defined" unless lookup.get_datasource
37
- @lookups << lookup if lookup.valid? && @lookup_proceed
38
- @lookup_proceed = false if !lookup.proceed? && lookup.valid?
39
- end
24
+ if request.use_schema && Jerakia.config[:enable_schema]
25
+ schema_config = Jerakia.config[:schema] || {}
26
+ @schema = Jerakia::Schema.new(request, schema_config)
27
+ end
40
28
 
41
- def execute
42
- response_entries = []
29
+ scope = Jerakia::Scope.new(request)
30
+ answer = Jerakia::Answer.new(request.lookup_type, request.merge)
43
31
 
44
- @lookups.each do |l|
45
- responses = l.run
46
- lookup_answers = responses.entries.map { |r| r }
32
+ response_entries = []
33
+ lookups.each do |lookup|
34
+ lookup_instance = lookup.call clone_request(request), scope
35
+ next unless lookup_instance.valid? && lookup_instance.proceed?
36
+ register_datasource lookup_instance.datasource[:name]
37
+ responses = Jerakia::Datasource.run(lookup_instance)
38
+ lookup_instance.output_filters.each do |filter|
39
+ Jerakia.log.debug("Using output filter #{filter[:name]}")
40
+ responses.filter! filter[:name], filter[:opts]
41
+ end
42
+ lookup_answers = responses.entries.map { |r| r}
47
43
  response_entries << lookup_answers if lookup_answers
48
44
  end
49
-
50
- response_entries.flatten.each { |res| process_response(res) }
51
- consolidate_answer
45
+ answer.process_response(response_entries)
46
+ return answer
52
47
  end
53
48
 
54
- private
55
-
56
- # Process the response depending on the requests lookup_type
57
- # if it is a :first lookup then we only want to set the result
58
- # once, if it's cascading, we should ammend the payload array
59
- #
60
- def process_response(res)
61
- case request.lookup_type
62
- when :first
63
- @answer.payload ||= res[:value]
64
- @answer.datatype ||= res[:datatype]
65
- when :cascade
66
- @answer.payload << res[:value]
67
- end
49
+ def register_datasource(datasource)
50
+ Jerakia::Datasource.load_datasource(datasource)
68
51
  end
69
52
 
70
- # Once all the responses are submitted into the answers payload
71
- # we need to consolidate the data based on the merge behaviour
72
- # requested.
73
- #
74
- def consolidate_answer
75
- if request.lookup_type == :cascade && @answer.payload.is_a?(Array)
76
- case request.merge
77
- when :array
78
- @answer.flatten_payload!
79
- when :hash, :deep_hash
80
- @answer.merge_payload!(request.merge)
81
- end
82
- end
53
+ def clone_request(request)
54
+ Marshal.load(Marshal.dump(request))
83
55
  end
56
+
84
57
  end
85
58
  end
@@ -1,7 +1,8 @@
1
1
  class Jerakia::Response
2
2
  module Filter
3
- def filter!(name, opts)
3
+ def filter!(name, opts = {})
4
4
  Jerakia::Util.autoload('response/filter', name)
5
+ Jerakia.log.debug("Invoking output filter #{name}")
5
6
  instance_eval "extend Jerakia::Response::Filter::#{name.to_s.capitalize}"
6
7
  instance_eval "self.filter_#{name} (#{opts})"
7
8
  end
@@ -1,51 +1,34 @@
1
- # Parts of this class are copied from https://github.com/TomPoulton/hiera-eyaml/blob/master/lib/hiera/backend/eyaml_backend.rb
2
- # The MIT License (MIT)
3
- #
4
- # Copyright (c) 2013 Tom Poulton
5
- #
6
- # Other code Copyright (c) 2014 Craig Dunn, Apache 2.0 License.
7
- #
8
-
9
- require 'hiera/backend/eyaml/encryptor'
10
- require 'hiera/backend/eyaml/utils'
11
- require 'hiera/backend/eyaml/options'
12
- require 'hiera/backend/eyaml/parser/parser'
13
- require 'hiera/filecache'
14
-
15
- require 'yaml'
1
+ require 'jerakia/encryption'
16
2
 
17
3
  class Jerakia::Response
18
4
  module Filter
19
5
  module Encryption
20
6
  def filter_encryption(_opts = {})
21
- parse_values do |val|
22
- decrypt val if val.is_a?(String)
23
- val
7
+ Jerakia.log.debug("Encryption filter started")
8
+ provider = Jerakia::Encryption.handler
9
+
10
+ unless provider.loaded?
11
+ raise Jerakia::Error, 'Cannot load encryption output filter, no encryption provider configured'
12
+ end
13
+ unless provider.respond_to?('signiture')
14
+ raise Jerakia::Error, 'Encryption provider did not provide a signiture method, cannot run output filter'
24
15
  end
25
- end
26
16
 
27
- def decrypt(data)
28
- if encrypted?(data)
29
- public_key = config['eyaml']['public_key']
30
- private_key = config['eyaml']['private_key']
31
- Hiera::Backend::Eyaml::Options[:pkcs7_private_key] = private_key
32
- Hiera::Backend::Eyaml::Options[:pkcs7_public_key] = public_key
33
- parser = Hiera::Backend::Eyaml::Parser::ParserFactory.hiera_backend_parser
17
+ signiture = provider.signiture
18
+ raise Jerakia::Error, "Encryption provider signiture is not a Regexp" unless signiture.is_a?(Regexp)
34
19
 
35
- tokens = parser.parse(data)
36
- decrypted = tokens.map(&:to_plain_text)
37
- plaintext = decrypted.join
38
- Jerakia.log.debug(plaintext)
39
- plaintext.chomp!
40
- data.clear.insert(0, plaintext)
41
- else
42
- data
20
+ # Match the signiture of the provider (from the signiture method) against the string
21
+ # if the string matches the regex then call the decrypt method of the encryption
22
+ # provider
23
+ #
24
+ parse_values do |val|
25
+ if val =~ signiture
26
+ decrypted = provider.decrypt(val)
27
+ val.clear.insert(0, decrypted)
28
+ end
29
+ val
43
30
  end
44
31
  end
45
-
46
- def encrypted?(data)
47
- /.*ENC\[.*?\]/ =~ data ? true : false
48
- end
49
32
  end
50
33
  end
51
34
  end
@@ -11,21 +11,21 @@ class Jerakia::Schema
11
11
  )
12
12
 
13
13
  Jerakia.log.debug("Schema lookup invoked for #{request.key} namespace: #{request.namespace}")
14
- schema_lookup = Jerakia::Launcher.new(schema_request)
15
14
 
16
15
  begin
17
- schema_lookup.evaluate do
16
+ schema_policy = Jerakia::Launcher.evaluate do
18
17
  policy :schema do
19
18
  lookup :schema do
20
19
  datasource *schema_datasource
21
20
  end
22
21
  end
23
22
  end
23
+ schema_lookup = schema_policy.run(schema_request)
24
24
  rescue Jerakia::Error => e
25
25
  raise Jerakia::SchemaError, "Schema lookup for #{request.key} failed: #{e.message}"
26
26
  end
27
27
 
28
- @schema_data = schema_lookup.answer.payload || {}
28
+ @schema_data = schema_lookup.payload || {}
29
29
 
30
30
  # Validate the returned data from the schema
31
31
  raise Jerakia::SchemaError, "Schema must return a hash for key #{request.key}" unless @schema_data.is_a?(Hash)
@@ -0,0 +1,51 @@
1
+ require 'net/http'
2
+ require 'json'
3
+ require 'openssl'
4
+
5
+ class Jerakia
6
+ module Util
7
+ class Http
8
+
9
+ class << self
10
+
11
+ def post(uri_str, data={}, headers={}, options={})
12
+ uri = URI.parse(uri_str)
13
+ request = Net::HTTP::Post.new(uri.path)
14
+ request.body = data.to_json
15
+ http_send(uri, request, headers, options)
16
+ end
17
+
18
+ def put(uri_str, data={}, headers={}, options={})
19
+ uri = URI.parse(uri_str)
20
+ request = Net::HTTP::Put.new(uri.path)
21
+ request.body = data.to_json
22
+ http_send(uri, request, headers, options)
23
+ end
24
+
25
+
26
+ def http_send(uri, request, headers={}, options={})
27
+ request.add_field('Content-Type', options[:content_type]) if options[:content_type]
28
+
29
+ headers.each do |header, value|
30
+ request.add_field(header, value)
31
+ end
32
+
33
+ http = Net::HTTP.new(uri.host, uri.port)
34
+ if options[:ssl]
35
+ http.use_ssl = true
36
+ http.verify_mode = options[:ssl_verify] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
37
+ http.cert = OpenSSL::X509::Certificate.new(options[:ssl_cert]) if options[:ssl_cert]
38
+ http.key = OpenSSL::PKey::RSA.new(options[:ssl_key]) if options[:ssl_key]
39
+ end
40
+
41
+ begin
42
+ response = http.request(request)
43
+ return response
44
+ rescue => e
45
+ raise Jerakia::HTTPError, e.message
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -3,5 +3,5 @@ class Jerakia
3
3
  #
4
4
  # This should be updated when a new gem is released and it is read from the gemspec file
5
5
  #
6
- VERSION = '1.2.1'.freeze
6
+ VERSION = '2.0.0'.freeze
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jerakia
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Dunn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-17 00:00:00.000000000 Z
11
+ date: 2017-04-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -116,7 +116,6 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - bin/jerakia
119
- - lib/hiera/backend/jerakia_backend.rb
120
119
  - lib/jerakia.rb
121
120
  - lib/jerakia/answer.rb
122
121
  - lib/jerakia/cache.rb
@@ -124,6 +123,7 @@ files:
124
123
  - lib/jerakia/cache/file.rb
125
124
  - lib/jerakia/cli.rb
126
125
  - lib/jerakia/cli/lookup.rb
126
+ - lib/jerakia/cli/secret.rb
127
127
  - lib/jerakia/cli/server.rb
128
128
  - lib/jerakia/cli/token.rb
129
129
  - lib/jerakia/config.rb
@@ -132,10 +132,11 @@ files:
132
132
  - lib/jerakia/datasource/file.rb
133
133
  - lib/jerakia/datasource/file/json.rb
134
134
  - lib/jerakia/datasource/file/yaml.rb
135
- - lib/jerakia/datasource/file_new.rb
136
135
  - lib/jerakia/datasource/http.rb
137
136
  - lib/jerakia/dsl/lookup.rb
138
137
  - lib/jerakia/dsl/policy.rb
138
+ - lib/jerakia/encryption.rb
139
+ - lib/jerakia/encryption/vault.rb
139
140
  - lib/jerakia/error.rb
140
141
  - lib/jerakia/launcher.rb
141
142
  - lib/jerakia/log.rb
@@ -145,7 +146,6 @@ files:
145
146
  - lib/jerakia/lookup/plugin_config.rb
146
147
  - lib/jerakia/lookup/pluginfactory.rb
147
148
  - lib/jerakia/policy.rb
148
- - lib/jerakia/policy/registry.rb
149
149
  - lib/jerakia/request.rb
150
150
  - lib/jerakia/response.rb
151
151
  - lib/jerakia/response/filter.rb
@@ -162,9 +162,8 @@ files:
162
162
  - lib/jerakia/server/auth/token.rb
163
163
  - lib/jerakia/server/rest.rb
164
164
  - lib/jerakia/util.rb
165
+ - lib/jerakia/util/http.rb
165
166
  - lib/jerakia/version.rb
166
- - lib/puppet/indirector/data_binding/jerakia.rb
167
- - lib/puppet/indirector/data_binding/jerakia_rest.rb
168
167
  homepage: http://jerakia.io
169
168
  licenses:
170
169
  - Apache 2.0
@@ -1,59 +0,0 @@
1
- require 'puppet'
2
- require 'puppet/resource'
3
-
4
- class Hiera
5
- module Backend
6
- class Jerakia_backend
7
- def initialize(config = nil)
8
- require 'jerakia'
9
- @config = config || Hiera::Config[:jerakia] || {}
10
- @policy = @config[:policy] || 'default'
11
- @jerakia = ::Jerakia.new(@config)
12
- Jerakia.log.debug("[hiera] hiera backend loaded with policy #{@policy}")
13
- end
14
-
15
- def lookup(key, scope, _order_override, resolution_type)
16
- lookup_type = :first
17
- merge_type = :none
18
-
19
- case resolution_type
20
- when :array
21
- lookup_type = :cascade
22
- merge_type = :array
23
- when :hash
24
- lookup_type = :cascade
25
- merge_type = :hash
26
- end
27
-
28
- namespace = []
29
-
30
- if key.include?('::')
31
- lookup_key = key.split('::')
32
- key = lookup_key.pop
33
- namespace = lookup_key
34
- end
35
-
36
- Jerakia.log.debug("[hiera] backend invoked for key #{key} using namespace #{namespace}")
37
-
38
- metadata = {}
39
- metadata = if scope.is_a?(Hash)
40
- scope.reject { |_k, v| v.is_a?(Puppet::Resource) }
41
- else
42
- scope.real.to_hash.reject { |_k, v| v.is_a?(Puppet::Resource) }
43
- end
44
-
45
- request = Jerakia::Request.new(
46
- :key => key,
47
- :namespace => namespace,
48
- :policy => metadata['jerakia_policy'] || @policy,
49
- :lookup_type => lookup_type,
50
- :merge => merge_type,
51
- :metadata => metadata
52
- )
53
-
54
- answer = @jerakia.lookup(request)
55
- answer.payload
56
- end
57
- end
58
- end
59
- end