secure_data_bag 2.2.0 → 3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +165 -46
- data/Rakefile +1 -2
- data/lib/chef/config.rb +2 -4
- data/lib/chef/dsl/data_query.rb +1 -2
- data/lib/chef/knife/secure_bag_edit.rb +31 -33
- data/lib/chef/knife/secure_bag_from_file.rb +13 -22
- data/lib/chef/knife/secure_bag_open.rb +37 -0
- data/lib/chef/knife/secure_bag_show.rb +40 -35
- data/lib/chef/knife/secure_data_bag/base_mixin.rb +80 -0
- data/lib/chef/knife/secure_data_bag/defaults_mixin.rb +32 -0
- data/lib/chef/knife/secure_data_bag/export_mixin.rb +85 -0
- data/lib/chef/knife/secure_data_bag/secrets_mixin.rb +57 -0
- data/lib/secure_data_bag.rb +5 -7
- data/lib/secure_data_bag/check_encrypted.rb +29 -0
- data/lib/secure_data_bag/constants.rb +5 -0
- data/lib/secure_data_bag/decryptor.rb +149 -0
- data/lib/secure_data_bag/dsl/data_query.rb +6 -6
- data/lib/secure_data_bag/encryptor.rb +185 -0
- data/lib/secure_data_bag/exceptions.rb +4 -0
- data/lib/secure_data_bag/item.rb +197 -149
- data/lib/secure_data_bag/version.rb +1 -3
- data/secure_data_bag.gemspec +14 -13
- data/spec/item_spec.rb +15 -16
- data/spec/spec_helper.rb +0 -1
- metadata +112 -7
- data/lib/chef/knife/secure_bag_base.rb +0 -74
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef/knife/data_bag_show'
|
3
|
+
require_relative 'secure_data_bag/base_mixin'
|
4
|
+
require_relative 'secure_data_bag/export_mixin'
|
5
|
+
require_relative 'secure_data_bag/secrets_mixin'
|
6
|
+
|
7
|
+
class Chef
|
8
|
+
class Knife
|
9
|
+
class SecureBagOpen < Knife::DataBagShow
|
10
|
+
include SecureDataBag::BaseMixin
|
11
|
+
include SecureDataBag::SecretsMixin
|
12
|
+
|
13
|
+
banner 'knife secure bag open PATH'
|
14
|
+
category 'secure bag'
|
15
|
+
|
16
|
+
def run
|
17
|
+
unless ::File.exist?(@name_args[0])
|
18
|
+
ui.fatal('File not found.')
|
19
|
+
show_usage
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
display_metadata = config_metadata.dup
|
24
|
+
display_metadata[:encryption_format] ||= 'plain'
|
25
|
+
|
26
|
+
data = File.read(@name_args[0])
|
27
|
+
data = JSON.parse(data)
|
28
|
+
item = create_item('local', @name_args[0], data, display_metadata)
|
29
|
+
|
30
|
+
display_data = item.to_hash(metadata: true)
|
31
|
+
display_data = format_for_display(display_data)
|
32
|
+
|
33
|
+
output(display_data)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,46 +1,51 @@
|
|
1
|
-
|
2
|
-
require 'chef/knife/secure_bag_base'
|
3
1
|
require 'chef/knife/data_bag_show'
|
2
|
+
require_relative 'secure_data_bag/base_mixin'
|
3
|
+
require_relative 'secure_data_bag/export_mixin'
|
4
|
+
require_relative 'secure_data_bag/secrets_mixin'
|
5
|
+
require_relative 'secure_data_bag/defaults_mixin'
|
4
6
|
|
5
7
|
class Chef
|
6
8
|
class Knife
|
7
9
|
class SecureBagShow < Knife::DataBagShow
|
8
|
-
include
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
boolean: true,
|
16
|
-
description: "Whether we wish to display encoded values",
|
17
|
-
default: false
|
18
|
-
|
19
|
-
def load_item(bag, item_name)
|
20
|
-
item = SecureDataBag::Item.load(bag, item_name,
|
21
|
-
key: read_secret,
|
22
|
-
fields: encoded_fields
|
23
|
-
)
|
24
|
-
|
25
|
-
data = item.to_hash(encoded: config[:encoded])
|
26
|
-
data["_encoded_fields"] = item.encoded_fields
|
27
|
-
data
|
28
|
-
end
|
10
|
+
include SecureDataBag::BaseMixin
|
11
|
+
include SecureDataBag::ExportMixin
|
12
|
+
include SecureDataBag::SecretsMixin
|
13
|
+
include SecureDataBag::DefaultsMixin
|
14
|
+
|
15
|
+
banner 'knife secure bag show BAG [ITEM] (options)'
|
16
|
+
category 'secure bag'
|
29
17
|
|
30
18
|
def run
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
19
|
+
case @name_args.length
|
20
|
+
when 2
|
21
|
+
run_show
|
22
|
+
when 1
|
23
|
+
run_list
|
24
|
+
else
|
25
|
+
stdout.puts opt_parser
|
26
|
+
exit(1)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def run_show
|
31
|
+
config_defaults_for_data_bag!(@name_args[0])
|
32
|
+
|
33
|
+
display_metadata = config_metadata.dup
|
34
|
+
display_metadata[:encryption_format] ||= 'plain'
|
35
|
+
|
36
|
+
item = load_item(@name_args[0], @name_args[1], display_metadata)
|
37
|
+
data = item.to_hash(metadata: true)
|
38
|
+
data = format_for_display(data)
|
39
|
+
|
40
|
+
export!(@name_args[0], @name_args[1], item) if should_export?
|
41
|
+
output(data)
|
42
|
+
end
|
43
|
+
|
44
|
+
def run_list
|
45
|
+
data = Chef::DataBag.load(@name_args[0])
|
46
|
+
data = format_list_for_display(data)
|
47
|
+
output(data)
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
46
|
-
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
module SecureDataBag
|
6
|
+
module BaseMixin
|
7
|
+
# Steps to execute when the mixin is include.
|
8
|
+
# In this case specifically, add additional command line options
|
9
|
+
# related to exporting.
|
10
|
+
# @since 3.0.0
|
11
|
+
def self.included(base)
|
12
|
+
base.deps do
|
13
|
+
require 'secure_data_bag'
|
14
|
+
end
|
15
|
+
|
16
|
+
base.option :encryption_format,
|
17
|
+
description: 'The format with which to encrypt data. If unset, it will be autodetected.',
|
18
|
+
long: '--enc-format [plain|encrypted|nested]'
|
19
|
+
|
20
|
+
base.option :decryption_format,
|
21
|
+
description: 'The format with which to decrypt data. If unset, it will be autodetected.',
|
22
|
+
long: '--dec-format [plain|encrypted|nested]'
|
23
|
+
|
24
|
+
base.option :encrypted_keys,
|
25
|
+
description: 'Comma delimited list of keys which should be encrypted, in addition to what was previously there',
|
26
|
+
long: '--enc-keys FIELD1,FIELD2,FIELD3',
|
27
|
+
proc: proc { |s| s.split(',') }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Metadata to use when interacting with SecureDataBag containing
|
31
|
+
# overrides specified on the command-line.
|
32
|
+
# @since 3.0.0
|
33
|
+
def config_metadata
|
34
|
+
Mash.new(
|
35
|
+
encryption_format: config[:encryption_format],
|
36
|
+
decryption_format: config[:decryption_format],
|
37
|
+
encrypted_keys: encrypted_keys,
|
38
|
+
secret: secret
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Load a data_bag_item from Chef Server
|
43
|
+
# @param data_bag [String] the data_bag to load from
|
44
|
+
# @param item_name [String] the data_bag_item name to load
|
45
|
+
# @param metadata [Hash] the optional metadata to pass to ::Item
|
46
|
+
# @return [SecureDataBag::Item]
|
47
|
+
# @since 3.0.0
|
48
|
+
def load_item(data_bag, item_name, metadata = {})
|
49
|
+
item = ::SecureDataBag::Item.load(data_bag, item_name, metadata)
|
50
|
+
item
|
51
|
+
end
|
52
|
+
|
53
|
+
# Create a new data_bag_item
|
54
|
+
# @param data_bag [String] the data_bag to load from
|
55
|
+
# @param item_name [String] the data_bag_item name to load
|
56
|
+
# @param data [Hash] the optional raw_data to use
|
57
|
+
# @param metadata [Hash] the optional metadata to pass to ::Item
|
58
|
+
# @return [SecureDataBag::Item]
|
59
|
+
# @since 3.0.0
|
60
|
+
def create_item(data_bag, item_name, data = {}, metadata = {})
|
61
|
+
item = ::SecureDataBag::Item.new(metadata)
|
62
|
+
item.raw_data = { 'id' => item_name }.merge(data)
|
63
|
+
item.data_bag data_bag
|
64
|
+
item
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Keys to encrypt which are a result of merging the arrays found within
|
70
|
+
# the the configuration file and provided over the command-line.
|
71
|
+
# @since 3.0.0
|
72
|
+
def encrypted_keys
|
73
|
+
Array(config[:encrypted_keys]).concat(
|
74
|
+
Array(Chef::Config[:knife][:secure_data_bag][:encrypted_keys])
|
75
|
+
).uniq
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
module SecureDataBag
|
6
|
+
module DefaultsMixin
|
7
|
+
# Apply Knife config values defined in knife.rb
|
8
|
+
# @param data_bag [String] the data_bag name
|
9
|
+
# @since 3.0.0
|
10
|
+
def config_defaults_for_data_bag!(data_bag)
|
11
|
+
config_defaults_for_data_bags(data_bag).each do |key, value|
|
12
|
+
if options.key?(key.to_sym)
|
13
|
+
config[key.to_sym] ||= value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# Defaults configuration hash for a specific data_bag
|
21
|
+
# @param data_bag [String] the data_bag name
|
22
|
+
# @return [Hash] the configuration hash
|
23
|
+
# @since 3.0.0
|
24
|
+
def config_defaults_for_data_bags(data_bag)
|
25
|
+
defaults = Chef::Config[:knife][:secure_data_bag] || {}
|
26
|
+
defaults = defaults[:defaults] || {}
|
27
|
+
defaults[data_bag.to_sym] || {}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
class Chef
|
4
|
+
class Knife
|
5
|
+
module SecureDataBag
|
6
|
+
module ExportMixin
|
7
|
+
# Steps to execute when the mixin is include.
|
8
|
+
# In this case specifically, add additional command line options
|
9
|
+
# related to exporting.
|
10
|
+
# @since 3.0.0
|
11
|
+
def self.included(base)
|
12
|
+
base.option :export,
|
13
|
+
description: 'Whether to export the data_bag item',
|
14
|
+
long: '--export',
|
15
|
+
boolean: true
|
16
|
+
|
17
|
+
base.option :export_format,
|
18
|
+
description: 'Format to export the data_bag_item as. If unset, this will default to the encryption format.',
|
19
|
+
long: '--export-format'
|
20
|
+
|
21
|
+
base.option :export_root,
|
22
|
+
long: '--export-root PATH',
|
23
|
+
description: 'Path containing data_bag folders and items'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Should knife subcommands save data_bag_items to disk after uploading
|
27
|
+
# them to the Chef server.
|
28
|
+
# @returns [Boolean]
|
29
|
+
# @since 3.0.0
|
30
|
+
def should_export?
|
31
|
+
if config[:export].nil?
|
32
|
+
Chef::Config[:knife][:secure_data_bag][:export_on_upload]
|
33
|
+
else
|
34
|
+
config[:export]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Export the item to the filesystem.
|
39
|
+
# @param data_bag [String] the data_bag to upload to
|
40
|
+
# @param item_name [String] the data_bag_item id to upload to
|
41
|
+
# @param item [SecureDataBag::Item] the item to upload
|
42
|
+
# @since 3.0.0
|
43
|
+
def export!(data_bag, item_name, item)
|
44
|
+
item.encryption_format = export_format
|
45
|
+
data = item.to_hash
|
46
|
+
|
47
|
+
if export_root.nil?
|
48
|
+
ui.fatal('Export root is not defined')
|
49
|
+
show_usage
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
|
53
|
+
export_file_path = export_path(data_bag, item_name)
|
54
|
+
unless ::File.directory?(::File.dirname(export_file_path))
|
55
|
+
ui.fatal("Export directory does not exist: #{export_file_path}")
|
56
|
+
show_usage
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
|
60
|
+
::File.open(export_file_path, 'w') do |f|
|
61
|
+
f.write(Chef::JSONCompat.to_json_pretty(data))
|
62
|
+
end
|
63
|
+
|
64
|
+
display_path = export_file_path.sub(%r{/^#{export_root}/}, '')
|
65
|
+
stdout.puts("Exported to #{display_path}")
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def export_root
|
71
|
+
config[:export_root] ||
|
72
|
+
Chef::Config[:knife][:secure_data_bag][:export_root]
|
73
|
+
end
|
74
|
+
|
75
|
+
def export_path(data_bag, item_name)
|
76
|
+
::File.join(export_root, data_bag, item_name) + '.json'
|
77
|
+
end
|
78
|
+
|
79
|
+
def export_format
|
80
|
+
config[:export_format]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Chef
|
2
|
+
class Knife
|
3
|
+
module SecureDataBag
|
4
|
+
module SecretsMixin
|
5
|
+
# Steps to execute when the mixin is include.
|
6
|
+
# In this case specifically, add additional command line options
|
7
|
+
# related to exporting.
|
8
|
+
# @since 3.0.0
|
9
|
+
def self.included(base)
|
10
|
+
base.option :secret,
|
11
|
+
description: 'The secret key used to (de)encrypt data bag item values',
|
12
|
+
short: '-s SECRET',
|
13
|
+
long: '--secret '
|
14
|
+
|
15
|
+
base.option :secret_file,
|
16
|
+
description: 'The secret key file used to (de)encrypt data bag item values',
|
17
|
+
long: '--secret-file SECRET_FILE'
|
18
|
+
end
|
19
|
+
|
20
|
+
# The shared secret used to encrypt / decrypt data bag items
|
21
|
+
# @return [String] the shared secret
|
22
|
+
# @since 3.0.0
|
23
|
+
def secret
|
24
|
+
@secret ||= begin
|
25
|
+
secret = load_secret
|
26
|
+
unless secret
|
27
|
+
ui.fatal('A secret or secret_file must be specified')
|
28
|
+
show_usage
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
secret
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Path to the secret_file
|
38
|
+
# @return [String]
|
39
|
+
# @since 3.0.0
|
40
|
+
def secret_file
|
41
|
+
config[:secret_file] ||
|
42
|
+
Chef::Config[:knife][:secure_data_bag][:secret_file]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Load the shared secret, either from command line parameters or from
|
46
|
+
# a file on the filesystem.
|
47
|
+
# @return [String] the shared secret
|
48
|
+
# @since 3.0.0
|
49
|
+
def load_secret
|
50
|
+
if config[:secret] then config[:secret]
|
51
|
+
else ::SecureDataBag::Item.load_secret(secret_file)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/secure_data_bag.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
+
require 'secure_data_bag/version'
|
2
|
+
require 'secure_data_bag/item'
|
3
|
+
require 'secure_data_bag/dsl/data_query'
|
1
4
|
|
2
|
-
|
3
|
-
|
4
|
-
require "secure_data_bag/dsl/data_query"
|
5
|
-
|
6
|
-
require_relative "chef/config"
|
7
|
-
require_relative "chef/dsl/data_query"
|
8
|
-
|
5
|
+
require_relative 'chef/config'
|
6
|
+
require_relative 'chef/dsl/data_query'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'chef/encrypted_data_bag_item/check_encrypted'
|
2
|
+
|
3
|
+
module SecureDataBag
|
4
|
+
# Common code for checking if a data bag appears encrypted
|
5
|
+
module CheckEncrypted
|
6
|
+
include Chef::EncryptedDataBagItem::CheckEncrypted
|
7
|
+
|
8
|
+
# Autodetect whether the item's raw hash appears to be encrypted
|
9
|
+
def partially_encrypted?(raw_data)
|
10
|
+
data = raw_data.reject { |k, _| k == 'id' }
|
11
|
+
|
12
|
+
# Detect whether any of the raw hash keys, or their nested structures
|
13
|
+
# contain encrypted values.
|
14
|
+
data.any? do |_, v|
|
15
|
+
looks_like_partially_encrypted?(v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Chef if any of the nested data structures look like they have been
|
22
|
+
# encrypted in a manner compatible with
|
23
|
+
# Chef::EncryptedDataBagItem::Encryptor::VersionXEncryptor.
|
24
|
+
def looks_like_partially_encrypted?(data)
|
25
|
+
return false unless data.is_a?(Hash)
|
26
|
+
looks_like_encrypted?(data) || partially_encrypted?(data)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'secure_data_bag/constants'
|
2
|
+
require 'secure_data_bag/check_encrypted'
|
3
|
+
|
4
|
+
module SecureDataBag
|
5
|
+
module Decryptor
|
6
|
+
# Instantiate an Decryptor object responsable for decrypting the
|
7
|
+
# encrypted_hash with the secret. As much as possible, this method will
|
8
|
+
# attempt to auto-detect the item format to ensure compatibility.
|
9
|
+
#
|
10
|
+
# Much like with upstream, call #for_encrypted_item on the resulting
|
11
|
+
# object to decrypt and deserialize it.
|
12
|
+
#
|
13
|
+
# @param encrypted_hash [Hash] the encrypted hash to decrypt
|
14
|
+
# @param secret [String]
|
15
|
+
# @param metadata [Hash] the optional metdata to configure the decryptor
|
16
|
+
# @return [SecureDataBag::NestedDecryptor] the object capable of decrypting
|
17
|
+
# @since 3.0.0
|
18
|
+
def self.for(encrypted_hash, secret, metadata = {})
|
19
|
+
metadata = Mash.new(metadata)
|
20
|
+
NestedDecryptor.new(encrypted_hash, secret, metadata)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Decryptor object responsable for decrypting the encrypted_hash with the
|
25
|
+
# secret. This functions similarly, to how
|
26
|
+
# Chef::EncryptedDataBagItem::Decryptor does, with the caveat that this
|
27
|
+
# is meant to decrypt entire objects and not single values.
|
28
|
+
#
|
29
|
+
# @since 3.0.0
|
30
|
+
class NestedDecryptor
|
31
|
+
include SecureDataBag::CheckEncrypted
|
32
|
+
|
33
|
+
# The encrypted hash received
|
34
|
+
# @since 3.0.0
|
35
|
+
attr_reader :encrypted_hash
|
36
|
+
|
37
|
+
# The keys found that had to be decrypted in the hash
|
38
|
+
# @since 3.0.0
|
39
|
+
attr_reader :decrypted_keys
|
40
|
+
|
41
|
+
# The decrypted hash
|
42
|
+
# @since 3.0.0
|
43
|
+
attr_reader :decrypted_hash
|
44
|
+
|
45
|
+
# The format of this DataBagItem.
|
46
|
+
# May be one of:
|
47
|
+
# - encrypted refers to an EncryptedDataBagItem
|
48
|
+
# - nested refers to a SecureDataBagItem with nested values
|
49
|
+
# - plain refers to a plain DataBagItem
|
50
|
+
# @since 3.0.0
|
51
|
+
attr_reader :format
|
52
|
+
|
53
|
+
# Initializer
|
54
|
+
# @param encrypted_hash [Hash,String] the encrypted hash to decrypt
|
55
|
+
# @param secret [String] the secret to decrypt with
|
56
|
+
# @param metadata [Hash] the optional metdata to configure the decryptor
|
57
|
+
# @since 3.0.0
|
58
|
+
def initialize(encrypted_hash, secret, metadata = {})
|
59
|
+
@secret = secret
|
60
|
+
|
61
|
+
@decrypted_keys = []
|
62
|
+
@encrypted_hash = encrypted_hash
|
63
|
+
@decrypted_hash = {}
|
64
|
+
|
65
|
+
@format = metadata[:decryption_format] ||
|
66
|
+
if @encrypted_hash.key?(SecureDataBag::METADATA_KEY)
|
67
|
+
'nested'
|
68
|
+
elsif encrypted?(@encrypted_hash)
|
69
|
+
'encrypted'
|
70
|
+
elsif partially_encrypted?(@encrypted_hash)
|
71
|
+
'nested'
|
72
|
+
else
|
73
|
+
'plain'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Method called to decrypt the data structure and return it.
|
78
|
+
# @return [Mix] the unencrypted value
|
79
|
+
# @since 3.0.0
|
80
|
+
def decrypt!
|
81
|
+
@decrypted_hash = decrypt
|
82
|
+
end
|
83
|
+
|
84
|
+
# Method called to decrypt the data structure and return it.
|
85
|
+
# @return [Mix] the unencrypted value
|
86
|
+
# @since 3.0.0
|
87
|
+
def decrypt
|
88
|
+
decrypt_data(@encrypted_hash)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Method name preserved for compatibility with
|
92
|
+
# Chef::EncryptedDataBagItem::Decryptor.
|
93
|
+
# @since 3.0.0
|
94
|
+
alias :for_decrypted_item :decrypt!
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# Decrypt a possibly encrypted value
|
99
|
+
# @param raw_hash [Hash] a potentially encrypted hash
|
100
|
+
# @return [Hash] the unencrypted value
|
101
|
+
# @since 3.0.0
|
102
|
+
def decrypt_data(raw_hash)
|
103
|
+
if looks_like_encrypted?(raw_hash)
|
104
|
+
decrypt_value(raw_hash)
|
105
|
+
else
|
106
|
+
decrypt_hash(raw_hash)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Decrypt a hash potentially containing nested encrypted values
|
111
|
+
#
|
112
|
+
# Additionally, this method will attempt tovkeep track of the names of
|
113
|
+
# each encrypted key.
|
114
|
+
#
|
115
|
+
# @param hash [Hash] a potentially encrypted hash
|
116
|
+
# @return [Hash] the unencrypted value
|
117
|
+
# @since 3.0.0
|
118
|
+
def decrypt_hash(hash)
|
119
|
+
decrypted_hash = Mash.new
|
120
|
+
|
121
|
+
hash.each do |key, value|
|
122
|
+
value = if looks_like_encrypted?(value)
|
123
|
+
@decrypted_keys.push(key) unless @decrypted_keys
|
124
|
+
.include?(key)
|
125
|
+
decrypt_value(value)
|
126
|
+
elsif value.is_a?(Hash)
|
127
|
+
decrypt_hash(value)
|
128
|
+
else value
|
129
|
+
end
|
130
|
+
decrypted_hash[key] = value
|
131
|
+
end
|
132
|
+
|
133
|
+
decrypted_hash
|
134
|
+
end
|
135
|
+
|
136
|
+
# Decrypt an encrypted value
|
137
|
+
# @param hash [Hash] the encrypted value as a hash
|
138
|
+
# @return [Mix] the unencrypted value
|
139
|
+
# @since 3.0.0
|
140
|
+
def decrypt_value(value)
|
141
|
+
case @format
|
142
|
+
when 'plain' then value
|
143
|
+
else
|
144
|
+
Chef::EncryptedDataBagItem::Decryptor
|
145
|
+
.for(value, @secret).for_decrypted_item
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|