secrets-manager 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 2.0.2
data/CHANGELOG.md ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in secrets-manager.gemspec
4
+ gemspec
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -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,3 @@
1
+ module SecretsManager
2
+ VERSION = "1.0.0"
3
+ end
@@ -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: []