Class: Chef::EncryptedAttribute::EncryptedMash

Inherits:
Mash
  • Object
show all
Defined in:
lib/chef/encrypted_attribute/encrypted_mash.rb,
lib/chef/encrypted_attribute/encrypted_mash/version0.rb,
lib/chef/encrypted_attribute/encrypted_mash/version1.rb,
lib/chef/encrypted_attribute/encrypted_mash/version2.rb

Overview

Mash structure with embedded Mash structure encrypted.

This is the most basic encrypted object, which inherits from Chef::Mash.

This class is used to construct the different EncryptedAttribute versions. Each version implements the encryption in a different way or using different algorithms.

Currently three EncryptedMash versions exists. But you can create your own versions and name it with the Chef::EncryptedAttribute::EncryptedMash::Version prefix.

Uses Version1 by default.

This class is oriented to be easily integrable with chef in the future using JSONCompat.

Direct Known Subclasses

Version0

Defined Under Namespace

Classes: Version0, Version1, Version2

Constant Summary collapse

JSON_CLASS =

Mash key name to use for JSON class name. Chef uses the 'json_class' key internally for objects, we use a renamed key.

'x_json_class'.freeze
CHEF_TYPE =

Mash key name to use for Chef object type.

'chef_type'.freeze
CHEF_TYPE_VALUE =

Chef object type value.

'encrypted_attribute'.freeze
VERSION_PREFIX =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Name prefix for all EncryptedAttribute version classes. Used internally by the #self.version_class method.

"#{name}::Version"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(enc_hs = nil) ⇒ EncryptedMash

Encrypted Mash constructor.

Raises:


67
68
69
70
71
72
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 67

def initialize(enc_hs = nil)
  super
  self[JSON_CLASS] = self.class.name
  self[CHEF_TYPE] = CHEF_TYPE_VALUE
  update_from!(enc_hs) if enc_hs.is_a?(Hash)
end

Class Method Details

.create(version) ⇒ Object

Factory method to construct an encrypted Mash.

Raises:


113
114
115
116
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 113

def self.create(version)
  klass = version_klass(version)
  klass.send(:new)
end

.exist?(enc_hs) ⇒ Boolean

Checks whether an encrypted Mash exists.


85
86
87
88
89
90
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 85

def self.exist?(enc_hs)
  enc_hs.is_a?(Hash) &&
    enc_hs.key?(JSON_CLASS) &&
    enc_hs[JSON_CLASS] =~ /^#{Regexp.escape(Module.nesting[1].name)}/ &&
    enc_hs.key?(CHEF_TYPE) && enc_hs[CHEF_TYPE] == CHEF_TYPE_VALUE
end

.exists?(*args) ⇒ Boolean

Deprecated.

Use exist? instead.

Checks whether an encrypted Mash exists.


97
98
99
100
101
102
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 97

def self.exists?(*args)
  Chef::Log.warn(
    "#{name}.exists? is deprecated in favor of #{name}.exist?."
  )
  exist?(*args)
end

.json_create(enc_hs) ⇒ EncryptedMash

Creates an EncryptedMash::Version object from a JSON Hash.

Reads the EncryptedMash version to create from the JSON_CLASS key.

Raises:


162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 162

def self.json_create(enc_hs)
  unless enc_hs.is_a?(Hash)
    fail UnacceptableEncryptedAttributeFormat,
         'Encrypted attribute not found or corrupted.'
  end
  klass = string_to_klass(enc_hs[JSON_CLASS])
  if klass.nil?
    fail UnsupportedEncryptedAttributeFormat,
         "Unknown chef-encrypted-attribute class #{enc_hs[JSON_CLASS]}"
  end
  klass.send(:new, enc_hs)
end

.string_to_klass(class_name) ⇒ Class

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets the class reference from its string representation.

Raises:


182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 182

def self.string_to_klass(class_name)
  unless class_name.is_a?(String)
    fail UnacceptableEncryptedAttributeFormat,
         "Bad chef-encrypted-attribute class name #{class_name.inspect}"
  end
  begin
    class_name.split('::').inject(Kernel) do |scope, const|
      scope.const_get(const, scope == Kernel)
    end
  rescue NameError => e
    Chef::Log.error(e)
    nil
  end
end

.version_klass(version) ⇒ Class

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Gets the class reference for a EncryptedMash version.

The implementation of "Chef::EncryptedAttribute::Version#{version}" must exists and be included (require) beforehand.

Raises:


209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 209

def self.version_klass(version)
  version = version.to_s unless version.is_a?(String)
  if version.empty?
    fail UnacceptableEncryptedAttributeFormat,
         "Bad chef-encrypted-attribute version #{version.inspect}"
  end
  klass = string_to_klass("#{VERSION_PREFIX}#{version}")
  if klass.nil?
    fail UnsupportedEncryptedAttributeFormat,
         'This version of chef-encrypted-attribute does not support '\
         "encrypted attribute item format version: \"#{version}\""
  end
  klass
end

Instance Method Details

#for_jsonHash

Returns the object as a Ruby Hash.


129
130
131
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 129

def for_json
  to_hash
end

#to_json(*a) ⇒ String

Serializes this object as a Hash.


122
123
124
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 122

def to_json(*a)
  for_json.to_json(*a)
end

#update_from!(enc_hs) ⇒ Mash

Replaces the EncryptedMash content from a Mash.

Raises:


139
140
141
142
143
144
145
146
147
148
149
# File 'lib/chef/encrypted_attribute/encrypted_mash.rb', line 139

def update_from!(enc_hs)
  unless self.class.exist?(enc_hs)
    fail UnacceptableEncryptedAttributeFormat,
         'Trying to construct invalid encrypted attribute. Maybe it is '\
         'not encrypted?'
  end
  enc_hs = enc_hs.dup
  enc_hs.delete(JSON_CLASS)
  enc_hs.delete(CHEF_TYPE)
  update(enc_hs)
end