secret_config 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +63 -2
- data/lib/secret_config/errors.rb +3 -0
- data/lib/secret_config/providers/ssm.rb +2 -1
- data/lib/secret_config/registry.rb +17 -5
- data/lib/secret_config/setting_interpolator.rb +58 -0
- data/lib/secret_config/string_interpolator.rb +32 -0
- data/lib/secret_config/version.rb +1 -1
- data/lib/secret_config.rb +2 -2
- data/test/config/application.yml +1 -1
- data/test/providers/file_test.rb +1 -1
- data/test/registry_test.rb +2 -1
- data/test/secret_config_test.rb +31 -13
- data/test/setting_interpolator_test.rb +152 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24792842f7d81af2c5d70eb431eae87ec96f190a52500c7e68267b6e875a4e09
|
4
|
+
data.tar.gz: 29f1683c2be73597476f976860dd021476559d97ed94e04195789fadaf4fb7f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89a0ecfab4bfb8263768ccf51ec56b987866cac08d23c2c9e34a69b9ba3210d9ed40198cfd525d72f54dcf4e6aa0f2c8965d30204ec96c4b825f1c61313c35b5
|
7
|
+
data.tar.gz: c0047de74541f0589ebe2ad66a67133b73d6fa5635610d81b685394aca395d46dfadc4171ca655975296289292203dc004a977fe265c6b0d704ad4a894cc6983
|
data/README.md
CHANGED
@@ -5,6 +5,13 @@ Centralized Configuration and Secrets Management for Ruby and Rails applications
|
|
5
5
|
|
6
6
|
Securely store configuration information centrally, supporting multiple tenants of the same application.
|
7
7
|
|
8
|
+
## Overview
|
9
|
+
|
10
|
+
Securely store centralized configuration information such as:
|
11
|
+
* Settings
|
12
|
+
* Passwords
|
13
|
+
* Encryption keys and certificates
|
14
|
+
|
8
15
|
## Features
|
9
16
|
|
10
17
|
Supports storing configuration information in:
|
@@ -15,6 +22,17 @@ Supports storing configuration information in:
|
|
15
22
|
* AWS System Manager Parameter Store
|
16
23
|
* Encrypt and securely store secrets such as passwords centrally.
|
17
24
|
|
25
|
+
Supported data types:
|
26
|
+
* integer
|
27
|
+
* float
|
28
|
+
* string
|
29
|
+
* boolean
|
30
|
+
* symbol
|
31
|
+
* json
|
32
|
+
|
33
|
+
Supported conversions:
|
34
|
+
* base64
|
35
|
+
|
18
36
|
## Benefits
|
19
37
|
|
20
38
|
Benefits of moving sensitive configuration information into AWS System Manager Parameter Store:
|
@@ -23,7 +41,7 @@ Benefits of moving sensitive configuration information into AWS System Manager P
|
|
23
41
|
* Environment variables force all config into a single level.
|
24
42
|
* Reduces the number of environment variables.
|
25
43
|
* In a large application the number of secrets can grow dramatically.
|
26
|
-
*
|
44
|
+
* Replaces sensitive data stored in local yaml or configuration files.
|
27
45
|
* Including securing and managing encryption keys.
|
28
46
|
* When encryption keys change, such as during a key rotation, config files don't have to be changed.
|
29
47
|
* Removes security concerns with placing passwords in the clear into environment variables.
|
@@ -222,7 +240,7 @@ Note: Do not put any production credentials into this file.
|
|
222
240
|
|
223
241
|
### Environment Variables
|
224
242
|
|
225
|
-
Any of the above values can be overridden with an environment variable.
|
243
|
+
Any of the above values can be overridden with an environment variable, unless explicitly configured `SecretConfig.check_env_var = false`.
|
226
244
|
|
227
245
|
To overwrite any of these settings with an environment variable:
|
228
246
|
|
@@ -471,6 +489,49 @@ to view and modify parameters:
|
|
471
489
|
- `ssm:GetParameters`
|
472
490
|
- `ssm:GetParameter`
|
473
491
|
|
492
|
+
## String Interpolation
|
493
|
+
|
494
|
+
Values supplied for config settings can be replaced inline with date, time, hostname, pid and random values.
|
495
|
+
|
496
|
+
For example to include the `hostname` in the log file name setting:
|
497
|
+
|
498
|
+
~~~yaml
|
499
|
+
development:
|
500
|
+
logger:
|
501
|
+
level: info
|
502
|
+
file_name: /var/log/my_application_%{hostname}.log
|
503
|
+
~~~
|
504
|
+
|
505
|
+
Available interpolations:
|
506
|
+
|
507
|
+
* %{date}
|
508
|
+
* Current date in the format of "%Y%m%d" (CCYYMMDD)
|
509
|
+
* %{date:format}
|
510
|
+
* Current date in the supplied format. See strftime
|
511
|
+
* %{time}
|
512
|
+
* Current date and time down to ms in the format of "%Y%m%d%Y%H%M%S%L" (CCYYMMDDHHMMSSmmm)
|
513
|
+
* %{time:format}
|
514
|
+
* Current date and time in the supplied format. See strftime
|
515
|
+
* %{env:name}
|
516
|
+
* Extract value from the named environment variable.
|
517
|
+
* %{hostname}
|
518
|
+
* Full name of this host.
|
519
|
+
* %{hostname:short}
|
520
|
+
* Short name of this host. Everything up to the first period.
|
521
|
+
* %{pid}
|
522
|
+
* Process Id for this process.
|
523
|
+
* %{random}
|
524
|
+
* URL safe Random 32 byte value.
|
525
|
+
* %{random:size}
|
526
|
+
* URL safe Random value of `size` bytes.
|
527
|
+
|
528
|
+
#### Notes:
|
529
|
+
|
530
|
+
* To prevent interpolation use %%{...}
|
531
|
+
* %% is not touched, only %{...} is searched for.
|
532
|
+
* Since these interpolations are only evaluated at load time and
|
533
|
+
every time the registry is refreshed there is no runtime overhead when keys are fetched.
|
534
|
+
|
474
535
|
## Command Line Interface
|
475
536
|
|
476
537
|
Secret Config has a command line interface for exporting, importing and copying between paths in the registry.
|
data/lib/secret_config/errors.rb
CHANGED
@@ -32,7 +32,13 @@ module SecretConfig
|
|
32
32
|
|
33
33
|
# Returns [String] configuration value for the supplied key, or nil when missing.
|
34
34
|
def [](key)
|
35
|
-
|
35
|
+
full_key = expand_key(key)
|
36
|
+
value = cache[full_key]
|
37
|
+
if value.nil? && SecretConfig.check_env_var?
|
38
|
+
value = env_var_override(key, value)
|
39
|
+
cache[full_key] = value unless value.nil?
|
40
|
+
end
|
41
|
+
value
|
36
42
|
end
|
37
43
|
|
38
44
|
# Returns [String] configuration value for the supplied key, or nil when missing.
|
@@ -45,8 +51,7 @@ module SecretConfig
|
|
45
51
|
value = self[key]
|
46
52
|
if value.nil?
|
47
53
|
raise(MissingMandatoryKey, "Missing configuration value for #{path}/#{key}") if default == :no_default_supplied
|
48
|
-
|
49
|
-
value = default.respond_to?(:call) ? default.call : default
|
54
|
+
value = block_given? ? yield : default
|
50
55
|
end
|
51
56
|
|
52
57
|
value = convert_encoding(encoding, value) if encoding
|
@@ -78,7 +83,8 @@ module SecretConfig
|
|
78
83
|
existing_keys = cache.keys
|
79
84
|
updated_keys = []
|
80
85
|
provider.each(path) do |key, value|
|
81
|
-
|
86
|
+
value = interpolator.parse(value) if value.is_a?(String) && value.include?('%{')
|
87
|
+
cache[key] = env_var_override(relative_key(key), value)
|
82
88
|
updated_keys << key
|
83
89
|
end
|
84
90
|
|
@@ -92,10 +98,16 @@ module SecretConfig
|
|
92
98
|
|
93
99
|
attr_reader :cache
|
94
100
|
|
101
|
+
def interpolator
|
102
|
+
@interpolator ||= SettingInterpolator.new
|
103
|
+
end
|
104
|
+
|
95
105
|
# Returns the value from an env var if it is present,
|
96
106
|
# Otherwise the value is returned unchanged.
|
97
107
|
def env_var_override(key, value)
|
98
|
-
|
108
|
+
return value unless SecretConfig.check_env_var?
|
109
|
+
|
110
|
+
env_var_name = key.upcase.gsub("/", "_")
|
99
111
|
ENV[env_var_name] || value
|
100
112
|
end
|
101
113
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'socket'
|
3
|
+
require 'securerandom'
|
4
|
+
# * SecretConfig Interpolations
|
5
|
+
#
|
6
|
+
# Expanding values inline for date, time, hostname, pid and random values.
|
7
|
+
# %{date} # Current date in the format of "%Y%m%d" (CCYYMMDD)
|
8
|
+
# %{date:format} # Current date in the supplied format. See strftime
|
9
|
+
# %{time} # Current date and time down to ms in the format of "%Y%m%d%Y%H%M%S%L" (CCYYMMDDHHMMSSmmm)
|
10
|
+
# %{time:format} # Current date and time in the supplied format. See strftime
|
11
|
+
# %{env:name} # Extract value from the named environment value.
|
12
|
+
# %{hostname} # Full name of this host.
|
13
|
+
# %{hostname:short} # Short name of this host. Everything up to the first period.
|
14
|
+
# %{pid} # Process Id for this process.
|
15
|
+
# %{random} # URL safe Random 32 byte value.
|
16
|
+
# %{random:size} # URL safe Random value of `size` bytes.
|
17
|
+
#
|
18
|
+
# Retrieve values elsewhere in the registry.
|
19
|
+
# Paths can be relative to the current root, or absolute paths outside the current root.
|
20
|
+
# %{fetch:key} # Fetches a single value from a relative or absolute path
|
21
|
+
# %{include:path} # Fetches a path of keys and values
|
22
|
+
module SecretConfig
|
23
|
+
class SettingInterpolator < StringInterpolator
|
24
|
+
def date(format = "%Y%m%d")
|
25
|
+
Date.today.strftime(format)
|
26
|
+
end
|
27
|
+
|
28
|
+
def time(format = "%Y%m%d%H%M%S%L")
|
29
|
+
Time.now.strftime(format)
|
30
|
+
end
|
31
|
+
|
32
|
+
def env(name)
|
33
|
+
ENV[name]
|
34
|
+
end
|
35
|
+
|
36
|
+
def hostname(format = nil)
|
37
|
+
name = Socket.gethostname
|
38
|
+
name = name.split('.')[0] if format == "short"
|
39
|
+
name
|
40
|
+
end
|
41
|
+
|
42
|
+
def pid
|
43
|
+
$$
|
44
|
+
end
|
45
|
+
|
46
|
+
def random(size = 32)
|
47
|
+
SecureRandom.urlsafe_base64(size)
|
48
|
+
end
|
49
|
+
|
50
|
+
#def fetch(key)
|
51
|
+
# SecretConfig[key]
|
52
|
+
#end
|
53
|
+
#
|
54
|
+
#def include(path)
|
55
|
+
#
|
56
|
+
#end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Parse strings containing %{key:value1,value2,value3}
|
2
|
+
# Where `key` is a method implemented by a class inheriting from this class
|
3
|
+
#
|
4
|
+
# The following `key`s are reserved:
|
5
|
+
# * parse
|
6
|
+
# * initialize
|
7
|
+
#
|
8
|
+
# Notes:
|
9
|
+
# * To prevent interpolation use %%{...}
|
10
|
+
# * %% is not touched, only %{...} is identified.
|
11
|
+
module SecretConfig
|
12
|
+
class StringInterpolator
|
13
|
+
def initialize(pattern = nil)
|
14
|
+
@pattern = pattern || /%{1,2}\{([^}]+)\}/
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse(string)
|
18
|
+
string.gsub(/%{1,2}\{([^}]+)\}/) do |match|
|
19
|
+
if match.start_with?('%%')
|
20
|
+
match[1..-1]
|
21
|
+
else
|
22
|
+
expr = $1 || $2 || match.tr("%{}", "")
|
23
|
+
key, args_str = expr.split(':')
|
24
|
+
key = key.strip.to_sym
|
25
|
+
arguments = args_str&.split(',')&.map { |v| v.strip == '' ? nil : v.strip } || []
|
26
|
+
raise(InvalidInterpolation, "Invalid key: #{key} in string: #{match}") unless respond_to?(key)
|
27
|
+
public_send(key, *arguments)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/secret_config.rb
CHANGED
@@ -18,6 +18,8 @@ module SecretConfig
|
|
18
18
|
end
|
19
19
|
|
20
20
|
autoload :CLI, "secret_config/cli"
|
21
|
+
autoload :SettingInterpolator, "secret_config/setting_interpolator"
|
22
|
+
autoload :StringInterpolator, "secret_config/string_interpolator"
|
21
23
|
autoload :Utils, "secret_config/utils"
|
22
24
|
|
23
25
|
class << self
|
@@ -65,8 +67,6 @@ module SecretConfig
|
|
65
67
|
@check_env_var = check_env_var
|
66
68
|
end
|
67
69
|
|
68
|
-
private
|
69
|
-
|
70
70
|
@check_env_var = true
|
71
71
|
@filters = [/password/i, /key\Z/i, /passphrase/i]
|
72
72
|
end
|
data/test/config/application.yml
CHANGED
data/test/providers/file_test.rb
CHANGED
@@ -15,7 +15,7 @@ module Providers
|
|
15
15
|
{
|
16
16
|
"/test/my_application/mongo/database" => "secret_config_test",
|
17
17
|
"/test/my_application/mongo/primary" => "127.0.0.1:27017",
|
18
|
-
"/test/my_application/mongo/secondary" => "
|
18
|
+
"/test/my_application/mongo/secondary" => "%{hostname}:27018",
|
19
19
|
"/test/my_application/mysql/database" => "secret_config_test",
|
20
20
|
"/test/my_application/mysql/password" => "secret_configrules",
|
21
21
|
"/test/my_application/mysql/username" => "secret_config",
|
data/test/registry_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'test_helper'
|
2
|
+
require 'socket'
|
2
3
|
|
3
4
|
class RegistryTest < Minitest::Test
|
4
5
|
describe SecretConfig::Registry do
|
@@ -22,7 +23,7 @@ class RegistryTest < Minitest::Test
|
|
22
23
|
{
|
23
24
|
"/test/my_application/mongo/database" => "secret_config_test",
|
24
25
|
"/test/my_application/mongo/primary" => "127.0.0.1:27017",
|
25
|
-
"/test/my_application/mongo/secondary" => "
|
26
|
+
"/test/my_application/mongo/secondary" => "#{Socket.gethostname}:27018",
|
26
27
|
"/test/my_application/mysql/database" => "secret_config_test",
|
27
28
|
"/test/my_application/mysql/password" => "secret_configrules",
|
28
29
|
"/test/my_application/mysql/username" => "secret_config",
|
data/test/secret_config_test.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
-
require_relative
|
1
|
+
require_relative "test_helper"
|
2
|
+
require "socket"
|
2
3
|
|
3
4
|
class SecretConfigTest < Minitest::Test
|
4
5
|
describe SecretConfig::Providers::File do
|
5
6
|
let :file_name do
|
6
|
-
File.join(File.dirname(__FILE__),
|
7
|
+
File.join(File.dirname(__FILE__), "config", "application.yml")
|
7
8
|
end
|
8
9
|
|
9
10
|
let :path do
|
@@ -14,39 +15,56 @@ class SecretConfigTest < Minitest::Test
|
|
14
15
|
SecretConfig.use :file, path: path, file_name: file_name
|
15
16
|
end
|
16
17
|
|
17
|
-
describe
|
18
|
-
it
|
18
|
+
describe "#configuration" do
|
19
|
+
it "returns a copy of the config" do
|
19
20
|
assert_equal "127.0.0.1", SecretConfig.configuration.dig("mysql", "host")
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
describe
|
24
|
-
it
|
24
|
+
describe "#key?" do
|
25
|
+
it "has key" do
|
25
26
|
assert SecretConfig.key?("mysql/database")
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
describe
|
30
|
-
it
|
30
|
+
describe "#[]" do
|
31
|
+
it "returns values" do
|
31
32
|
assert_equal "secret_config_test", SecretConfig["mysql/database"]
|
32
33
|
end
|
34
|
+
|
35
|
+
it "returns values with interpolation" do
|
36
|
+
assert_equal "#{Socket.gethostname}:27018", SecretConfig["mongo/secondary"]
|
37
|
+
end
|
33
38
|
end
|
34
39
|
|
35
|
-
describe
|
40
|
+
describe "#fetch" do
|
36
41
|
after do
|
37
|
-
ENV[
|
42
|
+
ENV["MYSQL_DATABASE"] = nil
|
43
|
+
SecretConfig.check_env_var = true
|
38
44
|
end
|
39
45
|
|
40
|
-
it
|
46
|
+
it "fetches values" do
|
41
47
|
assert_equal "secret_config_test", SecretConfig.fetch("mysql/database")
|
42
48
|
end
|
43
49
|
|
44
|
-
it
|
45
|
-
ENV[
|
50
|
+
it "can be overridden by an environment variable" do
|
51
|
+
ENV["MYSQL_DATABASE"] = "other"
|
46
52
|
|
47
53
|
SecretConfig.use :file, path: path, file_name: file_name
|
48
54
|
assert_equal "other", SecretConfig.fetch("mysql/database")
|
49
55
|
end
|
56
|
+
|
57
|
+
it "returns values with interpolation" do
|
58
|
+
assert_equal "#{Socket.gethostname}:27018", SecretConfig.fetch("mongo/secondary")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "can be omitted an environment variable override with #check_env_var configuration" do
|
62
|
+
ENV["MYSQL_DATABASE"] = "other"
|
63
|
+
|
64
|
+
SecretConfig.check_env_var = false
|
65
|
+
SecretConfig.use :file, path: path, file_name: file_name
|
66
|
+
assert_equal "secret_config_test", SecretConfig.fetch("mysql/database")
|
67
|
+
end
|
50
68
|
end
|
51
69
|
end
|
52
70
|
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
module SecretConfig
|
3
|
+
class SettingInterpolatorTest < Minitest::Test
|
4
|
+
describe SettingInterpolator do
|
5
|
+
let(:interpolator) { SettingInterpolator.new }
|
6
|
+
|
7
|
+
describe '#parse' do
|
8
|
+
it "handles good key" do
|
9
|
+
string = "Set a date of %{date} here."
|
10
|
+
expected = string.gsub("%{date}", Date.today.strftime("%Y%m%d"))
|
11
|
+
actual = interpolator.parse(string)
|
12
|
+
assert_equal expected, actual, string
|
13
|
+
end
|
14
|
+
|
15
|
+
it "handles multiple keys" do
|
16
|
+
string = "%{pid}: Set a date of %{date} here and a %{time:%H%M} here and for luck %{pid}"
|
17
|
+
expected = string.gsub("%{date}", Date.today.strftime("%Y%m%d"))
|
18
|
+
expected = expected.gsub("%{time:%H%M}", Time.now.strftime("%H%M"))
|
19
|
+
expected = expected.gsub("%{pid}", $$.to_s)
|
20
|
+
actual = interpolator.parse(string)
|
21
|
+
assert_equal expected, actual, string
|
22
|
+
end
|
23
|
+
|
24
|
+
it "handles bad key" do
|
25
|
+
string = "Set a date of %{blah} here."
|
26
|
+
assert_raises InvalidInterpolation do
|
27
|
+
interpolator.parse(string)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#date" do
|
33
|
+
it 'interpolates date only' do
|
34
|
+
string = "%{date}"
|
35
|
+
expected = Date.today.strftime("%Y%m%d")
|
36
|
+
actual = interpolator.parse(string)
|
37
|
+
assert_equal expected, actual, string
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'interpolates date' do
|
41
|
+
string = "Set a date of %{date} here."
|
42
|
+
expected = string.gsub("%{date}", Date.today.strftime("%Y%m%d"))
|
43
|
+
actual = interpolator.parse(string)
|
44
|
+
assert_equal expected, actual, string
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'interpolates date with custom format' do
|
48
|
+
string = "Set a custom %{date:%m%d%Y} here."
|
49
|
+
expected = string.gsub("%{date:%m%d%Y}", Date.today.strftime("%m%d%Y"))
|
50
|
+
actual = interpolator.parse(string)
|
51
|
+
assert_equal expected, actual, string
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#time" do
|
56
|
+
it 'interpolates time only' do
|
57
|
+
string = "%{time}"
|
58
|
+
time = Time.now
|
59
|
+
Time.stub(:now, time) do
|
60
|
+
expected = Time.now.strftime("%Y%m%d%H%M%S%L")
|
61
|
+
actual = interpolator.parse(string)
|
62
|
+
assert_equal expected, actual, string
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'interpolates time' do
|
67
|
+
string = "Set a time of %{time} here."
|
68
|
+
time = Time.now
|
69
|
+
Time.stub(:now, time) do
|
70
|
+
expected = string.gsub("%{time}", Time.now.strftime("%Y%m%d%H%M%S%L"))
|
71
|
+
actual = interpolator.parse(string)
|
72
|
+
assert_equal expected, actual, string
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'interpolates time with custom format' do
|
77
|
+
string = "Set a custom time of %{time:%H%M} here."
|
78
|
+
expected = string.gsub("%{time:%H%M}", Time.now.strftime("%H%M"))
|
79
|
+
actual = interpolator.parse(string)
|
80
|
+
assert_equal expected, actual, string
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#env" do
|
85
|
+
before do
|
86
|
+
ENV["TEST_SETTING"] = "Secret"
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'fetches existing ENV var' do
|
90
|
+
string = "%{env:TEST_SETTING}"
|
91
|
+
actual = interpolator.parse(string)
|
92
|
+
assert_equal "Secret", actual, string
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'fetches existing ENV var into a larger string' do
|
96
|
+
string = "Hello %{env:TEST_SETTING}. How are you?"
|
97
|
+
actual = interpolator.parse(string)
|
98
|
+
expected = string.gsub("%{env:TEST_SETTING}", "Secret")
|
99
|
+
assert_equal expected, actual, string
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'handles missing ENV var' do
|
103
|
+
string = "%{env:OTHER_TEST_SETTING}"
|
104
|
+
actual = interpolator.parse(string)
|
105
|
+
assert_equal "", actual, string
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#hostname" do
|
110
|
+
it 'returns hostname' do
|
111
|
+
string = "%{hostname}"
|
112
|
+
actual = interpolator.parse(string)
|
113
|
+
assert_equal Socket.gethostname, actual, string
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'returns short hostname' do
|
117
|
+
string = "%{hostname:short}"
|
118
|
+
actual = interpolator.parse(string)
|
119
|
+
assert_equal Socket.gethostname.split('.')[0], actual, string
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "#pid" do
|
124
|
+
it 'returns process id' do
|
125
|
+
string = "%{pid}"
|
126
|
+
actual = interpolator.parse(string)
|
127
|
+
assert_equal $$.to_s, actual, string
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe "#random" do
|
132
|
+
it 'interpolates random 32 byte string' do
|
133
|
+
string = "%{random}"
|
134
|
+
random = SecureRandom.urlsafe_base64(32)
|
135
|
+
SecureRandom.stub(:urlsafe_base64, random) do
|
136
|
+
actual = interpolator.parse(string)
|
137
|
+
assert_equal random, actual, string
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'interpolates custom length random string' do
|
142
|
+
string = "%{random:64}"
|
143
|
+
random = SecureRandom.urlsafe_base64(64)
|
144
|
+
SecureRandom.stub(:urlsafe_base64, random) do
|
145
|
+
actual = interpolator.parse(string)
|
146
|
+
assert_equal random, actual, string
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secret_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -44,6 +44,8 @@ files:
|
|
44
44
|
- lib/secret_config/providers/ssm.rb
|
45
45
|
- lib/secret_config/railtie.rb
|
46
46
|
- lib/secret_config/registry.rb
|
47
|
+
- lib/secret_config/setting_interpolator.rb
|
48
|
+
- lib/secret_config/string_interpolator.rb
|
47
49
|
- lib/secret_config/utils.rb
|
48
50
|
- lib/secret_config/version.rb
|
49
51
|
- test/config/application.yml
|
@@ -51,6 +53,7 @@ files:
|
|
51
53
|
- test/providers/ssm_test.rb
|
52
54
|
- test/registry_test.rb
|
53
55
|
- test/secret_config_test.rb
|
56
|
+
- test/setting_interpolator_test.rb
|
54
57
|
- test/test_helper.rb
|
55
58
|
- test/utils_test.rb
|
56
59
|
homepage: https://github.com/rocketjob/secret_config
|
@@ -81,6 +84,7 @@ test_files:
|
|
81
84
|
- test/providers/ssm_test.rb
|
82
85
|
- test/providers/file_test.rb
|
83
86
|
- test/registry_test.rb
|
87
|
+
- test/setting_interpolator_test.rb
|
84
88
|
- test/test_helper.rb
|
85
89
|
- test/utils_test.rb
|
86
90
|
- test/secret_config_test.rb
|