nuclear_secrets 1.0.1 → 1.0.2
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 +16 -1
- data/lib/nuclear_secrets.rb +55 -38
- data/lib/nuclear_secrets/errors.rb +84 -0
- data/lib/nuclear_secrets/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 175b07894161bdae17411c570da95b2378fb64a8
|
4
|
+
data.tar.gz: ed3c759584c3e898ecf93461df2a6705c1d76368
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e57fb6daf72613508d0008fe2a20a3a5f2109856b61a840fa764d5f62c10fb15d2274d153b52d94e90aaf54bff78b3b18e0df1e1a1a42b201ff705155c140ab
|
7
|
+
data.tar.gz: 1c71339468af3cc4f234991b9e6a7d4fdf5fa863c67eadb99ae9fc419413c64e784684aefb5e5ed2aaf8c327d4b1e9c87b50501c610cac72948148f7da4b6f4b
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Nuclear Secrets
|
2
2
|
Quell rails secret espionage by verifying what secrets exist and their types in your rails application
|
3
3
|
|
4
4
|
## Usage
|
@@ -30,6 +30,21 @@ end
|
|
30
30
|
```
|
31
31
|
Include all secrets that your application utilizes, and their types, in `required_secrets` hash
|
32
32
|
|
33
|
+
## Advanced Usage
|
34
|
+
In addition to being able to supply NuclearSecrets with the type of a secret,
|
35
|
+
you can also pass a Proc or a Lambda. If the proc or lamba returns true when
|
36
|
+
passed the value of the secret, then the secret will be allowed.
|
37
|
+
|
38
|
+
```
|
39
|
+
NuclearSecrets.configure do |config|
|
40
|
+
config.required_secrets = {
|
41
|
+
my_string_secret: String,
|
42
|
+
my_numeric_secret: Fixnum,
|
43
|
+
my_secret: Proc.new { |secret| secret.is_worthy? }
|
44
|
+
}
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
33
48
|
## Contributing
|
34
49
|
Contribution directions go here.
|
35
50
|
|
data/lib/nuclear_secrets.rb
CHANGED
@@ -1,61 +1,78 @@
|
|
1
1
|
require "nuclear_secrets/engine"
|
2
|
+
require "nuclear_secrets/errors"
|
2
3
|
|
3
4
|
module NuclearSecrets
|
4
|
-
class
|
5
|
-
|
6
|
-
@secrets = secrets
|
7
|
-
end
|
8
|
-
|
9
|
-
def get_error_list
|
10
|
-
@secrets.reduce("") do |message, current|
|
11
|
-
message << "#{current.first} of type #{current.last} \n"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
5
|
+
class << self
|
6
|
+
attr_accessor(:required_secrets)
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
"You must include a required_secrets key in your config/secrets.yml file"
|
8
|
+
def configure
|
9
|
+
yield self if block_given?
|
19
10
|
end
|
20
|
-
end
|
21
11
|
|
22
|
-
|
23
|
-
|
24
|
-
super(secrets: secrets)
|
12
|
+
def make_type_check(type)
|
13
|
+
Proc.new { |item| item.class == type }
|
25
14
|
end
|
26
15
|
|
27
|
-
|
28
|
-
|
16
|
+
# secrets: hash of given secrets
|
17
|
+
# required_values: hash of required secrets
|
18
|
+
# key: key to build tuple for
|
19
|
+
# returns [key, required_type, given_type]
|
20
|
+
def build_secret_tuple(secrets, required_values, key)
|
21
|
+
[key, required_values[key], secrets[key]]
|
29
22
|
end
|
30
|
-
end
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
def build_pairs(keys, secrets)
|
25
|
+
keys.map do |k|
|
26
|
+
build_secret_tuple(secrets, required_secrets, k)
|
27
|
+
end
|
35
28
|
end
|
36
29
|
|
37
|
-
def
|
38
|
-
|
30
|
+
def build_assertions(secrets, existing_keys)
|
31
|
+
existing_keys.map do |key|
|
32
|
+
if required_secrets[key].class == Class
|
33
|
+
make_type_check(required_secrets[key])
|
34
|
+
elsif required_secrets[key].respond_to? :call
|
35
|
+
required_secrets[key]
|
36
|
+
else
|
37
|
+
raise NuclearSecrets::InvalidRequiredSecretValue.new(
|
38
|
+
[
|
39
|
+
build_secret_tuple(secrets, required_secrets, key),
|
40
|
+
],
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
39
44
|
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class << self
|
43
|
-
attr_accessor(:required_secrets)
|
44
45
|
|
45
|
-
def
|
46
|
-
|
46
|
+
def check_assertions(secrets, assertions)
|
47
|
+
secrets.to_a.zip(assertions).select do |pair|
|
48
|
+
result = pair.last.call(pair.first[1])
|
49
|
+
if !result
|
50
|
+
pair.first[0]
|
51
|
+
else
|
52
|
+
false
|
53
|
+
end
|
54
|
+
end.map do |pair|
|
55
|
+
flat_pair = pair.flatten
|
56
|
+
build_secret_tuple(secrets, required_secrets, flat_pair.first)
|
57
|
+
end
|
47
58
|
end
|
48
59
|
|
49
60
|
def check_secrets(secrets)
|
50
61
|
raise NuclearSecrets::RequiredSecretsListMissing if required_secrets.nil?
|
51
|
-
|
52
|
-
|
62
|
+
req_keys = required_secrets.keys
|
63
|
+
existing_keys = secrets.keys
|
64
|
+
|
65
|
+
missing_keys = req_keys - existing_keys
|
66
|
+
extra_keys = existing_keys - req_keys
|
53
67
|
|
54
|
-
|
55
|
-
|
68
|
+
missing_pairs = build_pairs(missing_keys, secrets)
|
69
|
+
extra_pairs = build_pairs(extra_keys, secrets)
|
70
|
+
raise SecretsMissingError.new(missing_pairs) unless missing_keys.empty?
|
71
|
+
raise ExtraSecretsError.new(extra_pairs) unless extra_keys.empty?
|
56
72
|
|
57
|
-
|
58
|
-
|
73
|
+
assertions = build_assertions(secrets, existing_keys)
|
74
|
+
error_pairs = check_assertions(secrets, assertions)
|
75
|
+
raise MismatchedSecretType.new(error_pairs) if !error_pairs.empty?
|
59
76
|
end
|
60
77
|
end
|
61
78
|
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module NuclearSecrets
|
2
|
+
class NuclearSecretError < StandardError
|
3
|
+
def initialize(secrets: [])
|
4
|
+
@secrets = secrets
|
5
|
+
end
|
6
|
+
|
7
|
+
def required_type_message(req_type)
|
8
|
+
if req_type.nil?
|
9
|
+
" of value nil"
|
10
|
+
elsif req_type.class == Class
|
11
|
+
" of type #{req_type}"
|
12
|
+
elsif req_type.class == Proc
|
13
|
+
source_pair = req_type.source_location
|
14
|
+
" of type Proc (defined in file: #{source_pair.first}, line: #{source_pair.last})"
|
15
|
+
else
|
16
|
+
" of value #{req_type}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def given_type_message(given_type)
|
21
|
+
if given_type.nil?
|
22
|
+
"\n"
|
23
|
+
elsif given_type.class == String
|
24
|
+
" was given \"#{given_type}\"\n"
|
25
|
+
else
|
26
|
+
" was given #{given_type}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_error_list
|
31
|
+
@secrets.reduce("") do |message, current|
|
32
|
+
message << current.first.to_s
|
33
|
+
message << required_type_message(current[1])
|
34
|
+
message << given_type_message(current.last)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class RequiredSecretsListMissing < NuclearSecretError
|
40
|
+
def message
|
41
|
+
"You must include a NuclearSecrets initializer in your app"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class SecretsMissingError < NuclearSecretError
|
46
|
+
def initialize(secrets)
|
47
|
+
super(secrets: secrets)
|
48
|
+
end
|
49
|
+
|
50
|
+
def message
|
51
|
+
"You are not using a secret that is required in the secrets list: \n#{get_error_list}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class ExtraSecretsError < NuclearSecretError
|
56
|
+
def initialize(secrets)
|
57
|
+
super(secrets: secrets)
|
58
|
+
end
|
59
|
+
|
60
|
+
def message
|
61
|
+
"You have used a secret that is not in included in the secrets list: \n#{get_error_list}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class InvalidRequiredSecretValue < NuclearSecretError
|
66
|
+
def initialize(secrets)
|
67
|
+
super(secrets: secrets)
|
68
|
+
end
|
69
|
+
|
70
|
+
def message
|
71
|
+
"You used an invalid secret: \n#{get_error_list}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class MismatchedSecretType < NuclearSecretError
|
76
|
+
def initialize(secrets)
|
77
|
+
super(secrets: secrets)
|
78
|
+
end
|
79
|
+
|
80
|
+
def message
|
81
|
+
"You included a secret of the wrong type: \n#{get_error_list}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nuclear_secrets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atomic Jolt
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- config/initializers/nuclear_secrets.rb
|
53
53
|
- lib/nuclear_secrets.rb
|
54
54
|
- lib/nuclear_secrets/engine.rb
|
55
|
+
- lib/nuclear_secrets/errors.rb
|
55
56
|
- lib/nuclear_secrets/version.rb
|
56
57
|
homepage: https://github.com/atomicjolt/NuclearSecrets
|
57
58
|
licenses:
|
@@ -73,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
74
|
version: '0'
|
74
75
|
requirements: []
|
75
76
|
rubyforge_project:
|
76
|
-
rubygems_version: 2.6.
|
77
|
+
rubygems_version: 2.6.11
|
77
78
|
signing_key:
|
78
79
|
specification_version: 4
|
79
80
|
summary: Quell rails secret espionage by verifying what secrets exist and their types
|