Class: Chef::EncryptedAttribute

Inherits:
Object
  • Object
show all
Extended by:
API
Defined in:
lib/chef/encrypted_attribute.rb,
lib/chef/encrypted_attribute/api.rb,
lib/chef/encrypted_attribute/yajl.rb,
lib/chef/encrypted_attribute/config.rb,
lib/chef/encrypted_attribute/version.rb,
lib/chef/encrypted_attribute/cache_lru.rb,
lib/chef/encrypted_attribute/local_node.rb,
lib/chef/encrypted_attribute/assertions.rb,
lib/chef/encrypted_attribute/exceptions.rb,
lib/chef/encrypted_attribute/remote_node.rb,
lib/chef/encrypted_attribute/remote_nodes.rb,
lib/chef/encrypted_attribute/remote_users.rb,
lib/chef/encrypted_attribute/search_helper.rb,
lib/chef/encrypted_attribute/remote_clients.rb,
lib/chef/encrypted_attribute/encrypted_mash.rb,
lib/chef/encrypted_attribute/encrypted_mash/version2.rb,
lib/chef/encrypted_attribute/encrypted_mash/version0.rb,
lib/chef/encrypted_attribute/encrypted_mash/version1.rb

Overview

Main EncryptedAttribute class.

This class contains both static and instance level public methods. Internally, all work with EncryptedMash object instances.

Class Methods

The class methods (or static methods) are normally used from Chef cookbooks.

The attributes create with the class methods are encrypted only for the local node by default.

The static *_on_node methods can be used, although they have not been designed for this purpose (have not been tested).

They are # documented in the API class.

Instance Methods

The instance methods are normally used by other libraries or gems. For example, the knife extensions included in this gem uses these methods.

The instance methods will grant encrypted attribute access only to the remote node by default.

Usually only the *_from_node/*_on_node instance methods will be used.

See Also:

Defined Under Namespace

Modules: API, Assertions, SearchHelper, Yajl Classes: CacheLru, ClientNotFound, Config, DecryptionFailure, EncryptedMash, EncryptionFailure, InsufficientPrivileges, InvalidKey, InvalidPublicKey, InvalidSearchKeys, LocalNode, MessageAuthenticationFailure, RemoteClients, RemoteNode, RemoteNodes, RemoteUsers, RequirementsFailure, SearchFailure, SearchFatalError, UnacceptableEncryptedAttributeFormat, UnsupportedEncryptedAttributeFormat, UserNotFound

Constant Summary collapse

VERSION =

chef-encrypted-attributes gem version.

'0.10.0.dev'

Instance Method Summary collapse

Methods included from API

debug, exist?, exist_on_node?, exists?, exists_on_node?, local_node, warn

Constructor Details

#initialize(c = nil) ⇒ EncryptedAttribute

Chef::EncryptedAttribute constructor.

Parameters:

  • c (Config, Hash) (defaults to: nil)

    configuration to use.


76
77
78
# File 'lib/chef/encrypted_attribute.rb', line 76

def initialize(c = nil)
  config(c)
end

Instance Method Details

#config(arg = nil) ⇒ Config

Sets or gets the encrypted attribute configuration.

Reads the default configuration from Chef::Config[:encrypted_attributes].

When setting using a Config class, all the configuration options will be replaced.

When setting using a Hash, only the provided keys will be replaced.

Parameters:

  • arg (Config, Hash) (defaults to: nil)

    the configuration to set.

Returns:

  • (Config)

    the read or set configuration object.


92
93
94
95
96
97
98
# File 'lib/chef/encrypted_attribute.rb', line 92

def config(arg = nil)
  @config ||= EncryptedAttribute::Config.new(
    Chef::Config[:encrypted_attributes]
  )
  @config.update!(arg) unless arg.nil?
  @config
end

#create(value, keys = nil) ⇒ EncryptedMash

Creates an encrypted attribute from a Hash.

Only the keys passed as parameter and the configured keys will be able to decrypt the attribute, so beware of including your local key if you need to decrypt it in the future.

Parameters:

  • value (Hash, Array, String, Fixnum, ...)

    the value to encrypt in clear.

  • keys (String, OpenSSL::PKey::RSA) (defaults to: nil)

    public keys that will be able to decrypt the attribute.

Returns:

  • (EncryptedMash)

    encrypted attribute value. This is usually what is saved in the node attributes.

Raises:


170
171
172
173
174
175
# File 'lib/chef/encrypted_attribute.rb', line 170

def create(value, keys = nil)
  decrypted = { 'content' => value }

  enc_attr = EncryptedMash.create(config.version)
  enc_attr.encrypt(decrypted, target_keys(keys))
end

#create_on_node(name, attr_ary, value) ⇒ EncryptedMash

Creates an encrypted attribute on a remote node.

The remote node will always be able to decrypt it. The local node will not be able to decrypt it by default, you must remember to include the key in the configuration.

Parameters:

  • name (String)

    node name.

  • attr_ary (Array<String>)

    node attribute path as Array.

  • value (Hash, Array, String, Fixnum, ...)

    the value to encrypt.

Returns:

Raises:


206
207
208
209
210
211
212
213
214
215
216
# File 'lib/chef/encrypted_attribute.rb', line 206

def create_on_node(name, attr_ary, value)
  # read the client public key
  node_public_key = RemoteClients.get_public_key(name)

  # create the encrypted attribute
  enc_attr = create(value, [node_public_key])

  # save encrypted attribute
  remote_node = RemoteNode.new(name)
  remote_node.save_attribute(attr_ary, enc_attr)
end

#load(enc_hs, key = nil) ⇒ Hash, ...

Decrypts an encrypted attribute from a local node attribute.

Parameters:

  • enc_hs (Mash)

    the encrypted hash as read from the node attributes.

  • key (String, OpenSSL::PKey::RSA) (defaults to: nil)

    private key to use in the decryption process, uses the local node key by default.

Returns:

  • (Hash, Array, String, ...)

    decrypted attribute value.

Raises:


110
111
112
113
114
# File 'lib/chef/encrypted_attribute.rb', line 110

def load(enc_hs, key = nil)
  enc_attr = EncryptedMash.json_create(enc_hs)
  decrypted = enc_attr.decrypt(key || local_key)
  decrypted['content'] # TODO: check this Hash
end

#load_from_node(name, attr_ary, key = nil) ⇒ Hash, ...

Decrypts a encrypted attribute from a remote node.

Parameters:

  • name (String)

    node name.

  • attr_ary (Array<String>)

    node attribute path as Array.

  • key (String, OpenSSL::PKey::RSA) (defaults to: nil)

    private key to use in the decryption process, uses the local key by default.

Returns:

  • (Hash, Array, String, ...)

    decrypted attribute value.

Raises:


131
132
133
134
135
136
137
138
# File 'lib/chef/encrypted_attribute.rb', line 131

def load_from_node(name, attr_ary, key = nil)
  remote_node = RemoteNode.new(name)
  enc_hs =
    remote_node.load_attribute(
      attr_ary, config.search_max_rows, config.partial_search
    )
  load(enc_hs, key)
end

#update(enc_hs, keys = nil) ⇒ Boolean

Updates the keys for which a local attribute is encrypted.

In case new keys are added or some keys are removed, the attribute will be re-created again.

Only the keys passed as parameter and the configured keys will be able to decrypt the attribute, so beware of including your local key if you need to decrypt it in the future.

Uses the local key to decrypt the attribute, so the local key should be able to read the attribute. At least before updating.

Parameters:

  • enc_hs (Mash)

    encrypted attribute. This parameter value will be modified on updates.

  • keys (Array<String, OpenSSL::PKey::RSA> public keys that should be able to read the attribute.) (defaults to: nil)

    eys [Array public keys that should be able to read the attribute.

Returns:

  • (Boolean)

    Returns true if the encrypted attribute (the Mash parameter) has been updated.

Raises:

See Also:


255
256
257
258
259
260
261
262
263
264
265
# File 'lib/chef/encrypted_attribute.rb', line 255

def update(enc_hs, keys = nil)
  old_enc_attr = EncryptedMash.json_create(enc_hs)
  if old_enc_attr.needs_update?(target_keys(keys))
    hs = old_enc_attr.decrypt(local_key)
    new_enc_attr = create(hs['content'], keys) # TODO: check this Hash
    enc_hs.replace(new_enc_attr)
    true
  else
    false
  end
end

#update_on_node(name, attr_ary) ⇒ Boolean

Updates the keys for which a remote attribute is encrypted.

In case new keys are added or some keys are removed, the attribute will be re-created again.

Only the remote node and the configured keys will be able to decrypt the attribute, so beware of including your local key if you need to decrypt it in the future.

Uses the local key to decrypt the attribute, so the local key should be able to read the attribute. At least before updating.

Parameters:

  • name (String)

    node name.

  • attr_ary (Array<String>)

    node attribute path as Array.

Returns:

  • (Boolean)

    Returns true if the remote encrypted attribute has been updated.

Raises:

See Also:


303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/chef/encrypted_attribute.rb', line 303

def update_on_node(name, attr_ary)
  # read the client public key
  node_public_key = RemoteClients.get_public_key(name)

  # update the encrypted attribute
  remote_node = RemoteNode.new(name)
  enc_hs =
    remote_node.load_attribute(
      attr_ary, config.search_max_rows, config.partial_search
    )
  updated = update(enc_hs, [node_public_key])

  # save encrypted attribute
  if updated
    # TODO: Node is accessed twice (RemoteNode#load_attribute above)
    remote_node.save_attribute(attr_ary, enc_hs)
  end
  updated
end