hiera-eyaml 3.3.0 → 4.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +17 -0
  3. data/.github/workflows/release.yml +2 -2
  4. data/.github/workflows/test.yml +38 -21
  5. data/.rubocop.yml +8 -0
  6. data/.rubocop_todo.yml +416 -0
  7. data/CHANGELOG.md +59 -0
  8. data/Gemfile +13 -14
  9. data/README.md +37 -7
  10. data/Rakefile +11 -4
  11. data/hiera-eyaml.gemspec +17 -15
  12. data/lib/hiera/backend/eyaml/CLI.rb +12 -19
  13. data/lib/hiera/backend/eyaml/commands.rb +2 -6
  14. data/lib/hiera/backend/eyaml/edithelper.rb +24 -19
  15. data/lib/hiera/backend/eyaml/encrypthelper.rb +17 -19
  16. data/lib/hiera/backend/eyaml/encryptor.rb +40 -43
  17. data/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +79 -105
  18. data/lib/hiera/backend/eyaml/highlinehelper.rb +3 -5
  19. data/lib/hiera/backend/eyaml/logginghelper.rb +27 -29
  20. data/lib/hiera/backend/eyaml/options.rb +13 -16
  21. data/lib/hiera/backend/eyaml/parser/encrypted_tokens.rb +2 -2
  22. data/lib/hiera/backend/eyaml/parser/parser.rb +35 -36
  23. data/lib/hiera/backend/eyaml/parser/token.rb +15 -6
  24. data/lib/hiera/backend/eyaml/plugins.rb +13 -18
  25. data/lib/hiera/backend/eyaml/subcommand.rb +72 -74
  26. data/lib/hiera/backend/eyaml/subcommands/createkeys.rb +2 -6
  27. data/lib/hiera/backend/eyaml/subcommands/decrypt.rb +52 -52
  28. data/lib/hiera/backend/eyaml/subcommands/edit.rb +58 -59
  29. data/lib/hiera/backend/eyaml/subcommands/encrypt.rb +65 -69
  30. data/lib/hiera/backend/eyaml/subcommands/help.rb +17 -22
  31. data/lib/hiera/backend/eyaml/subcommands/recrypt.rb +13 -20
  32. data/lib/hiera/backend/eyaml/subcommands/unknown_command.rb +10 -14
  33. data/lib/hiera/backend/eyaml/subcommands/version.rb +4 -9
  34. data/lib/hiera/backend/eyaml/utils.rb +27 -28
  35. data/lib/hiera/backend/eyaml.rb +7 -9
  36. data/lib/hiera/backend/eyaml_backend.rb +34 -28
  37. metadata +63 -14
  38. data/tools/git_tag_release.rb +0 -98
  39. data/tools/regem.sh +0 -11
@@ -6,64 +6,63 @@ class Hiera
6
6
  module Backend
7
7
  module Eyaml
8
8
  class Utils
9
-
10
- def self.camelcase string
9
+ def self.camelcase(string)
11
10
  return string if string !~ /_/ && string =~ /[A-Z]+.*/
12
- string.split('_').map{|e| e.capitalize}.join
11
+
12
+ string.split('_').map { |e| e.capitalize }.join
13
13
  end
14
14
 
15
- def self.snakecase string
16
- return string if string !~ /[A-Z]/
17
- string.split(/(?=[A-Z])/).collect {|x| x.downcase}.join("_")
15
+ def self.snakecase(string)
16
+ return string unless /[A-Z]/.match?(string)
17
+
18
+ string.split(/(?=[A-Z])/).collect { |x| x.downcase }.join('_')
18
19
  end
19
20
 
20
- def self.find_closest_class args
21
- parent_class = args[ :parent_class ]
22
- class_name = args[ :class_name ]
21
+ def self.find_closest_class(args)
22
+ parent_class = args[:parent_class]
23
+ class_name = args[:class_name]
23
24
  constants = parent_class.constants
24
25
  candidates = []
25
- constants.each do | candidate |
26
+ constants.each do |candidate|
26
27
  candidates << candidate.to_s if candidate.to_s.downcase == class_name.downcase
27
28
  end
28
- if candidates.count > 0
29
- parent_class.const_get candidates.first
30
- else
31
- nil
32
- end
29
+ return unless candidates.count > 0
30
+
31
+ parent_class.const_get candidates.first
33
32
  end
34
33
 
35
- def self.require_dir classdir
36
- num_class_hierarchy_levels = self.to_s.split("::").count - 1
37
- root_folder = File.dirname(__FILE__) + "/" + Array.new(num_class_hierarchy_levels).fill("..").join("/")
38
- class_folder = root_folder + "/" + classdir
34
+ def self.require_dir(classdir)
35
+ num_class_hierarchy_levels = to_s.split('::').count - 1
36
+ root_folder = File.dirname(__FILE__) + '/' + Array.new(num_class_hierarchy_levels).fill('..').join('/')
37
+ class_folder = root_folder + '/' + classdir
39
38
  Dir[File.expand_path("#{class_folder}/*.rb")].uniq.each do |file|
40
39
  LoggingHelper.trace "Requiring file: #{file}"
41
40
  require file
42
41
  end
43
42
  end
44
43
 
45
- def self.find_all_subclasses_of args
46
- parent_class = args[ :parent_class ]
44
+ def self.find_all_subclasses_of(args)
45
+ parent_class = args[:parent_class]
47
46
  constants = parent_class.constants
48
47
  candidates = []
49
- constants.each do | candidate |
50
- candidates << candidate.to_s.split('::').last if parent_class.const_get(candidate).class.to_s == "Class"
48
+ constants.each do |candidate|
49
+ candidates << candidate.to_s.split('::').last if parent_class.const_get(candidate).instance_of?(::Class)
51
50
  end
52
51
  candidates
53
52
  end
54
53
 
55
54
  def self.hiera?
56
- "hiera".eql? Eyaml::Options[:source]
55
+ 'hiera'.eql? Eyaml::Options[:source]
57
56
  end
58
57
 
59
- def self.convert_to_utf_8 string
58
+ def self.convert_to_utf_8(string)
60
59
  orig_encoding = string.encoding
61
60
  return string if orig_encoding == Encoding::UTF_8
62
61
 
63
- return string.dup.force_encoding(Encoding::UTF_8)
64
- rescue EncodingError => detail
62
+ string.dup.force_encoding(Encoding::UTF_8)
63
+ rescue EncodingError => e
65
64
  warn "Unable to encode to \"Encoding::UTF_8\" using the original \"#{orig_encoding}\""
66
- return string
65
+ string
67
66
  end
68
67
  end
69
68
  end
@@ -1,14 +1,13 @@
1
1
  class Hiera
2
2
  module Backend
3
3
  module Eyaml
4
-
5
- VERSION = "3.3.0"
6
- DESCRIPTION = "Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties"
4
+ VERSION = '4.0.0'
5
+ DESCRIPTION = 'Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties'
7
6
 
8
7
  class RecoverableError < StandardError
9
8
  end
10
9
 
11
- def self.subcommand= command
10
+ def self.subcommand=(command)
12
11
  @@subcommand = command
13
12
  end
14
13
 
@@ -16,16 +15,16 @@ class Hiera
16
15
  @@subcommand
17
16
  end
18
17
 
19
- def self.default_encryption_scheme= new_encryption
18
+ def self.default_encryption_scheme=(new_encryption)
20
19
  @@default_encryption_scheme = new_encryption
21
20
  end
22
21
 
23
22
  def self.default_encryption_scheme
24
- @@default_encryption_scheme ||= "PKCS7"
23
+ @@default_encryption_scheme ||= 'PKCS7'
25
24
  @@default_encryption_scheme
26
25
  end
27
26
 
28
- def self.verbosity_level= new_verbosity_level
27
+ def self.verbosity_level=(new_verbosity_level)
29
28
  @@debug_level = new_verbosity_level
30
29
  end
31
30
 
@@ -34,14 +33,13 @@ class Hiera
34
33
  @@debug_level
35
34
  end
36
35
 
37
- def self.subcommands= commands
36
+ def self.subcommands=(commands)
38
37
  @@subcommands = commands
39
38
  end
40
39
 
41
40
  def self.subcommands
42
41
  @@subcommands
43
42
  end
44
-
45
43
  end
46
44
  end
47
45
  end
@@ -9,15 +9,14 @@ require 'yaml'
9
9
  class Hiera
10
10
  module Backend
11
11
  class Eyaml_backend
12
-
13
12
  attr_reader :extension
14
13
 
15
14
  def initialize(cache = nil)
16
- debug("Hiera eYAML backend starting")
15
+ debug('Hiera eYAML backend starting')
17
16
 
18
17
  @decrypted_cache = {}
19
18
  @cache = cache || Filecache.new
20
- @extension = Config[:eyaml][:extension] || "eyaml"
19
+ @extension = Config[:eyaml][:extension] || 'eyaml'
21
20
  end
22
21
 
23
22
  def lookup(key, scope, order_override, resolution_type)
@@ -31,7 +30,7 @@ class Hiera
31
30
  debug("Looking for data source #{source}")
32
31
  eyaml_file = Backend.datafile(:eyaml, scope, source, extension) || next
33
32
 
34
- next unless File.exists?(eyaml_file)
33
+ next unless File.exist?(eyaml_file)
35
34
 
36
35
  data = @cache.read(eyaml_file, Hash) do |data|
37
36
  YAML.load(data) || {}
@@ -54,20 +53,28 @@ class Hiera
54
53
  new_answer = parse_answer(data[key], scope)
55
54
  case resolution_type
56
55
  when :array
57
- raise Exception, "Hiera type mismatch: expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
56
+ unless new_answer.is_a? Array or new_answer.is_a? String
57
+ raise Exception,
58
+ "Hiera type mismatch: expected Array and got #{new_answer.class}"
59
+ end
60
+
58
61
  answer ||= []
59
62
  answer << new_answer
60
63
  when :hash
61
- raise Exception, "Hiera type mismatch: expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
64
+ unless new_answer.is_a? Hash
65
+ raise Exception,
66
+ "Hiera type mismatch: expected Hash and got #{new_answer.class}"
67
+ end
68
+
62
69
  answer ||= {}
63
- answer = Backend.merge_answer(new_answer,answer)
70
+ answer = Backend.merge_answer(new_answer, answer)
64
71
  else
65
72
  answer = new_answer
66
73
  break
67
74
  end
68
75
  end
69
76
 
70
- return answer
77
+ answer
71
78
  end
72
79
 
73
80
  private
@@ -78,19 +85,18 @@ class Hiera
78
85
 
79
86
  def decrypt(data)
80
87
  if encrypted?(data)
81
- debug("Attempting to decrypt")
88
+ debug('Attempting to decrypt')
82
89
  begin
83
90
  parser = Eyaml::Parser::ParserFactory.hiera_backend_parser
84
91
  tokens = parser.parse(data)
85
- decrypted = tokens.map{ |token| token.to_plain_text }
92
+ decrypted = tokens.map { |token| token.to_plain_text }
86
93
  plaintext = decrypted.join
87
94
  rescue OpenSSL::PKCS7::PKCS7Error => e
88
- debug("Caught exception: #{e.class}, #{e.message}\n"\
95
+ debug("Caught exception: #{e.class}, #{e.message}\n" \
89
96
  "#{e.backtrace.join("\n")}")
90
- raise "Hiera-eyaml decryption failed, check the "\
91
- "encrypted data matches the key you are using.\n"\
92
- "Raw message from system: #{e.message}"
93
-
97
+ raise 'Hiera-eyaml decryption failed, check the ' \
98
+ "encrypted data matches the key you are using.\n" \
99
+ "Raw message from system: #{e.message}"
94
100
  end
95
101
  plaintext.chomp
96
102
  else
@@ -99,14 +105,14 @@ class Hiera
99
105
  end
100
106
 
101
107
  def encrypted?(data)
102
- /.*ENC\[.*\]/ =~ data ? true : false
108
+ /.*ENC\[.*\]/.match?(data) ? true : false
103
109
  end
104
110
 
105
- def parse_answer(data, scope, extra_data={})
111
+ def parse_answer(data, scope, extra_data = {})
106
112
  if data.is_a?(Numeric) or data.is_a?(TrueClass) or data.is_a?(FalseClass)
107
- return data
113
+ data
108
114
  elsif data.is_a?(String)
109
- return parse_string(data, scope, extra_data)
115
+ parse_string(data, scope, extra_data)
110
116
  elsif data.is_a?(Hash)
111
117
  answer = {}
112
118
  data.each_pair do |key, val|
@@ -114,14 +120,14 @@ class Hiera
114
120
  answer[interpolated_key] = parse_answer(val, scope, extra_data)
115
121
  end
116
122
 
117
- return answer
123
+ answer
118
124
  elsif data.is_a?(Array)
119
125
  answer = []
120
126
  data.each do |item|
121
127
  answer << parse_answer(item, scope, extra_data)
122
128
  end
123
129
 
124
- return answer
130
+ answer
125
131
  end
126
132
  end
127
133
 
@@ -132,18 +138,18 @@ class Hiera
132
138
  debug("Set option: #{key} = #{parsed_value}")
133
139
  end
134
140
 
135
- Eyaml::Options[:source] = "hiera"
141
+ Eyaml::Options[:source] = 'hiera'
136
142
  end
137
143
 
138
- def parse_string(data, scope, extra_data={})
144
+ def parse_string(data, scope, extra_data = {})
139
145
  if Eyaml::Options[:cache_decrypted]
140
- if not @decrypted_cache.include?(data)
146
+ if @decrypted_cache.include?(data)
147
+ debug('Retrieving data from decrypted cache')
148
+ decrypted_data = @decrypted_cache[data]
149
+ else
141
150
  decrypted_data = decrypt(data)
142
- debug("Adding data to decrypted cache")
151
+ debug('Adding data to decrypted cache')
143
152
  @decrypted_cache[data] = decrypted_data
144
- else
145
- debug("Retrieving data from decrypted cache")
146
- decrypted_data = @decrypted_cache[data]
147
153
  end
148
154
  else
149
155
  decrypted_data = decrypt(data)
metadata CHANGED
@@ -1,43 +1,91 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiera-eyaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 4.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vox Pupuli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-20 00:00:00.000000000 Z
11
+ date: 2024-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: highline
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: optimist
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ">="
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '0'
33
+ version: '3.1'
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ">="
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '0'
40
+ version: '3.1'
27
41
  - !ruby/object:Gem::Dependency
28
- name: highline
42
+ name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.2'
31
48
  - - ">="
32
49
  - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
50
+ version: 13.2.1
51
+ type: :development
35
52
  prerelease: false
36
53
  version_requirements: !ruby/object:Gem::Requirement
37
54
  requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '13.2'
38
58
  - - ">="
39
59
  - !ruby/object:Gem::Version
40
- version: '0'
60
+ version: 13.2.1
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec-expectations
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.13'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.13'
75
+ - !ruby/object:Gem::Dependency
76
+ name: voxpupuli-rubocop
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '='
80
+ - !ruby/object:Gem::Version
81
+ version: 2.6.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '='
87
+ - !ruby/object:Gem::Version
88
+ version: 2.6.0
41
89
  description: Hiera backend for decrypting encrypted yaml properties
42
90
  email: voxpupuli@groups.io
43
91
  executables:
@@ -45,9 +93,12 @@ executables:
45
93
  extensions: []
46
94
  extra_rdoc_files: []
47
95
  files:
96
+ - ".github/dependabot.yml"
48
97
  - ".github/workflows/release.yml"
49
98
  - ".github/workflows/test.yml"
50
99
  - ".gitignore"
100
+ - ".rubocop.yml"
101
+ - ".rubocop_todo.yml"
51
102
  - CHANGELOG.md
52
103
  - Gemfile
53
104
  - HISTORY.md
@@ -85,8 +136,6 @@ files:
85
136
  - sublime_text/README.md
86
137
  - sublime_text/eyaml.sublime-package
87
138
  - sublime_text/eyaml.syntax_definition.json
88
- - tools/git_tag_release.rb
89
- - tools/regem.sh
90
139
  homepage: https://github.com/voxpupuli/hiera-eyaml/
91
140
  licenses:
92
141
  - MIT
@@ -99,7 +148,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
148
  requirements:
100
149
  - - ">="
101
150
  - !ruby/object:Gem::Version
102
- version: 2.5.0
151
+ version: '2.7'
103
152
  - - "<"
104
153
  - !ruby/object:Gem::Version
105
154
  version: '4'
@@ -109,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
158
  - !ruby/object:Gem::Version
110
159
  version: '0'
111
160
  requirements: []
112
- rubygems_version: 3.3.7
161
+ rubygems_version: 3.3.27
113
162
  signing_key:
114
163
  specification_version: 4
115
164
  summary: OpenSSL Encryption backend for Hiera
@@ -1,98 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9')
5
- $stderr.puts "This script requires Ruby >= 1.9"
6
- exit 1
7
- end
8
-
9
- require 'open3'
10
- result = Open3.capture3('git rev-parse --show-toplevel')
11
- unless result[2].exitstatus == 0
12
- $stderr.puts "You do not appear to be in a git repository. This script must be run from inside a git repository."
13
- exit 2
14
- end
15
- filename = result[0].lines.first.chomp + '/CHANGES.md'
16
- unless File.exist?(filename)
17
- $stderr.puts "CHANGES.md not found. Please ensure that CHANGES.md exists."
18
- exit 3
19
- end
20
- contents = IO.read(filename)
21
-
22
- lines = contents.lines.drop(3).map(&:chomp).reject(&:empty?)
23
- versions = Hash.new
24
- currentversion = nil
25
- versions[nil] = []
26
- lines.each_with_index do |line, index|
27
- if line =~ /\A-+\z/
28
- versions[currentversion].pop
29
- currentversion = lines[index-1]
30
- versions[currentversion] = []
31
- else
32
- versions[currentversion] << line
33
- end
34
- end
35
- versions.delete(nil)
36
-
37
- def prompt(*args)
38
- print(*args)
39
- gets.chomp
40
- end
41
-
42
- newest = versions.first[0]
43
- version = prompt "Version [#{newest}]: "
44
- version = newest if version.empty?
45
-
46
- unless versions[version]
47
- $stderr.puts "Version #{version} is invalid. Valid versions are: #{versions.keys.join(', ')}"
48
- exit 4
49
- end
50
-
51
- tagname = "v#{version}"
52
-
53
-
54
-
55
- result = Open3.capture3("git rev-parse #{tagname}")
56
- if result[2].exitstatus == 0
57
- $stderr.puts "Tag #{tagname} already exists."
58
- exit 5
59
- end
60
-
61
- commit = prompt "Commit: "
62
-
63
- result = Open3.capture3("git --no-pager log -1 #{commit} --format='%ci'")
64
- unless result[2].exitstatus == 0
65
- $stderr.puts "Commit '#{commit}' is not valid."
66
- exit result[2].exitstatus
67
- end
68
- commitdate = result[0].lines.first.chomp
69
-
70
- def word_wrap(line, width)
71
- first_prefix = line.match(/([ -]*)/)[1]
72
- prefix = ' ' * first_prefix.size
73
- real_width = width - (prefix.size * 2)
74
- line[prefix.size..-1].gsub(/(^)?(.{1,#{real_width}})(?: +|$)/) { |s| $1 ? "#{first_prefix}#{s}\n" : "#{prefix}#{s}\n" }
75
- end
76
-
77
- require 'tempfile'
78
- begin
79
- tf = Tempfile.new('tag-message')
80
- tf.puts "Version #{version} release"
81
- tf.puts ""
82
- tf.puts "Changes:"
83
- versions[version].each do |line|
84
- tf.puts word_wrap(line, 80)
85
- end
86
- tf.flush
87
-
88
- result = Open3.capture3({'GIT_COMMITTER_DATE' => commitdate}, "git tag -a #{tagname} #{commit} -F #{tf.path}")
89
- $stderr.puts result[1]
90
- if result[2].exitstatus == 0
91
- system "git --no-pager show #{tagname} --no-patch"
92
- puts ""
93
- puts "Tag created. Please push to GitHub with `git push origin #{tagname}`."
94
- end
95
- exit result[2].exitstatus
96
- ensure
97
- tf.close!
98
- end
data/tools/regem.sh DELETED
@@ -1,11 +0,0 @@
1
- #!/bin/sh
2
-
3
- # ToDo: Remove as 'rake install' task will build and install the latest gem?
4
-
5
- gem uninstall hiera-eyaml --executables
6
- RAKE_OUT=`rake build`
7
- echo ${RAKE_OUT}
8
- VERSION=`echo ${RAKE_OUT} | awk '{print $2}'`
9
- echo Installing version: ${VERSION} ...
10
- gem install pkg/hiera-eyaml-${VERSION}.gem
11
- eyaml version