Module: Garcon::SecretBag

Defined in:
lib/garcon/chef/secret_bag.rb

Overview

Library routine that returns an encrypted data bag value for a supplied string. The key used in decrypting the encrypted value should be located at node[:secret].

Note that if node[:devmode] is true, then the value of the index parameter is just returned as-is. This means that in developer mode, if a cookbook does this:

That means admin will be ‘RoG+3xqKE23uc’

You also can provide a default password value in developer mode, like:

node.set[:garcon][:secret][:passwd] = secret('passwords', 'eazypass')

The mysql_passwd will == 'eazypass'

Examples:

class Chef
  class Recipe
    include Garcon::SecretBag
  end
end

admin = secret('bag_name', 'RoG+3xqKE23uc')

Constant Summary collapse

InvalidDataBagTypeError =
Class.new(RuntimeError)
DataBagEncryptionError =
Class.new(RuntimeError)

Instance Method Summary collapse

Instance Method Details

#data_bag_config_for(environment, source) ⇒ Chef::DataBagItem

Loads the encrypted data bag item and returns credentials for the environment or for a default key.

Parameters:

  • environment (String)

    The environment

  • source (String)

    The deployment source to load configuration for

Returns:

  • (Chef::DataBagItem)

    The data bag item



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/garcon/chef/secret_bag.rb', line 129

def data_bag_config_for(environment, source)
  data_bag_item = encrypted_data_bag_for(environment, DATA_BAG)

  if data_bag_item.has_key?(source)
    data_bag_item[source]
  elsif DATA_BAG == source
    data_bag_item
  else
    {}
  end
end

#encrypted_data_bag_for(environment, data_bag) ⇒ Chef::Mash

Looks for the given data bag in the cache and if not found, will load a data bag item named for the chef_environment, or ‘_wildcard’ value.

Parameters:

  • environment (String)

    The environment.

  • data_bag (String)

    The data bag to load.

Returns:

  • (Chef::Mash)

    The data bag item in Mash form.



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/garcon/chef/secret_bag.rb', line 153

def encrypted_data_bag_for(environment, data_bag)
  @encrypted_data_bags = {} unless @encrypted_data_bags

  if encrypted_data_bags[data_bag]
    return get_from_data_bags_cache(data_bag)
  else
    data_bag_item = encrypted_data_bag_item(data_bag, environment)
    data_bag_item ||= encrypted_data_bag_item(data_bag, WILDCARD)
    data_bag_item ||= {}
    @encrypted_data_bags[data_bag] = data_bag_item
    return data_bag_item
  end
end

#encrypted_data_bag_item(dbag, dbag_item) ⇒ Chef::Mash

Loads an EncryptedDataBagItem from the Chef server and turns it into a Chef::Mash, giving it indifferent access. Returns nil when a data bag item is not found.

Parameters:

Returns:

  • (Chef::Mash)

Raises:

  • (Chef::Garcon::DataBagEncryptionError)

    When the data bag cannot be decrypted or transformed into a Mash for some reason.



196
197
198
199
200
201
202
# File 'lib/garcon/chef/secret_bag.rb', line 196

def encrypted_data_bag_item(dbag, dbag_item)
  Mash.from_hash(Chef::EncryptedDataBagItem.load(dbag, dbag_item).to_hash)
rescue Net::HTTPServerException
  nil
rescue NoMethodError
  raise DataBagEncryptionError.new
end

#encrypted_data_bagsHash

Returns:



168
169
170
# File 'lib/garcon/chef/secret_bag.rb', line 168

def encrypted_data_bags
  @encrypted_data_bags
end

#encrypted_secret(bag_name, index) ⇒ Object



67
68
69
70
71
72
73
# File 'lib/garcon/chef/secret_bag.rb', line 67

def encrypted_secret(bag_name, index)
  key_path = node[:garcon][:secret][:key_path]
  Chef::Log.info "Loading encrypted databag #{bag_name}.#{index} " \
                 "using key at #{key_path}"
  secret = Chef::EncryptedDataBagItem.load_secret key_path
  Chef::EncryptedDataBagItem.load(bag_name, index, secret)[index]
end

#get_from_data_bags_cache(data_bag) ⇒ type

Loads an entry from the encrypted_data_bags class variable.

Parameters:

  • dbag (String)

    The data bag to find.

Returns:

  • (type)
    description


179
180
181
# File 'lib/garcon/chef/secret_bag.rb', line 179

def get_from_data_bags_cache(data_bag)
  encrypted_data_bags[data_bag]
end

#get_password(type, key) ⇒ Object

Return a password using either data bags or attributes for storage. The storage mechanism used is determined by the ‘node[:use_databags]` attribute.

Parameters:

  • type (String)

    password type, can be ‘:user`, `:service`, `:db` or `:token`

  • keys (String)

    the identifier of the password



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/garcon/chef/secret_bag.rb', line 100

def get_password(type, key)
  unless [:db, :user, :service, :token].include?(type)
    Chef::Log.error "Unsupported type for get_password: #{type}"
    return
  end

  if node[:garcon][:use_databags]
    if type == :token
      secret node[:garcon][:secret][:secrets_data_bag], key
    else
      secret node[:garcon][:secret]["#{type}_passwords_data_bag"], key
    end
  else
    node[:garcon][:secret][key][type]
  end
end

#secret(bag_name, index) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/garcon/chef/secret_bag.rb', line 50

def secret(bag_name, index)
  if node[:garcon][:devmode]
    dev_secret(index)
  else
    case node[:garcon][:databag_type]
    when :encrypted
      encrypted_secret(bag_name, index)
    when :standard
      standard_secret(bag_name, index)
    when :vault
      vault_secret('vault_' + bag_name, index)
    else
      raise InvalidDataBagType
    end
  end
end

#standard_secret(bag_name, index) ⇒ Object



75
76
77
78
# File 'lib/garcon/chef/secret_bag.rb', line 75

def standard_secret(bag_name, index)
  Chef::Log.info "Loading databag #{bag_name}.#{index}"
  Chef::DataBagItem.load(bag_name, index)[index]
end

#vault_secret(bag_name, index) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/garcon/chef/secret_bag.rb', line 80

def vault_secret(bag_name, index)
  begin
    require 'chef-vault'
  rescue LoadError
    Chef::Log.warn "Missing gem 'chef-vault'"
  end
  Chef::Log.info "Loading vault secret #{index} from #{bag_name}"
  ChefVault::Item.load(bag_name, index)[index]
end