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