secrets-manager 1.0.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +51 -0
- data/README.md +71 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/secrets-manager.rb +100 -0
- data/lib/version.rb +3 -0
- data/secrets-manager.gemspec +34 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9881f60a1a1f81f48e84d02a99ce4b99970ef8ca534415fb4b3a343833264609
|
4
|
+
data.tar.gz: 5203cca0dc0456e337e073fe141cf4f850bf2e680aef2952c2a3833505e0417a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc8fca98711dcd170126c276da1809ab266d699726d8469712c3e0299acf833b798dacd6834a0ba56cbfb6c0450cf9c90ff45ecb1cb7dfb198b7baf5965f6c39
|
7
|
+
data.tar.gz: ceb8a360399a5bdf04c2ef38969ba88537a231b2a4b0c3f2066798e59adbed67fe5f8662bbf46dec2cc269b74e2324ab25d1d782d2ec7f5020f89308e1daefab
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
secrets-manager (1.0.0)
|
5
|
+
aws-sdk-secretsmanager (>= 1.31.0)
|
6
|
+
concurrent-ruby (>= 1.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
aws-eventstream (1.0.3)
|
12
|
+
aws-partitions (1.213.0)
|
13
|
+
aws-sdk-core (3.68.0)
|
14
|
+
aws-eventstream (~> 1.0, >= 1.0.2)
|
15
|
+
aws-partitions (~> 1.0)
|
16
|
+
aws-sigv4 (~> 1.1)
|
17
|
+
jmespath (~> 1.0)
|
18
|
+
aws-sdk-secretsmanager (1.31.0)
|
19
|
+
aws-sdk-core (~> 3, >= 3.61.1)
|
20
|
+
aws-sigv4 (~> 1.1)
|
21
|
+
aws-sigv4 (1.1.0)
|
22
|
+
aws-eventstream (~> 1.0, >= 1.0.2)
|
23
|
+
concurrent-ruby (1.1.5)
|
24
|
+
diff-lcs (1.3)
|
25
|
+
jmespath (1.4.0)
|
26
|
+
rake (10.5.0)
|
27
|
+
rspec (3.8.0)
|
28
|
+
rspec-core (~> 3.8.0)
|
29
|
+
rspec-expectations (~> 3.8.0)
|
30
|
+
rspec-mocks (~> 3.8.0)
|
31
|
+
rspec-core (3.8.2)
|
32
|
+
rspec-support (~> 3.8.0)
|
33
|
+
rspec-expectations (3.8.4)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.8.0)
|
36
|
+
rspec-mocks (3.8.1)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.8.0)
|
39
|
+
rspec-support (3.8.2)
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
bundler (~> 2.0)
|
46
|
+
rake (~> 10.0)
|
47
|
+
rspec (~> 3.0)
|
48
|
+
secrets-manager!
|
49
|
+
|
50
|
+
BUNDLED WITH
|
51
|
+
2.0.2
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# SecretsManager.rb
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem 'secrets-manager'
|
9
|
+
```
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install secrets-manager
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
To use this gem, you must have an AWS account and permissions to setup secret values using [Secrets Manager](https://aws.amazon.com/secrets-manager/)
|
22
|
+
|
23
|
+
This gem makes assumptions and has requirements about how you should be storing your secrets.
|
24
|
+
|
25
|
+
### Path Name
|
26
|
+
This gem uses the concept of env specific secrets within the same account. While separate AWS accounts can be used to maintain separation, it can be desirable to use a single account.
|
27
|
+
|
28
|
+
The path format is as follows: `{{secret_env}}/{{secret_path}}`. When using this gem you would leave the `secret_env` out of your request.
|
29
|
+
|
30
|
+
For example, to access the secret `twlio-key`, `$secrets.fetch('twilio-key')`. This would be stored in AWS SM as `dev/twilio-key`.
|
31
|
+
|
32
|
+
### Payload
|
33
|
+
This gem expects your secret value to be a JSON object. The only required key is `value`. The following keys are optional:
|
34
|
+
* `ttl` - Time to live in seconds. Describes how long the secret should live in in-memory cache.
|
35
|
+
* `encoding` - Currently, only `base64` is supported as a value. If your `value` is base64 encoded, this will result in a returned secret that is base64 decoded.
|
36
|
+
|
37
|
+
Example:
|
38
|
+
```
|
39
|
+
{"value": "secretvalue", "ttl": 60} // Will live in cache for 60 seconds.
|
40
|
+
```
|
41
|
+
|
42
|
+
```
|
43
|
+
{"value": "c2VjcmV0dmFsdWU=", "ttl": 60, "encoding": "base64"} // Will live in cache for 60 seconds and is base64 encoded. Result will be "secretvalue"
|
44
|
+
```
|
45
|
+
|
46
|
+
### Configuration
|
47
|
+
The follow ENV vars are expected:
|
48
|
+
* `AWS_SECRETS_ENV` - preceeds all path lookups, ex: `dev`, `staging`, `qa`, `production`
|
49
|
+
* `AWS_SECRETS_KEY` - AWS IAM access key
|
50
|
+
* `AWS_SECRETS_SECRET` - AWS IAM access secret
|
51
|
+
|
52
|
+
The manager should be created at boot time, in an initializer for example, and stored as a constant or global.
|
53
|
+
```
|
54
|
+
$secrets = SecretsManager.new
|
55
|
+
```
|
56
|
+
|
57
|
+
### Lookup
|
58
|
+
```
|
59
|
+
$secrets.fetch('services/twilio/api-key')
|
60
|
+
$secrets['services/twilio/api-key']
|
61
|
+
```
|
62
|
+
|
63
|
+
## Development
|
64
|
+
|
65
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
66
|
+
|
67
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
68
|
+
|
69
|
+
## Contributing
|
70
|
+
|
71
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/secrets-manager.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "secrets-manager"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "version"
|
4
|
+
require "aws-sdk-secretsmanager"
|
5
|
+
require "concurrent-ruby"
|
6
|
+
require "json"
|
7
|
+
|
8
|
+
module SecretsManager
|
9
|
+
class SecretNotFound < StandardError; end;
|
10
|
+
|
11
|
+
def self.new(**args)
|
12
|
+
Manager.new(**args)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Cache
|
16
|
+
def initialize
|
17
|
+
@_cache = Concurrent::Map.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
@_cache = Concurrent::Map.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def set(path, value, ttl = 86400)
|
25
|
+
@_cache[path] = {expires_at: (Time.now + ttl), value: value}
|
26
|
+
return self
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(path)
|
30
|
+
fetched = @_cache[path]
|
31
|
+
return unless fetched
|
32
|
+
return unless !fetched[:expires_at].nil? && (fetched[:expires_at]) > Time.now
|
33
|
+
fetched[:value]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Manager
|
38
|
+
attr_reader :cache
|
39
|
+
|
40
|
+
def initialize(client: nil)
|
41
|
+
@cache = Cache.new
|
42
|
+
@aws_client = client
|
43
|
+
end
|
44
|
+
|
45
|
+
def secret_env
|
46
|
+
ENV['AWS_SECRETS_ENV'] || ENV['RACK_ENV'] || dev
|
47
|
+
end
|
48
|
+
|
49
|
+
def client
|
50
|
+
return @aws_client if @aws_client
|
51
|
+
|
52
|
+
@_client ||= Aws::SecretsManager::Client.new({
|
53
|
+
region: ENV.fetch('AWS_SECRETS_REGION', 'us-east-1'),
|
54
|
+
credentials: Aws::Credentials.new(ENV['AWS_SECRETS_KEY'], ENV['AWS_SECRETS_SECRET'])
|
55
|
+
})
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch(secret_path)
|
59
|
+
resolved_path = secret_env + '/' + secret_path
|
60
|
+
|
61
|
+
cached_value = cache.find(resolved_path)
|
62
|
+
return cached_value if cached_value
|
63
|
+
|
64
|
+
response = client.get_secret_value(secret_id: resolved_path)
|
65
|
+
return nil unless response && response.secret_string
|
66
|
+
object = JSON.parse(response.secret_string, symbolize_names: true)
|
67
|
+
|
68
|
+
value = parse_value(object)
|
69
|
+
set_in_memory(resolved_path, value, parse_ttl(object))
|
70
|
+
return value
|
71
|
+
rescue Aws::SecretsManager::Errors::ResourceNotFoundException => e
|
72
|
+
raise SecretsManager::SecretNotFound, "Could not find secret with path #{resolved_path}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def [](path)
|
76
|
+
fetch(path)
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def parse_ttl(data)
|
81
|
+
## Default to one day cache TTL
|
82
|
+
return 86400 unless data[:ttl].present?
|
83
|
+
data[:ttl].to_i
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_value(data)
|
87
|
+
value = data[:value]
|
88
|
+
|
89
|
+
if data[:encoding].present?
|
90
|
+
case data[:encoding]
|
91
|
+
when "base64"
|
92
|
+
value = Base64.strict_decode64(value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
return value
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "secrets-manager"
|
7
|
+
spec.version = SecretsManager::VERSION
|
8
|
+
spec.authors = ["Christopher Ostrowski", "Matt Hooks", "Evan Waters"]
|
9
|
+
spec.email = ["chris@dutchie.com", "matt.hooks@dutchie.com", "evan.waters@dutchie.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Ruby + AWS Secrets Manager}
|
12
|
+
spec.description = %q{Ruby AWS Secrets Manager interface. Allows for env specific secrets, in-memory caching with custom TTL, file storage, and simple API.}
|
13
|
+
spec.homepage = "https://github.com/GetDutchie/SecretsManager"
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.com/GetDutchie/SecretsManager.git"
|
17
|
+
spec.metadata["changelog_uri"] = "https://github.com/GetDutchie/SecretsManager/blob/master/CHANGELOG.md"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = "exe"
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_dependency "concurrent-ruby", ">= 1.0"
|
29
|
+
spec.add_dependency 'aws-sdk-secretsmanager', '>= 1.31.0'
|
30
|
+
|
31
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: secrets-manager
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christopher Ostrowski
|
8
|
+
- Matt Hooks
|
9
|
+
- Evan Waters
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2019-09-17 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: concurrent-ruby
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '1.0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: aws-sdk-secretsmanager
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.31.0
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.31.0
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: bundler
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '2.0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '2.0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rake
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '10.0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '10.0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rspec
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '3.0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - "~>"
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '3.0'
|
85
|
+
description: Ruby AWS Secrets Manager interface. Allows for env specific secrets,
|
86
|
+
in-memory caching with custom TTL, file storage, and simple API.
|
87
|
+
email:
|
88
|
+
- chris@dutchie.com
|
89
|
+
- matt.hooks@dutchie.com
|
90
|
+
- evan.waters@dutchie.com
|
91
|
+
executables: []
|
92
|
+
extensions: []
|
93
|
+
extra_rdoc_files: []
|
94
|
+
files:
|
95
|
+
- ".gitignore"
|
96
|
+
- ".rspec"
|
97
|
+
- ".travis.yml"
|
98
|
+
- CHANGELOG.md
|
99
|
+
- Gemfile
|
100
|
+
- Gemfile.lock
|
101
|
+
- README.md
|
102
|
+
- Rakefile
|
103
|
+
- bin/console
|
104
|
+
- bin/setup
|
105
|
+
- lib/secrets-manager.rb
|
106
|
+
- lib/version.rb
|
107
|
+
- secrets-manager.gemspec
|
108
|
+
homepage: https://github.com/GetDutchie/SecretsManager
|
109
|
+
licenses: []
|
110
|
+
metadata:
|
111
|
+
homepage_uri: https://github.com/GetDutchie/SecretsManager
|
112
|
+
source_code_uri: https://github.com/GetDutchie/SecretsManager.git
|
113
|
+
changelog_uri: https://github.com/GetDutchie/SecretsManager/blob/master/CHANGELOG.md
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
require_paths:
|
117
|
+
- lib
|
118
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
requirements:
|
125
|
+
- - ">="
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
requirements: []
|
129
|
+
rubygems_version: 3.0.3
|
130
|
+
signing_key:
|
131
|
+
specification_version: 4
|
132
|
+
summary: Ruby + AWS Secrets Manager
|
133
|
+
test_files: []
|