manageiq-password 1.0.0 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a506e65c484778a8b89cc16300e5145922de810e612499fe5046015e8668915
4
- data.tar.gz: 5322663567882ef7b24f4275d9a6f21e1d967bd086de0afe64dcdf45d67e868d
3
+ metadata.gz: 169673824deb748589d388452d71ade309bf678d35a30be8e88493cdfd9058c7
4
+ data.tar.gz: 49c0b253a7ec7a1212ebce03d2e83f3b407b6e6bcad0c49d44cb4889e5968cb2
5
5
  SHA512:
6
- metadata.gz: 3ea27faaef7f610f5f07f67e19c1b27739c43f418f9662cfbf558d6a05168f0002b8697a1ec782b540b29b99e67a9d25996b03e1ad5cf9044d3644b5b3aaa9cb
7
- data.tar.gz: 4b5e896206731cdd5895b1a90165c69af0bbdd789bf86509e2d4e1568a7a3437b794e043094a9183d09612717a67b278b5d32733523e3652698abcb637dd5ad0
6
+ metadata.gz: 0b72cf25be15763836db8d0779da31bb69c45116a44602a61ad4a7bece0083ae57d60c59fe4c295f26c059c4d1b1c01181efce56fb25ad45d2f731095410f77f
7
+ data.tar.gz: ca33b0b6939a2a8671f04905ab00d2ba4c48bcc7b7a48611f968fa3f626a25b08f4b21a8b9e3c285c54410820c3432f44aab0153dd62094bb20da67f881f5ce6
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  language: ruby
3
+ dist: bionic
3
4
  cache: bundler
4
5
  rvm:
5
6
  - 2.6.7
data/CHANGELOG.md CHANGED
@@ -4,6 +4,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.1.0] - 2021-11-08
8
+ ### Added
9
+ - Add manageiq-password CLI [[#23](https://github.com/ManageIQ/manageiq-password/pull/23)]
10
+
11
+ ### Fixed
12
+ - chmod v2_key on creation [[#22](https://github.com/ManageIQ/manageiq-password/pull/22)]
13
+ - Raise an exception when decrypting plaintext [[#26](https://github.com/ManageIQ/manageiq-password/pull/26)]
14
+ - Fix encrypted? and try_decrypt to work with erb strings [[#28](https://github.com/ManageIQ/manageiq-password/pull/28)]
15
+
7
16
  ## [1.0.0] - 2021-05-05
8
17
  ### Removed
9
18
  - **BREAKING**: Drop support for legacy v0 and v1 keys [[#14](https://github.com/ManageIQ/manageiq-password/pull/14)]
@@ -13,5 +22,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).
13
22
  key
14
23
  - **BREAKING**: Drop deprecated methods [[#16](https://github.com/ManageIQ/manageiq-password/pull/16)]
15
24
 
16
- [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v1.0.0...HEAD
25
+ [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v1.1.0...HEAD
26
+ [1.1.0]: https://github.com/ManageIQ/more_core_extensions/compare/v1.1.0...v1.0.0
17
27
  [1.0.0]: https://github.com/ManageIQ/more_core_extensions/compare/v1.0.0...v0.3.0
@@ -0,0 +1,100 @@
1
+ #!/bin/bash
2
+
3
+ while [[ "$#" -gt 0 ]]; do
4
+ case $1 in
5
+ -d|--decrypt)
6
+ mode="decrypt"
7
+ ;;
8
+ -e|--encrypt)
9
+ mode="encrypt"
10
+ ;;
11
+ -k|--key)
12
+ keyfile="$2"
13
+ shift
14
+ ;;
15
+ -h|--help|-?)
16
+ cat <<-EOS >&2
17
+ Usage: $(basename $0) [--encrypt|--decrypt] [--key KEYFILE]
18
+
19
+ Options:
20
+ -d, --decrypt Decrypt the value on STDIN (default mode)
21
+ -e, --encrypt Encrypt the value on STDIN
22
+ -k, --key Path to the key file (default: $(pwd)/certs/v2_key)
23
+
24
+ -h, --help, -? Display help
25
+ EOS
26
+ exit 0
27
+ ;;
28
+ *)
29
+ echo "ERROR: Unknown parameter passed: $1" >&2
30
+ exit 1
31
+ ;;
32
+ esac
33
+ shift
34
+ done
35
+
36
+ mode=${mode:-"decrypt"}
37
+ keyfile=${keyfile:-"$(pwd)/certs/v2_key"}
38
+
39
+ if [ ! -r "$keyfile" ]; then
40
+ echo "ERROR: Cannot read v2 key file: $keyfile" >&2
41
+ exit 1
42
+ fi
43
+
44
+ extractFromKeyfile() {
45
+ grep :$1: "$keyfile" | cut -d ' ' -f 2
46
+ }
47
+
48
+ extractAlgorithm() {
49
+ extractFromKeyfile "algorithm"
50
+ }
51
+
52
+ extractKey() {
53
+ extractFromKeyfile "key" | base64 -d | xxd -p -c256
54
+ }
55
+
56
+ extractIv() {
57
+ iv=$(extractFromKeyfile "iv" | base64 -d | xxd -p -c256)
58
+ echo -n "${iv:-"00000000000000000000000000000000"}"
59
+ }
60
+
61
+ algorithm=$(extractAlgorithm)
62
+ if [ "$algorithm" != "aes-256-cbc" ]; then
63
+ echo "ERROR: Invalid v2 key file: $keyfile" >&2
64
+ exit 1
65
+ fi
66
+
67
+ if [ -n "$DEBUG" ]; then
68
+ cat <<-EOS >&2
69
+ ==============================================================================
70
+ Mode: $mode
71
+ Key File: $keyfile
72
+ Algorithm: $algorithm
73
+ IV (Base64): $(extractFromKeyfile "iv")
74
+ IV (Hex): $(extractIv)
75
+ Key (Base64): $(extractFromKeyfile "key")
76
+ Key (Hex): $(extractKey)
77
+ ==============================================================================
78
+ EOS
79
+ fi
80
+
81
+ case $mode in
82
+ decrypt)
83
+ (
84
+ xargs -L1 echo | \
85
+ sed 's/^.\{4\}//;s/.$//' | \
86
+ openssl enc -d -base64 -$algorithm -iv "$(extractIv)" -K "$(extractKey)"
87
+ ) < /dev/stdin
88
+ ;;
89
+ encrypt)
90
+ (
91
+ xargs -L1 echo -n | \
92
+ openssl enc -base64 -$algorithm -iv "$(extractIv)" -K "$(extractKey)" | \
93
+ sed "s/^/v2:{/;s/$/}/" | \
94
+ xargs -L1 echo -n
95
+ ) < /dev/stdin
96
+ ;;
97
+ *)
98
+ echo "ERROR: Invalid mode: $mode" >&2
99
+ exit 1
100
+ esac
@@ -1,5 +1,5 @@
1
1
  module ManageIQ
2
2
  class Password
3
- VERSION = "1.0.0".freeze
3
+ VERSION = "1.1.0".freeze
4
4
  end
5
5
  end
@@ -22,15 +22,32 @@ module ManageIQ
22
22
  @encStr = encrypt(str)
23
23
  end
24
24
 
25
- def encrypt(str, key = self.class.key)
25
+ def encrypt(*args)
26
+ self.class.encrypt(*args)
27
+ end
28
+
29
+ def decrypt(*args)
30
+ self.class.decrypt(*args)
31
+ end
32
+
33
+ def recrypt(*args)
34
+ self.class.recrypt(*args)
35
+ end
36
+
37
+ def self.encrypt(str, key = self.key)
26
38
  return str if str.nil?
27
39
 
28
40
  enc = key.encrypt64(str).delete("\n") unless str.empty?
29
- self.class.wrap(enc)
41
+ wrap(enc)
30
42
  end
31
43
 
32
- def decrypt(str, key = self.class.key)
33
- enc = self.class.unwrap(str)
44
+ def self.decrypt(str, key = self.key)
45
+ str = remove_erb(str)
46
+ return str if str.nil? || str.empty?
47
+
48
+ raise PasswordError, "cannot decrypt plaintext string" unless wrapped?(str)
49
+
50
+ enc = unwrap(str)
34
51
  return enc if enc.nil? || enc.empty?
35
52
 
36
53
  begin
@@ -40,7 +57,7 @@ module ManageIQ
40
57
  end
41
58
  end
42
59
 
43
- def recrypt(str, prior_key = nil)
60
+ def self.recrypt(str, prior_key = nil)
44
61
  return str if str.nil?
45
62
 
46
63
  decrypted_str = decrypt(str, prior_key) if prior_key rescue nil
@@ -48,21 +65,8 @@ module ManageIQ
48
65
  encrypt(decrypted_str)
49
66
  end
50
67
 
51
- def self.encrypt(*args)
52
- new.encrypt(*args)
53
- end
54
-
55
- def self.decrypt(*args)
56
- new.decrypt(*args)
57
- end
58
-
59
- def self.recrypt(*args)
60
- new.recrypt(*args)
61
- end
62
-
63
68
  def self.encrypted?(str)
64
- return false if str.nil? || str.empty?
65
- !!unwrap(str)
69
+ wrapped?(remove_erb(str))
66
70
  end
67
71
 
68
72
  def self.md5crypt(str)
@@ -83,6 +87,7 @@ module ManageIQ
83
87
  end
84
88
 
85
89
  def self.try_decrypt(str)
90
+ str = remove_erb(str)
86
91
  encrypted?(str) ? decrypt(str) : str
87
92
  end
88
93
 
@@ -124,26 +129,27 @@ module ManageIQ
124
129
  Key.new.tap { |key| store_key_file(filename, key) if filename }
125
130
  end
126
131
 
127
- protected
128
-
129
- def self.wrap(encrypted_str)
132
+ private_class_method def self.wrap(encrypted_str)
130
133
  "v2:{#{encrypted_str}}"
131
134
  end
132
135
 
133
- def self.unwrap(str)
134
- _unwrap(str) || _unwrap(extract_erb_encrypted_value(str))
135
- end
136
-
137
- private_class_method def self._unwrap(str)
136
+ private_class_method def self.unwrap(str)
138
137
  return str if str.nil? || str.empty?
138
+
139
139
  str.match(REGEXP_START_LINE)&.public_send(:[], 1)
140
140
  end
141
141
 
142
- def self.store_key_file(filename, key)
143
- File.write(filename, key.to_h.to_yaml)
142
+ private_class_method def self.wrapped?(str)
143
+ return false if str.nil? || str.empty?
144
+
145
+ str.match?(REGEXP_START_LINE)
146
+ end
147
+
148
+ private_class_method def self.store_key_file(filename, key)
149
+ File.write(filename, key.to_h.to_yaml, :perm => 0440)
144
150
  end
145
151
 
146
- def self.load_key_file(filename)
152
+ private_class_method def self.load_key_file(filename)
147
153
  return filename if filename.respond_to?(:decrypt64)
148
154
 
149
155
  # if it is an absolute path, or relative to pwd, leave as is
@@ -154,8 +160,11 @@ module ManageIQ
154
160
  Key.new(*YAML.load_file(filename).values_at(:algorithm, :key, :iv))
155
161
  end
156
162
 
157
- def self.extract_erb_encrypted_value(value)
158
- return $1 if value =~ /\A<%= (?:MiqPassword|DB_PASSWORD|ManageIQ::Password)\.decrypt\(['"]([^'"]+)['"]\) %>\Z/
163
+ private_class_method def self.remove_erb(str)
164
+ return str if str.nil? || str.empty? || !str.start_with?("<%=")
165
+
166
+ match = str.match(/\A<%= (?:MiqPassword|DB_PASSWORD|ManageIQ::Password)\.decrypt\(['"](.+?)['"]\) %>\Z/m)
167
+ match ? match[1] : str
159
168
  end
160
169
 
161
170
  class Key
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
+ spec.add_development_dependency "awesome_spawn"
21
22
  spec.add_development_dependency "bundler"
22
23
  spec.add_development_dependency "manageiq-style"
23
24
  spec.add_development_dependency "rake", ">= 12.3.3"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manageiq-password
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Authors
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-06 00:00:00.000000000 Z
11
+ date: 2021-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: awesome_spawn
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +96,8 @@ dependencies:
82
96
  version: '0'
83
97
  description:
84
98
  email:
85
- executables: []
99
+ executables:
100
+ - manageiq-password
86
101
  extensions: []
87
102
  extra_rdoc_files: []
88
103
  files:
@@ -101,6 +116,7 @@ files:
101
116
  - Rakefile
102
117
  - bin/console
103
118
  - bin/setup
119
+ - exe/manageiq-password
104
120
  - lib/manageiq-password.rb
105
121
  - lib/manageiq/password.rb
106
122
  - lib/manageiq/password/password_mixin.rb
@@ -128,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
144
  - !ruby/object:Gem::Version
129
145
  version: '0'
130
146
  requirements: []
131
- rubygems_version: 3.1.4
147
+ rubygems_version: 3.1.6
132
148
  signing_key:
133
149
  specification_version: 4
134
150
  summary: A simple encryption util for storing passwords in a database.