Class: SecureCredentials::Store
- Inherits:
-
Object
- Object
- SecureCredentials::Store
- Defined in:
- lib/secure_credentials/store.rb
Overview
Store provides read-write interface for YAML configuration files. It supports:
- both encrypted and plain files,
- both file-per-environment and multi-environment files.
It takes base path of configuration file (for example, ‘config/secrets`) and environment value. Then it tries to find the most appropriate file for this configuration in following order:
"#{base}.#{env}.yml.enc"
"#{base}.#{env}.yml"
"#{base}.yml.enc"
"#{base}.yml"
Key for decoding encoded files can be passed:
- in `key` argument;
- envvar identified by `env_key`, default is to upcased basename appended with `_KEY`
(ex., `SECRETS_KEY`);
- in file found at `key_path`,
by default it uses filename and replaces `.yml.enc` with `.key`
(`secrets.production.key` for `secrets.production.yml.enc`);
- SecureCredentials.master_key.
If environment specific file is present, it’s whole content is returned. Otherwise ‘env` is used to fetch appropriate section.
Instance Attribute Summary collapse
-
#encrypted ⇒ Object
(also: #encrypted?)
readonly
Returns the value of attribute encrypted.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#environmental ⇒ Object
(also: #environmental?)
readonly
Returns the value of attribute environmental.
-
#filename ⇒ Object
readonly
Returns the value of attribute filename.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
-
.detect_filename(path, env) ⇒ Object
Finds the most appropriate existing file for given path and env.
-
.detect_key_path_for(path) ⇒ Object
Looks for key file for given path replacing ‘.yml.enc` with `.key`.
- .env_key_for(path) ⇒ Object
-
.load_yaml(string) ⇒ Object
ERB -> YAML.safe_load with aliases support.
Instance Method Summary collapse
-
#change(&block) ⇒ Object
Prepares file for edition, yields filename and then saves updated file.
-
#content ⇒ Object
Fetches appropriate environmental content or returns whole content in the case of single-environment file.
-
#initialize(path, env: nil, key: nil, key_path: nil, env_key: nil) ⇒ Store
constructor
A new instance of Store.
-
#read ⇒ Object
Read file content.
Constructor Details
#initialize(path, env: nil, key: nil, key_path: nil, env_key: nil) ⇒ Store
Returns a new instance of Store.
74 75 76 77 78 79 80 81 |
# File 'lib/secure_credentials/store.rb', line 74 def initialize(path, env: nil, key: nil, key_path: nil, env_key: nil) @path = path = Pathname.new(path) @env = env @environmental, @encrypted, @filename = self.class.detect_filename(path, env) @key = key @key_path = key_path || self.class.detect_key_path_for(filename) @env_key = env_key || self.class.env_key_for(path) end |
Instance Attribute Details
#encrypted ⇒ Object (readonly) Also known as: encrypted?
Returns the value of attribute encrypted.
70 71 72 |
# File 'lib/secure_credentials/store.rb', line 70 def encrypted @encrypted end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
70 71 72 |
# File 'lib/secure_credentials/store.rb', line 70 def env @env end |
#environmental ⇒ Object (readonly) Also known as: environmental?
Returns the value of attribute environmental.
70 71 72 |
# File 'lib/secure_credentials/store.rb', line 70 def environmental @environmental end |
#filename ⇒ Object (readonly)
Returns the value of attribute filename.
70 71 72 |
# File 'lib/secure_credentials/store.rb', line 70 def filename @filename end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
70 71 72 |
# File 'lib/secure_credentials/store.rb', line 70 def path @path end |
Class Method Details
.detect_filename(path, env) ⇒ Object
Finds the most appropriate existing file for given path and env. Returns ‘[environmental?, encrypted?, filename]`.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/secure_credentials/store.rb', line 35 def detect_filename(path, env) # Backward compatibility with original Rails implementation: # if filename is given with extension then we don't try to detect # environmental and/or encrypted variant. if path.basename.to_s =~ /\.yml(\.enc)?\z/i [false, path.basename.to_s.end_with?('.enc'), path] else stub_ext_path = Pathname.new("#{path}.stub") [ [true, true, stub_ext_path.sub_ext(".#{env}.yml.enc")], [true, false, stub_ext_path.sub_ext(".#{env}.yml")], [false, true, stub_ext_path.sub_ext('.yml.enc')], [false, false, stub_ext_path.sub_ext('.yml')], ].find { |x| x[2].exist? } end end |
.detect_key_path_for(path) ⇒ Object
Looks for key file for given path replacing ‘.yml.enc` with `.key`. It falls back to `config/master.key` in Rails app if file does not exist.
54 55 56 57 58 |
# File 'lib/secure_credentials/store.rb', line 54 def detect_key_path_for(path) return unless path.to_s.end_with?('.yml.enc') key_path = path.sub_ext('').sub_ext('.key') key_path.exist? || !defined?(::Rails) ? key_path : ::Rails.root.join('config/master.key') end |
.env_key_for(path) ⇒ Object
60 61 62 |
# File 'lib/secure_credentials/store.rb', line 60 def env_key_for(path) "#{path.basename.to_s.upcase}_KEY" end |
.load_yaml(string) ⇒ Object
ERB -> YAML.safe_load with aliases support.
65 66 67 |
# File 'lib/secure_credentials/store.rb', line 65 def load_yaml(string) YAML.safe_load(ERB.new(string).result, [], [], true) end |
Instance Method Details
#change(&block) ⇒ Object
Prepares file for edition, yields filename and then saves updated file.
101 102 103 104 105 106 107 108 |
# File 'lib/secure_credentials/store.rb', line 101 def change(&block) raise FileNotFound, "File not found for '#{path}'" unless filename && filename.exist? if encrypted? encrypted_file.change(&block) else yield filename end end |
#content ⇒ Object
Fetches appropriate environmental content or returns whole content in the case of single-environment file.
85 86 87 88 |
# File 'lib/secure_credentials/store.rb', line 85 def content result = environmental? ? full_content : full_content[env.to_s] result || {} end |
#read ⇒ Object
Read file content.
91 92 93 94 95 96 97 98 |
# File 'lib/secure_credentials/store.rb', line 91 def read return '' unless filename && filename.exist? if encrypted? encrypted_file.read else filename.read end end |