secret_config 0.6.4 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|