Class: SecureDataBag::Item

Inherits:
Chef::DataBagItem
  • Object
show all
Defined in:
lib/secure_data_bag/secure_data_bag_item.rb

Overview

SecureDataBagItem extends the standard DataBagItem by providing it with encryption / decryption capabilities.

Although it does provide methods which may be used to specifically perform crypto functions, it should be used the same way.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Item

Returns a new instance of Item.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 18

def initialize(opts={})
  # Chef 12.3 introduced the new option
  begin super(chef_server_rest: opts.delete(:chef_server_rest))
  rescue ArgumentError; super()
  end

  secret_path     opts[:secret_path] if opts[:secret_path]
  secret          opts[:secret] if opts[:secret]
  encoded_fields  opts[:fields] if opts[:fields]

  self.raw_data = opts[:data] if opts[:data]
  self
end

Class Method Details

.from_hash(h, opts = {}) ⇒ Object

Transitions



161
162
163
164
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 161

def self.from_hash(h, opts={})
  item = new(opts.merge(data:h))
  item
end

.from_item(h, opts = {}) ⇒ Object



166
167
168
169
170
171
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 166

def self.from_item(h, opts={})
  item = self.from_hash(h.to_hash, opts)
  item.data_bag h.data_bag
  item.encoded_fields h.encoded_fields if h.respond_to?(:encoded_fields)
  item
end

.load(data_bag, name, opts = {}) ⇒ Object

Fetch databag item via DataBagItem and then optionally decrypt



66
67
68
69
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 66

def self.load(data_bag, name, opts={})
  data = super(data_bag, name)
  new(opts.merge(data:data.to_hash))
end

.load_secret(path = nil) ⇒ Object



59
60
61
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 59

def self.load_secret(path=nil)
  Chef::EncryptedDataBagItem.load_secret(secret_path(path))
end

.secret_path(arg = nil) ⇒ Object



41
42
43
44
45
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 41

def self.secret_path(arg=nil)
  arg || 
  Chef::Config[:knife][:secure_data_bag][:secret_file] ||
  Chef::Config[:encrypted_data_bag_secret]
end

Instance Method Details

#decode_data!Object

Raw Data decoder methods



96
97
98
99
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 96

def decode_data!
  @raw_data = decoded_data
  @raw_data
end

#decode_hash(hash) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 107

def decode_hash(hash)
  hash.each do |k,v|
    v = if encoded_value?(v)
          encoded_fields encoded_fields << k
          decode_value(v)
        elsif v.is_a?(Hash)
          decode_hash(v)
        else v
        end
    hash[k] = v
  end
  hash
end

#decode_value(value) ⇒ Object



121
122
123
124
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 121

def decode_value(value)
  Chef::EncryptedDataBagItem::Decryptor.
    for(value, secret).for_decrypted_item
end

#decoded_dataObject



101
102
103
104
105
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 101

def decoded_data
  if encoded_value?(@raw_data) then decode_value(@raw_data)
  else decode_hash(@raw_data)
  end
end

#encode_data!Object

Raw Data encoded methods



133
134
135
136
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 133

def encode_data!
  @raw_data = encoded_data
  @raw_data
end

#encode_hash(hash) ⇒ Object



142
143
144
145
146
147
148
149
150
151
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 142

def encode_hash(hash)
  hash.each do |k,v|
    v = if encoded_fields.include?(k) then encode_value(v)
        elsif v.is_a?(Hash) then encode_hash(v)
        else v
        end
    hash[k] = v
  end
  hash
end

#encode_value(value) ⇒ Object



153
154
155
156
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 153

def encode_value(value)
  Chef::EncryptedDataBagItem::Encryptor.
    new(value, secret).for_encrypted_item
end

#encoded_dataObject



138
139
140
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 138

def encoded_data
  encode_hash(@raw_data.dup)
end

#encoded_fields(arg = nil) ⇒ Object

Fields we wish to encode



87
88
89
90
91
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 87

def encoded_fields(arg=nil)
  @encoded_fields = Array(arg).map{|s|s.to_s}.uniq if arg
  @encoded_fields ||= Chef::Config[:knife][:secure_data_bag][:fields] ||
                      Array.new
end

#encoded_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 126

def encoded_value?(value)
  value.is_a?(Hash) and value.key?(:encrypted_data)
end

#load_secretObject



55
56
57
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 55

def load_secret
  @secret = self.class.load_secret(secret_path)
end

#raw_data=(data) ⇒ Object

Setter for @raw_data

  • ensure the data we receive is a Mash to support symbols

  • pass it to DataBagItem for additional validation

  • ensure the data has the encryption hash

  • decode the data



78
79
80
81
82
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 78

def raw_data=(data)
  data = Mash.new(data)
  super(data)
  decode_data!
end

#secret(arg = nil) ⇒ Object

Content of encryption secret



50
51
52
53
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 50

def secret(arg=nil)
  @secret = arg unless arg.nil?
  @secret ||= load_secret
end

#secret_path(arg = nil) ⇒ Object

Path to encryption key file



35
36
37
38
39
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 35

def secret_path(arg=nil)
  set_or_return :secret_path, arg, 
    kind_of: String,
    default: self.class.secret_path
end

#to_hash(opts = {}) ⇒ Object



173
174
175
176
177
178
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 173

def to_hash(opts={})
  result = opts[:encoded] ? encoded_data : @raw_data
  result["chef_type"] = "data_bag_item"
  result["data_bag"] = data_bag
  result
end

#to_json(*a) ⇒ Object



180
181
182
183
184
185
186
187
188
189
# File 'lib/secure_data_bag/secure_data_bag_item.rb', line 180

def to_json(*a)
  result = {
    name: self.object_name,
    json_class: "Chef::DataBagItem",
    chef_type: "data_bag_item",
    data_bag: data_bag,
    raw_data: encoded_data
  }
  result.to_json(*a)
end