settings_reader-vault_resolver 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 684115b87887c0d2774679160f1f0d7d7136035053b3af87a9878fd5ab4b5778
4
- data.tar.gz: 9d3747fdd02285d0664569ec73566951637aeb1c145223da5be9239078c4a6cf
3
+ metadata.gz: 16ca7880831b27b05c24651940a1dab796b792f7d98229f2f01e229ffcee5662
4
+ data.tar.gz: ff8e434b0512ce66772e8f99b16761ea51597614b195abb91889a5543ba88267
5
5
  SHA512:
6
- metadata.gz: 3b7b5512574b61c2b7fd96fdf121152938c7c232e12c8da23a864f52db1502501406dec213e28eec118decdfe142f7f90dbcd1748ae551558583691af26de97f
7
- data.tar.gz: 81f2e979bee9b9cfca5ec316c4218bc2260042875eab9fc580443e0d4edcd159299c64398b17ddc12fe9a25aac545d6f217cabd5f71e146fe1c4eb6c31033e4d
6
+ metadata.gz: e1476c785e7369a2a2f3d4ee47a149cfd3c1fc2ebf333a94a1ec158c564584995ced9392fa08e1be9ec16ba166c0f20899414e02622473a4d0058ef5d70abce2
7
+ data.tar.gz: 8c1a40bd635b8e9de7193114618a0669e3c9d3ffabae250ff5efc416a31636c199584bb7e474373ead29bde9e85e281adbba0e7ba123358e1729d0e599bf17bf
@@ -0,0 +1,52 @@
1
+ name: "linters"
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+ schedule:
9
+ - cron: '30 0 * * 1'
10
+
11
+ jobs:
12
+ rubocop:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v2
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: 2.5
22
+ bundler-cache: true
23
+ - name: Run rubocop
24
+ run: bundle exec rubocop --parallel
25
+
26
+ code-ql:
27
+ name: Analyze
28
+ runs-on: ubuntu-latest
29
+ permissions:
30
+ actions: read
31
+ contents: read
32
+ security-events: write
33
+
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ language: [ 'ruby' ]
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v2
42
+
43
+ - name: Initialize CodeQL
44
+ uses: github/codeql-action/init@v1
45
+ with:
46
+ languages: ${{ matrix.language }}
47
+
48
+ - name: Autobuild
49
+ uses: github/codeql-action/autobuild@v1
50
+
51
+ - name: Perform CodeQL Analysis
52
+ uses: github/codeql-action/analyze@v1
@@ -13,6 +13,7 @@ jobs:
13
13
  build:
14
14
  env:
15
15
  COVERAGE: true
16
+ CODECOV_TOKEN: a0c859b6-dfb7-4d9f-9933-2dd945cdd960
16
17
  VAULT_ADDR: 'http://127.0.0.1:8200'
17
18
  VAULT_TOKEN: 'vault_root_token'
18
19
 
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ SuggestExtensions: false
4
+ TargetRubyVersion: 2.5
5
+
6
+ Gemspec/RequireMFA:
7
+ Enabled: false
8
+
9
+ Style/FrozenStringLiteralComment:
10
+ Enabled: false
11
+
12
+ Metrics/BlockLength:
13
+ IgnoredMethods: ['describe', 'context']
14
+
15
+ Layout/LineLength:
16
+ Max: 120
data/.simplecov CHANGED
@@ -1,4 +1,4 @@
1
- if ENV["COVERAGE"]
1
+ if ENV['COVERAGE']
2
2
  require 'simplecov'
3
3
  require 'codecov'
4
4
  SimpleCov.start do
@@ -6,4 +6,4 @@ if ENV["COVERAGE"]
6
6
  primary_coverage :branch
7
7
  formatter SimpleCov::Formatter::Codecov
8
8
  end
9
- end
9
+ end
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.0]
3
+ ## [0.2.1]
4
+ ### Fixes
5
+ - Use default k8s auth route without namespace
6
+
7
+ ## [0.2.0]
8
+ ### New features
9
+ - Better integration with parent gem
10
+ - Support of k8s authentication method
11
+ - Additional tests and fixes related to Vault permissions
12
+
13
+ ## [0.1.1]
4
14
  ### Fixes
5
15
  - Fix CI release
6
16
  - Add changelog
@@ -11,7 +21,9 @@
11
21
  - Secrets caching
12
22
  - Automatic secrets lease renewal
13
23
 
14
- [Unreleased]: https://github.com/matic-insurance/settings_reader-vault_resolver/compare/0.1.1...HEAD
15
- [0.1.0]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.1.1
24
+ [Unreleased]: https://github.com/matic-insurance/settings_reader-vault_resolver/compare/0.2.1...HEAD
25
+ [0.2.1]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.2.1
26
+ [0.2.0]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.2.0
27
+ [0.1.1]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.1.1
16
28
  [0.1.0]: https://github.com/matic-insurance/settings_reader-vault_resolver/commits/0.1.0
17
29
 
data/Gemfile CHANGED
@@ -1,4 +1,12 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in settings_reader-vault_resolver.gemspec
4
4
  gemspec
5
+
6
+ gem 'codecov'
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ gem 'rubocop'
10
+ gem 'rubocop-rspec'
11
+ gem 'simplecov'
12
+ gem 'timecop'
data/Gemfile.lock CHANGED
@@ -3,6 +3,7 @@ PATH
3
3
  specs:
4
4
  settings_reader-vault_resolver (0.0.0)
5
5
  concurrent-ruby (~> 1.1)
6
+ settings_reader (~> 0.1)
6
7
  vault (~> 0.16)
7
8
 
8
9
  GEM
@@ -18,11 +19,11 @@ GEM
18
19
  diff-lcs (1.5.0)
19
20
  docile (1.4.0)
20
21
  parallel (1.21.0)
21
- parser (3.1.0.0)
22
+ parser (3.1.1.0)
22
23
  ast (~> 2.4.1)
23
- rainbow (3.0.0)
24
+ rainbow (3.1.1)
24
25
  rake (13.0.6)
25
- regexp_parser (2.2.0)
26
+ regexp_parser (2.2.1)
26
27
  rexml (3.2.5)
27
28
  rspec (3.10.0)
28
29
  rspec-core (~> 3.10.0)
@@ -37,20 +38,21 @@ GEM
37
38
  diff-lcs (>= 1.2.0, < 2.0)
38
39
  rspec-support (~> 3.10.0)
39
40
  rspec-support (3.10.3)
40
- rubocop (0.93.1)
41
+ rubocop (1.25.1)
41
42
  parallel (~> 1.10)
42
- parser (>= 2.7.1.5)
43
+ parser (>= 3.1.0.0)
43
44
  rainbow (>= 2.2.2, < 4.0)
44
- regexp_parser (>= 1.8)
45
+ regexp_parser (>= 1.8, < 3.0)
45
46
  rexml
46
- rubocop-ast (>= 0.6.0)
47
+ rubocop-ast (>= 1.15.1, < 2.0)
47
48
  ruby-progressbar (~> 1.7)
48
- unicode-display_width (>= 1.4.0, < 2.0)
49
- rubocop-ast (1.15.1)
50
- parser (>= 3.0.1.1)
49
+ unicode-display_width (>= 1.4.0, < 3.0)
50
+ rubocop-ast (1.16.0)
51
+ parser (>= 3.1.1.0)
51
52
  rubocop-rspec (1.32.0)
52
53
  rubocop (>= 0.60.0)
53
54
  ruby-progressbar (1.11.0)
55
+ settings_reader (0.1.0)
54
56
  simplecov (0.21.2)
55
57
  docile (~> 1.1)
56
58
  simplecov-html (~> 0.11)
@@ -58,7 +60,7 @@ GEM
58
60
  simplecov-html (0.12.3)
59
61
  simplecov_json_formatter (0.1.3)
60
62
  timecop (0.9.4)
61
- unicode-display_width (1.8.0)
63
+ unicode-display_width (2.1.0)
62
64
  vault (0.16.0)
63
65
  aws-sigv4
64
66
 
@@ -66,15 +68,14 @@ PLATFORMS
66
68
  ruby
67
69
 
68
70
  DEPENDENCIES
69
- bundler (~> 2.0)
70
- codecov (~> 0.4)
71
- rake (~> 13.0)
72
- rspec (~> 3.0)
73
- rubocop (~> 0.66)
74
- rubocop-rspec (~> 1.32.0)
71
+ codecov
72
+ rake
73
+ rspec
74
+ rubocop
75
+ rubocop-rspec
75
76
  settings_reader-vault_resolver!
76
- simplecov (~> 0.16)
77
- timecop (~> 0.9)
77
+ simplecov
78
+ timecop
78
79
 
79
80
  BUNDLED WITH
80
81
  2.1.4
data/README.md CHANGED
@@ -26,20 +26,13 @@ At the load of application when initializing `settings_reader`:
26
26
  Vault.address = 'http://127.0.0.1:8200'
27
27
  Vault.token = 'MY_SUPER_SECRET_TOKEN'
28
28
 
29
- #Init Settings Reader
30
- SettingsReader.configure do |config|
31
- config.settings_providers = [
32
- SettingsReader::Providers::Yaml,
33
- ]
34
-
35
- config.value_resolvers = [
36
- SettingsReader::Resolvers::Vault,
37
- SettingsReader::Resolvers::Env,
38
- ]
29
+ #Load Settings Reader and configure resolver
30
+ AppSettings = SettingsReader.load do |config|
31
+ # ... Other configurations
32
+
33
+ # Add vault resolver as one of resolvers
34
+ config.resolvers << SettingsReader::VaultResolver.resolver
39
35
  end
40
-
41
- #Load Settings
42
- APP_SETTINGS = SettingsReader.load
43
36
  ```
44
37
 
45
38
  ### Usage
@@ -51,16 +44,22 @@ Assuming your settings has following structure:
51
44
  app:
52
45
  name: 'MyCoolApp'
53
46
  hostname: 'http://localhost:3001'
54
- secret: 'vault://secret/apps/my_cool_app#app_secret'
47
+ static_secret: 'vault://secret/apps/my_cool_app#app_secret'
48
+ dynamic_secret: 'vault://database/creds/app-db#username'
55
49
  ```
56
50
 
57
51
  When requesting `app/secret` from `SettingsReader` it will resolve in Vault as:
58
52
 
59
53
  ```ruby
60
- secret = APP_SETTINGS.get('app/secret')
54
+ secret = AppSettings.get('app/static_secret')
61
55
  # Gem will read `vault://secret/app#secret` from YAML
62
56
  # Gem will resolve value in Vault using Vault.kv('secret').read('apps/my_cool_app')
63
57
  # Gem will return `app_secret` attribute from the secret resolved above
58
+
59
+ db_user = AppSettings.get('app/dynamic_secret')
60
+ # Gem will request dynamic credentials from `vault://database/creds/app-db` and cache them
61
+ # Gem will renew lease on retrieved credentials 3 minutes prior lease expiration from vault
62
+ # Gem will return `username` attribute from dynamic secret
64
63
  ```
65
64
 
66
65
  ## Development
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "settings_reader/vault_resolver"
3
+ require 'bundler/setup'
4
+ require 'settings_reader/vault_resolver'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "settings_reader/vault_resolver"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -1,5 +1,6 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
+ # Parsing of vault address
3
4
  class Address
4
5
  def initialize(uri)
5
6
  @uri = URI.parse(uri)
@@ -10,11 +11,11 @@ module SettingsReader
10
11
  end
11
12
 
12
13
  def path
13
- @uri.path
14
+ @uri.path.delete_prefix('/')
14
15
  end
15
16
 
16
17
  def full_path
17
- "#{mount}#{path}"
18
+ "#{mount}#{@uri.path}"
18
19
  end
19
20
 
20
21
  def attribute
@@ -22,7 +23,7 @@ module SettingsReader
22
23
  end
23
24
 
24
25
  def options
25
- URI::decode_www_form(@uri.query || '').to_h
26
+ URI.decode_www_form(@uri.query || '').to_h
26
27
  end
27
28
 
28
29
  def to_s
@@ -1,5 +1,6 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
+ # Secrets cache for seamless dynamic keys and renewal operations
3
4
  class Cache
4
5
  def initialize
5
6
  @secrets = {}
@@ -42,4 +43,4 @@ module SettingsReader
42
43
  end
43
44
  end
44
45
  end
45
- end
46
+ end
@@ -1,7 +1,9 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
+ # Wrapper around vault secret object
3
4
  class Entry
4
5
  attr_reader :address, :secret
6
+
5
7
  MONTH = 30 * 60 * 60
6
8
 
7
9
  def initialize(address, secret)
@@ -32,12 +34,18 @@ module SettingsReader
32
34
  @secret = Vault.sys.renew(@secret.lease_id)
33
35
  @lease_started = Time.now
34
36
  true
37
+ rescue Vault::HTTPClientError => e
38
+ raise SettingsReader::VaultResolver::Error, e.message
35
39
  end
36
40
 
37
41
  def value_for(attribute)
38
42
  secret.data[attribute.to_sym]
39
43
  end
40
44
 
45
+ def to_s
46
+ address.to_s
47
+ end
48
+
41
49
  private
42
50
 
43
51
  def lease_duration
@@ -0,0 +1,43 @@
1
+ require_relative '../patches/authenticate'
2
+
3
+ module SettingsReader
4
+ module VaultResolver
5
+ module Helpers
6
+ # Helps with Vault authentication using kubernetes login
7
+ class K8sAuth
8
+ def call(role)
9
+ secret = Vault.auth.kubernetes(role)
10
+
11
+ cache_token_for_renewal(secret)
12
+ secret
13
+ end
14
+
15
+ private
16
+
17
+ def cache_token_for_renewal(secret)
18
+ address = SettingsReader::VaultResolver::Address.new('vault://v1/auth/token/lookup-self')
19
+ entry = SettingsReader::VaultResolver::AuthEntry.new(address, secret)
20
+ SettingsReader::VaultResolver.cache.save(entry)
21
+ entry
22
+ end
23
+ end
24
+ end
25
+
26
+ # Helps with auth token lease renewal
27
+ class AuthEntry < SettingsReader::VaultResolver::Entry
28
+ def leased?
29
+ true
30
+ end
31
+
32
+ def lease_duration
33
+ @secret.auth.lease_duration
34
+ end
35
+
36
+ def renew
37
+ Vault.client.auth_token.renew_self
38
+ @lease_started = Time.now
39
+ true
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,64 @@
1
+ require 'vault'
2
+
3
+ module SettingsReader
4
+ module VaultResolver
5
+ # Resolver class for Settings Reader
6
+ class Instance
7
+ include Logging
8
+
9
+ IDENTIFIER = 'vault://'.freeze
10
+ DATABASE_MOUNT = 'database'.freeze
11
+
12
+ def resolvable?(value, _path)
13
+ return unless value.respond_to?(:start_with?)
14
+
15
+ value.start_with?(IDENTIFIER)
16
+ end
17
+
18
+ # Expect value in format `vault://mount/path/to/secret?attribute_name`
19
+ def resolve(value, _path)
20
+ debug { "Resolving Vault secret at #{value}" }
21
+ address = SettingsReader::VaultResolver::Address.new(value)
22
+ entry = fetch_entry(address)
23
+ entry&.value_for(address.attribute)
24
+ end
25
+
26
+ # Resolve KV secret
27
+ def kv_secret(address)
28
+ debug { "Fetching new kv secret at: #{address}" }
29
+ Vault.kv(address.mount).read(address.path)
30
+ rescue Vault::HTTPClientError => e
31
+ error { "Error retrieving secret at: #{address}: #{e.message}" }
32
+ raise SettingsReader::VaultResolver::Error, e.message
33
+ end
34
+
35
+ def database_secret(address)
36
+ debug { "Fetching new database secret at: #{address}" }
37
+ Vault.logical.read(address.full_path)
38
+ rescue Vault::HTTPClientError => e
39
+ error { "Error retrieving database secret: #{address}: #{e.message}" }
40
+ return nil if e.message.include?('* unknown role')
41
+
42
+ raise SettingsReader::VaultResolver::Error, e.message
43
+ end
44
+
45
+ private
46
+
47
+ def fetch_entry(address)
48
+ cache.fetch(address) do
49
+ info { "Retrieving new secret at: #{address}" }
50
+ if (secret = address.mount == DATABASE_MOUNT ? database_secret(address) : kv_secret(address))
51
+ debug { "Retrieved secret at: #{address}" }
52
+ SettingsReader::VaultResolver::Entry.new(address, secret)
53
+ else
54
+ debug { "Secret not retrieved: #{address}" }
55
+ end
56
+ end
57
+ end
58
+
59
+ def cache
60
+ SettingsReader::VaultResolver.cache
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,40 @@
1
+ module SettingsReader
2
+ module VaultResolver
3
+ # Methods for centralized logging
4
+ module Logging
5
+ def debug(&block)
6
+ logger.debug do
7
+ "[VaultResolver] #{block.call}"
8
+ end
9
+ nil
10
+ end
11
+
12
+ def info(&block)
13
+ logger.info do
14
+ "[VaultResolver] #{block.call}"
15
+ end
16
+ nil
17
+ end
18
+
19
+ def warn(&block)
20
+ logger.warn do
21
+ "[VaultResolver] #{block.call}"
22
+ end
23
+ nil
24
+ end
25
+
26
+ def error(&block)
27
+ logger.error do
28
+ "[VaultResolver] #{block.call}"
29
+ end
30
+ nil
31
+ end
32
+
33
+ private
34
+
35
+ def logger
36
+ @logger ||= SettingsReader::VaultResolver.logger
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module Vault
2
+ # Monkey patch to support k8s authenticaiton. Taken from https://github.com/hashicorp/vault-ruby/pull/202
3
+ class Authenticate < Request
4
+ def kubernetes(role, route = nil, service_token_path = nil)
5
+ route ||= '/v1/auth/kubernetes/login'
6
+ service_token_path ||= '/var/run/secrets/kubernetes.io/serviceaccount/token'
7
+
8
+ payload = {
9
+ role: role,
10
+ jwt: File.read(service_token_path)
11
+ }
12
+
13
+ json = client.post(route, JSON.fast_generate(payload))
14
+
15
+ secret = Secret.decode(json)
16
+ client.token = secret.auth.client_token
17
+
18
+ secret
19
+ end
20
+ end
21
+ end
@@ -1,7 +1,10 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
+ # Vault Lease refresher task
3
4
  class Refresher
4
- DEFAULT_RENEW_DELAY = 120
5
+ include Logging
6
+
7
+ DEFAULT_RENEW_DELAY = 200
5
8
  REFRESH_INTERVAL = 60
6
9
 
7
10
  def initialize(cache)
@@ -10,19 +13,26 @@ module SettingsReader
10
13
 
11
14
  def refresh
12
15
  @cache.entries.each do |entry|
16
+ debug { "Checking lease for #{entry}. Leased?: #{entry.leased?}. Expires in: #{entry.expires_in}s" }
13
17
  next unless entry.leased?
14
18
  next unless entry.expires_in < DEFAULT_RENEW_DELAY
15
19
 
20
+ info { "Refreshing lease for #{entry}. Expires in: #{entry.expires_in}" }
16
21
  entry.renew
22
+ info { "Lease renewed for #{entry}. Expires in: #{entry.expires_in}" }
23
+ rescue SettingsReader::VaultResolver::Error => e
24
+ error { "Error refreshing lease for #{entry}: #{e.message}" }
25
+ # Continue renewal.
17
26
  end
18
27
  end
19
28
 
20
29
  def self.refresh_task(cache)
21
30
  refresher = self
22
31
  Concurrent::TimerTask.new(execution_interval: refresher::REFRESH_INTERVAL) do
32
+ info { 'Refreshing Vault leases' }
23
33
  refresher.new(cache).refresh
24
34
  end
25
35
  end
26
36
  end
27
37
  end
28
- end
38
+ end
@@ -1,5 +1,5 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
- VERSION = "0.1.1"
3
+ VERSION = '0.2.2'.freeze
4
4
  end
5
5
  end
@@ -1,12 +1,17 @@
1
- require 'concurrent/timer_task.rb'
2
- require "settings_reader/vault_resolver/version"
3
- require "settings_reader/vault_resolver/address"
4
- require "settings_reader/vault_resolver/entry"
5
- require "settings_reader/vault_resolver/cache"
6
- require "settings_reader/vault_resolver/refresher"
7
- require "settings_reader/resolvers/vault"
1
+ require 'logger'
2
+ require 'concurrent/timer_task'
3
+
4
+ require 'settings_reader'
5
+ require 'settings_reader/vault_resolver/version'
6
+ require 'settings_reader/vault_resolver/logging'
7
+ require 'settings_reader/vault_resolver/address'
8
+ require 'settings_reader/vault_resolver/entry'
9
+ require 'settings_reader/vault_resolver/cache'
10
+ require 'settings_reader/vault_resolver/refresher'
11
+ require 'settings_reader/vault_resolver/instance'
8
12
 
9
13
  module SettingsReader
14
+ # Singleton for lease renewals and secrets cache
10
15
  module VaultResolver
11
16
  class Error < StandardError; end
12
17
 
@@ -14,6 +19,13 @@ module SettingsReader
14
19
  attr_accessor :cache, :refresher_timer_task
15
20
  end
16
21
 
22
+ def self.logger
23
+ return @logger if @logger
24
+ return @logger = Rails.logger if defined? Rails
25
+
26
+ @logger = Logger.new($stdout, level: Logger::INFO)
27
+ end
28
+
17
29
  def self.setup_cache
18
30
  self.cache ||= SettingsReader::VaultResolver::Cache.new
19
31
  end
@@ -24,7 +36,7 @@ module SettingsReader
24
36
  end
25
37
 
26
38
  def self.resolver
27
- SettingsReader::VaultResolver::Vault
39
+ SettingsReader::VaultResolver::Instance.new
28
40
  end
29
41
 
30
42
  setup_cache
@@ -4,7 +4,7 @@ Gem::Specification.new do |spec|
4
4
  spec.name = 'settings_reader-vault_resolver'
5
5
  spec.version = SettingsReader::VaultResolver::VERSION
6
6
  spec.authors = ['Volodymyr Mykhailyk']
7
- spec.email = ['712680+volodymyr-mykhailyk@users.noreply.github.com']
7
+ spec.email = ['volodymyr.mykhailyk@gmail.com']
8
8
 
9
9
  spec.summary = 'Settings Reader plugin to resolve values using in Hashicorp Vault'
10
10
  spec.description = 'This gem works as a resolver for `settings_reader` gem. \
@@ -12,15 +12,15 @@ Gem::Specification.new do |spec|
12
12
  with support of dynamic secrets and lease renewal.'
13
13
  spec.homepage = 'https://github.com/matic-insurance/settings_reader-vault_resolver'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
16
16
 
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
18
  spec.metadata['source_code_uri'] = spec.homepage
19
- spec.metadata['changelog_uri'] = spec.homepage + "/blob/master/CHANGELOG.md"
19
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/master/CHANGELOG.md"
20
20
 
21
21
  # Specify which files should be added to the gem when it is released.
22
22
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
24
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|local)/}) }
25
25
  end
26
26
  spec.bindir = 'exe'
@@ -28,14 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  spec.add_dependency 'concurrent-ruby', '~> 1.1'
31
+ spec.add_dependency 'settings_reader', '~> 0.1'
31
32
  spec.add_dependency 'vault', '~> 0.16'
32
-
33
- spec.add_development_dependency 'bundler', '~> 2.0'
34
- spec.add_development_dependency 'codecov', '~> 0.4'
35
- spec.add_development_dependency 'rake', '~> 13.0'
36
- spec.add_development_dependency 'rspec', '~> 3.0'
37
- spec.add_development_dependency 'rubocop', '~> 0.66'
38
- spec.add_development_dependency 'rubocop-rspec', '~> 1.32.0'
39
- spec.add_development_dependency 'simplecov', '~> 0.16'
40
- spec.add_development_dependency 'timecop', '~> 0.9'
41
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: settings_reader-vault_resolver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodymyr Mykhailyk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-19 00:00:00.000000000 Z
11
+ date: 2022-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -25,144 +25,48 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: vault
28
+ name: settings_reader
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.16'
33
+ version: '0.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.16'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.0'
55
- - !ruby/object:Gem::Dependency
56
- name: codecov
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0.4'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '0.4'
40
+ version: '0.1'
69
41
  - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '13.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '13.0'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '3.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '3.0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '0.66'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '0.66'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop-rspec
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: 1.32.0
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: 1.32.0
125
- - !ruby/object:Gem::Dependency
126
- name: simplecov
42
+ name: vault
127
43
  requirement: !ruby/object:Gem::Requirement
128
44
  requirements:
129
45
  - - "~>"
130
46
  - !ruby/object:Gem::Version
131
47
  version: '0.16'
132
- type: :development
48
+ type: :runtime
133
49
  prerelease: false
134
50
  version_requirements: !ruby/object:Gem::Requirement
135
51
  requirements:
136
52
  - - "~>"
137
53
  - !ruby/object:Gem::Version
138
54
  version: '0.16'
139
- - !ruby/object:Gem::Dependency
140
- name: timecop
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '0.9'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '0.9'
153
55
  description: |-
154
56
  This gem works as a resolver for `settings_reader` gem. \
155
57
  Any value with matching format will be resolved using Vault \
156
58
  with support of dynamic secrets and lease renewal.
157
59
  email:
158
- - 712680+volodymyr-mykhailyk@users.noreply.github.com
60
+ - volodymyr.mykhailyk@gmail.com
159
61
  executables: []
160
62
  extensions: []
161
63
  extra_rdoc_files: []
162
64
  files:
65
+ - ".github/workflows/linters.yml"
163
66
  - ".github/workflows/main.yml"
164
67
  - ".gitignore"
165
68
  - ".rspec"
69
+ - ".rubocop.yml"
166
70
  - ".simplecov"
167
71
  - CHANGELOG.md
168
72
  - CODE_OF_CONDUCT.md
@@ -174,11 +78,14 @@ files:
174
78
  - bin/console
175
79
  - bin/setup
176
80
  - docker-compose.yml
177
- - lib/settings_reader/resolvers/vault.rb
178
81
  - lib/settings_reader/vault_resolver.rb
179
82
  - lib/settings_reader/vault_resolver/address.rb
180
83
  - lib/settings_reader/vault_resolver/cache.rb
181
84
  - lib/settings_reader/vault_resolver/entry.rb
85
+ - lib/settings_reader/vault_resolver/helpers/k8s_auth.rb
86
+ - lib/settings_reader/vault_resolver/instance.rb
87
+ - lib/settings_reader/vault_resolver/logging.rb
88
+ - lib/settings_reader/vault_resolver/patches/authenticate.rb
182
89
  - lib/settings_reader/vault_resolver/refresher.rb
183
90
  - lib/settings_reader/vault_resolver/version.rb
184
91
  - settings_reader-vault_resolver.gemspec
@@ -197,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
197
104
  requirements:
198
105
  - - ">="
199
106
  - !ruby/object:Gem::Version
200
- version: 2.3.0
107
+ version: 2.5.0
201
108
  required_rubygems_version: !ruby/object:Gem::Requirement
202
109
  requirements:
203
110
  - - ">="
@@ -1,50 +0,0 @@
1
- require 'vault'
2
-
3
- module SettingsReader
4
- module Resolver
5
- class Vault
6
- IDENTIFIER = 'vault://'.freeze
7
- DATABASE_MOUNT = 'database'.freeze
8
-
9
- def resolvable?(value, _path)
10
- return unless value.respond_to?(:start_with?)
11
-
12
- value.start_with?(IDENTIFIER)
13
- end
14
-
15
- # Expect value in format `vault://mount/path/to/secret?attribute_name`
16
- def resolve(value, _path)
17
- address = SettingsReader::VaultResolver::Address.new(value)
18
- entry = fetch_entry(address)
19
- entry&.value_for(address.attribute)
20
- end
21
-
22
- #Resolve KV secret
23
- def kv_secret(address)
24
- ::Vault.kv(address.mount).read(address.path)
25
- end
26
-
27
- def database_secret(address)
28
- ::Vault.logical.read(address.full_path)
29
- rescue ::Vault::HTTPClientError => e
30
- raise unless e.message.include?('* unknown role')
31
-
32
- nil
33
- end
34
-
35
- private
36
-
37
- def fetch_entry(address)
38
- cache.fetch(address) do
39
- if (secret = address.mount == DATABASE_MOUNT ? database_secret(address) : kv_secret(address))
40
- SettingsReader::VaultResolver::Entry.new(address, secret)
41
- end
42
- end
43
- end
44
-
45
- def cache
46
- SettingsReader::VaultResolver.cache
47
- end
48
- end
49
- end
50
- end