settings_reader-vault_resolver 0.4.10 → 0.6.1

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: e80770a5709f4c47de9c79c771e2174749ad345d5f59584d83d406fd44b9d8cb
4
- data.tar.gz: 78d265a099e0a191bf01882cb666acfeecc802e1211fa097fe5588107720e90c
3
+ metadata.gz: 1a4f83916758232ddc5e3b36f6cc9ea25b813cd5bc69fb0f4a71d5b651a07ddf
4
+ data.tar.gz: baa1b66b38f6d2b41bcf11fcf230613740a67a6cf78d68db531ff6a5960f8b0f
5
5
  SHA512:
6
- metadata.gz: 900237697adf7ee9984e912bde5c1a8433ef345084db65d76d03d39fd1d904fc4f5859a9a7205634e2c1ccb5f9a807f1f2ba066b147ade86febb1695bd7ff9d7
7
- data.tar.gz: 7ff9538f5d886b99ace02d7eed050df0e017abba45de586d8c91e0c20bd7b505074545317df3b7a7f223728ea32dc39adf76a214f0f938e5ad9a3fbaf63b8e49
6
+ metadata.gz: 3d44012714aed2cb366128221b4764c5b260ff6dadb0548de267b30663864f0c2bc0e0d5e6848576b2791672001fdb81c88f18846dcd6cad1b498fe009ee6c53
7
+ data.tar.gz: 05ffe659944dbc215264ad3097f64a54a481f9943c9b7cee500281af806246727df9292cf29c6a10481f6049bbf0d174d0ab5165b19b946999eb044bbc0bd088
@@ -18,28 +18,39 @@ jobs:
18
18
  runs-on: ubuntu-latest
19
19
  strategy:
20
20
  matrix:
21
- ruby: [ '2.5', '2.6', '2.7', '3.0' ]
22
- services:
23
- vault:
24
- image: hashicorp/vault
25
- ports:
26
- - "8200:8200"
27
- env:
28
- VAULT_DEV_ROOT_TOKEN_ID: vault_root_token
29
- SKIP_SETCAP: true
30
- database:
31
- image: postgres:14.1-alpine
32
- ports:
33
- - "5432:5432"
34
- env:
35
- POSTGRES_USER: 'vault_root'
36
- POSTGRES_PASSWORD: 'root_password'
37
- POSTGRES_DB: 'app_db'
38
- options: >-
39
- --health-cmd pg_isready
40
- --health-interval 10s
41
- --health-timeout 5s
42
- --health-retries 5
21
+ ruby: [ '2.7', '3.0', '3.3' ]
22
+ # services:
23
+ # vault:
24
+ # image: hashicorp/vault
25
+ # ports:
26
+ # - "8200:8200"
27
+ # env:
28
+ # VAULT_DEV_ROOT_TOKEN_ID: vault_root_token
29
+ # SKIP_SETCAP: true
30
+ # database:
31
+ # image: postgres:14.1-alpine
32
+ # ports:
33
+ # - "5432:5432"
34
+ # env:
35
+ # POSTGRES_USER: 'vault_root'
36
+ # POSTGRES_PASSWORD: 'root_password'
37
+ # POSTGRES_DB: 'app_db'
38
+ # options: >-
39
+ # --health-cmd pg_isready
40
+ # --health-interval 10s
41
+ # --health-timeout 5s
42
+ # --health-retries 5
43
+ # aws:
44
+ # image: localstack/localstack
45
+ # ports:
46
+ # - "127.0.0.1:4566:4566" # LocalStack Gateway
47
+ # - "127.0.0.1:4510-4559:4510-4559" # external services port range
48
+ # env:
49
+ # DEBUG: 0
50
+ # volumes:
51
+ # - '/home/runner/work/settings_reader-vault_resolver/local/localstack/app-access-policy.json:/etc/localstack/init/ready.d/app-access-policy.json'
52
+ # - '/home/runner/work/settings_reader-vault_resolver/local/localstack/app-assume-policy.json:/etc/localstack/init/ready.d/app-assume-policy.json'
53
+ # - '/home/runner/work/settings_reader-vault_resolver/local/localstack/init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh'
43
54
  steps:
44
55
  - name: Checkout
45
56
  uses: actions/checkout@v1
@@ -50,23 +61,24 @@ jobs:
50
61
  ruby-version: ${{ matrix.ruby }}
51
62
  bundler-cache: true
52
63
 
53
- - name: Set up Vault
54
- run: sh local/vault/setup.sh
64
+ - name: Start Dependencies
65
+ run: |
66
+ docker compose up -d
67
+ echo "Waiting 15 seconds for initial configuraiton"
68
+ sleep 15
55
69
 
56
70
  - name: Run specs
57
- env:
58
- COVERAGE: true
59
71
  run: bundle exec rspec
60
72
 
61
- - name: Upload coverage
62
- env:
63
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
64
- run: bash <(curl -s https://codecov.io/bash)
65
-
66
73
  release:
67
74
  runs-on: ubuntu-latest
68
75
  needs: build
69
- if: github.event_name == 'release' && github.event.action == 'published'
76
+ # if: github.event_name == 'release' && github.event.action == 'published'
77
+
78
+ permissions:
79
+ # contents: write
80
+ id-token: write
81
+
70
82
  steps:
71
83
  - name: Checkout
72
84
  uses: actions/checkout@v3
@@ -76,19 +88,16 @@ jobs:
76
88
  with:
77
89
  ruby-version: 2.7
78
90
  bundler-cache: true
79
- - name: Set up credentials
80
- run: |
81
- mkdir -p $HOME/.gem
82
- touch $HOME/.gem/credentials
83
- chmod 0600 $HOME/.gem/credentials
84
- printf -- "---\n:rubygems_api_key: ${{secrets.RUBYGEMS_AUTH_TOKEN}}\n" > $HOME/.gem/credentials
85
91
 
86
- - name: Get version
87
- run: echo "${GITHUB_REF/refs\/tags\//}" > release.tag
92
+
93
+ # - name: Get version
94
+ # run: echo "${GITHUB_REF/refs\/tags\//}" > release.tag
88
95
  - name: Set version
89
- run: sed -i "s/0.0.0/$(<release.tag)/g" $(find . -name "version.rb")
96
+ run: sed -i "s/0.0.0/0.6.1/g" $(find . -name "version.rb")
97
+
98
+ - uses: rubygems/configure-rubygems-credentials@v1.0.0
90
99
 
91
100
  - name: Build gem
92
101
  run: gem build *.gemspec
93
102
  - name: Push gem
94
- run: gem push *.gem
103
+ run: gem push *.gem
data/.rubocop.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
3
  SuggestExtensions: false
4
- TargetRubyVersion: 2.5
4
+ TargetRubyVersion: 2.7
5
5
 
6
6
  Gemspec/RequireMFA:
7
7
  Enabled: false
data/.simplecov CHANGED
@@ -1,9 +1,7 @@
1
1
  if ENV['COVERAGE']
2
2
  require 'simplecov'
3
- require 'codecov'
4
3
  SimpleCov.start do
5
4
  enable_coverage :branch
6
5
  primary_coverage :branch
7
- formatter SimpleCov::Formatter::Codecov
8
6
  end
9
7
  end
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 3.3.8
data/Gemfile CHANGED
@@ -3,7 +3,6 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in settings_reader-vault_resolver.gemspec
4
4
  gemspec
5
5
 
6
- gem 'codecov'
7
6
  gem 'rake'
8
7
  gem 'rspec'
9
8
  gem 'rubocop'
data/Gemfile.lock CHANGED
@@ -9,22 +9,25 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- ast (2.4.2)
12
+ ast (2.4.3)
13
13
  aws-eventstream (1.2.0)
14
14
  aws-sigv4 (1.4.0)
15
15
  aws-eventstream (~> 1, >= 1.0.2)
16
- codecov (0.6.0)
17
- simplecov (>= 0.15, < 0.22)
18
16
  concurrent-ruby (1.1.9)
19
17
  diff-lcs (1.5.0)
20
18
  docile (1.4.0)
21
- parallel (1.21.0)
22
- parser (3.1.1.0)
19
+ json (2.13.2)
20
+ language_server-protocol (3.17.0.5)
21
+ lint_roller (1.1.0)
22
+ parallel (1.27.0)
23
+ parser (3.3.9.0)
23
24
  ast (~> 2.4.1)
25
+ racc
26
+ prism (1.4.0)
27
+ racc (1.8.1)
24
28
  rainbow (3.1.1)
25
29
  rake (13.0.6)
26
- regexp_parser (2.2.1)
27
- rexml (3.2.5)
30
+ regexp_parser (2.11.2)
28
31
  rspec (3.10.0)
29
32
  rspec-core (~> 3.10.0)
30
33
  rspec-expectations (~> 3.10.0)
@@ -38,29 +41,34 @@ GEM
38
41
  diff-lcs (>= 1.2.0, < 2.0)
39
42
  rspec-support (~> 3.10.0)
40
43
  rspec-support (3.10.3)
41
- rubocop (1.25.1)
44
+ rubocop (1.80.2)
45
+ json (~> 2.3)
46
+ language_server-protocol (~> 3.17.0.2)
47
+ lint_roller (~> 1.1.0)
42
48
  parallel (~> 1.10)
43
- parser (>= 3.1.0.0)
49
+ parser (>= 3.3.0.2)
44
50
  rainbow (>= 2.2.2, < 4.0)
45
- regexp_parser (>= 1.8, < 3.0)
46
- rexml
47
- rubocop-ast (>= 1.15.1, < 2.0)
51
+ regexp_parser (>= 2.9.3, < 3.0)
52
+ rubocop-ast (>= 1.46.0, < 2.0)
48
53
  ruby-progressbar (~> 1.7)
49
- unicode-display_width (>= 1.4.0, < 3.0)
50
- rubocop-ast (1.16.0)
51
- parser (>= 3.1.1.0)
54
+ unicode-display_width (>= 2.4.0, < 4.0)
55
+ rubocop-ast (1.46.0)
56
+ parser (>= 3.3.7.2)
57
+ prism (~> 1.4)
52
58
  rubocop-rspec (1.32.0)
53
59
  rubocop (>= 0.60.0)
54
- ruby-progressbar (1.11.0)
60
+ ruby-progressbar (1.13.0)
55
61
  settings_reader (0.1.0)
56
62
  simplecov (0.21.2)
57
63
  docile (~> 1.1)
58
64
  simplecov-html (~> 0.11)
59
65
  simplecov_json_formatter (~> 0.1)
60
66
  simplecov-html (0.12.3)
61
- simplecov_json_formatter (0.1.3)
67
+ simplecov_json_formatter (0.1.4)
62
68
  timecop (0.9.4)
63
- unicode-display_width (2.1.0)
69
+ unicode-display_width (3.2.0)
70
+ unicode-emoji (~> 4.1)
71
+ unicode-emoji (4.1.0)
64
72
  vault (0.16.0)
65
73
  aws-sigv4
66
74
 
@@ -68,7 +76,6 @@ PLATFORMS
68
76
  ruby
69
77
 
70
78
  DEPENDENCIES
71
- codecov
72
79
  rake
73
80
  rspec
74
81
  rubocop
@@ -78,4 +85,4 @@ DEPENDENCIES
78
85
  timecop
79
86
 
80
87
  BUNDLED WITH
81
- 2.1.4
88
+ 2.2.32
data/docker-compose.yml CHANGED
@@ -2,12 +2,20 @@
2
2
  version: '3'
3
3
  services:
4
4
  vault:
5
- image: vault
5
+ image: hashicorp/vault
6
6
  ports:
7
7
  - "8200:8200"
8
8
  environment:
9
9
  VAULT_DEV_ROOT_TOKEN_ID: 'vault_root_token'
10
10
  SKIP_SETCAP: 'true'
11
+ # playground:
12
+ # image: hashicorp/vault
13
+ # command:
14
+ # - sleep
15
+ # - '10000000000'
16
+ # environment:
17
+ # VAULT_ADDR: 'http://aws:8200'
18
+ # VAULT_TOKEN: 'vault_root_token'
11
19
  db:
12
20
  image: postgres:14.1-alpine
13
21
  ports:
@@ -16,11 +24,24 @@ services:
16
24
  POSTGRES_USER: 'vault_root'
17
25
  POSTGRES_PASSWORD: 'root_password'
18
26
  POSTGRES_DB: 'app_db'
27
+ aws:
28
+ image: localstack/localstack
29
+ ports:
30
+ - "127.0.0.1:4566:4566" # LocalStack Gateway
31
+ - "127.0.0.1:4510-4559:4510-4559" # external services port range
32
+ environment:
33
+ # LocalStack configuration: https://docs.localstack.cloud/references/configuration/
34
+ - DEBUG=${DEBUG:-0}
35
+ volumes:
36
+ - './local/localstack/app-access-policy.json:/etc/localstack/init/ready.d/app-access-policy.json'
37
+ - './local/localstack/app-assume-policy.json:/etc/localstack/init/ready.d/app-assume-policy.json'
38
+ - './local/localstack/init-aws.sh:/etc/localstack/init/ready.d/init-aws.sh'
19
39
  init:
20
40
  image: curlimages/curl
21
41
  depends_on:
22
42
  - vault
23
43
  - db
44
+ - aws
24
45
  volumes:
25
46
  - './local/vault/setup.sh:/etc/vault/setup.sh'
26
47
  environment:
@@ -23,8 +23,8 @@ module SettingsReader
23
23
  end
24
24
 
25
25
  def fetch(address, &block)
26
- if !address.no_cache? && (exiting_entry = retrieve(address))
27
- exiting_entry
26
+ if !address.no_cache? && (existing_entry = retrieve(address))
27
+ existing_entry
28
28
  else
29
29
  new_entry = block.call(address)
30
30
  save(new_entry) if new_entry
@@ -42,7 +42,11 @@ module SettingsReader
42
42
  # Default: empty proc
43
43
  attr_accessor :lease_not_found_handler
44
44
 
45
- def initialize
45
+ # Whether to raise error or return nil when secret or attribute is missing
46
+ # Default: false
47
+ attr_accessor :raise_error_on_missing_secret
48
+
49
+ def initialize # rubocop:disable Metrics/MethodLength
46
50
  @logger = Logger.new($stdout, level: Logger::ERROR)
47
51
  @retriable_errors = [OpenSSL::SSL::SSLError, Vault::HTTPConnectionError]
48
52
  @retrieval_retries = 2
@@ -53,6 +57,7 @@ module SettingsReader
53
57
  @lease_renew_success_listener = ->(_result) {}
54
58
  @vault_initializer = -> {}
55
59
  @lease_not_found_handler = ->(_entry) {}
60
+ @raise_error_on_missing_secret = false
56
61
  end
57
62
 
58
63
  def setup_lease_refresher(cache, previous_task = nil)
@@ -70,6 +75,7 @@ module SettingsReader
70
75
  @vault_engines ||= [
71
76
  SettingsReader::VaultResolver::Engines::KV2.new(self),
72
77
  SettingsReader::VaultResolver::Engines::Database.new(self),
78
+ SettingsReader::VaultResolver::Engines::Aws.new(self),
73
79
  SettingsReader::VaultResolver::Engines::Auth.new(self)
74
80
  ]
75
81
  end
@@ -16,15 +16,17 @@ module SettingsReader
16
16
  end
17
17
 
18
18
  def get(address)
19
- return unless (vault_secret = get_and_retry_auth(address))
19
+ vault_secret = get_and_retry_auth(address)
20
+ entry = wrap_secret(address, vault_secret) if vault_secret
21
+ validate_secret!(entry, address) if config.raise_error_on_missing_secret
20
22
 
21
- wrap_secret(address, vault_secret)
23
+ entry
22
24
  rescue Vault::VaultError => e
23
25
  raise SettingsReader::VaultResolver::Error, e.message
24
26
  end
25
27
 
26
28
  def renew(entry)
27
- return unless entry.leased?
29
+ return unless entry.renewable?
28
30
 
29
31
  new_secret = renew_and_retry_auth(entry)
30
32
  entry.update_renewed(new_secret)
@@ -78,6 +80,14 @@ module SettingsReader
78
80
  def auth_error?(error)
79
81
  error.code == 403 || error.message =~ /token mac for token_version.*is incorrect/
80
82
  end
83
+
84
+ def validate_secret!(entry, address)
85
+ secret_value = entry&.value_for(address.attribute)
86
+ return if secret_value && !secret_value.empty?
87
+
88
+ raise SettingsReader::VaultResolver::Error,
89
+ "Secret not found at #{address}. Secret data: #{entry&.secret&.to_h}"
90
+ end
81
91
  end
82
92
  end
83
93
  end
@@ -0,0 +1,29 @@
1
+ module SettingsReader
2
+ module VaultResolver
3
+ module Engines
4
+ # Adapter to retrieve / renew secret from database engine
5
+ class Aws < Abstract
6
+ MOUNT = 'aws'.freeze
7
+
8
+ def retrieves?(address)
9
+ address.mount == MOUNT
10
+ end
11
+
12
+ private
13
+
14
+ def get_secret(address)
15
+ debug { "Fetching new aws secret at: #{address}" }
16
+ Vault.logical.read(address.full_path)
17
+ rescue Vault::HTTPClientError => e
18
+ return nil if e.message.match?('Role ".*" not found')
19
+
20
+ raise e
21
+ end
22
+
23
+ def renew_lease(entry)
24
+ Vault.sys.renew(entry.lease_id)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -13,10 +13,14 @@ module SettingsReader
13
13
  @lease_started = Time.now
14
14
  end
15
15
 
16
- def leased?
16
+ def renewable?
17
17
  @secret.renewable?
18
18
  end
19
19
 
20
+ def leased?
21
+ renewable? || @secret.lease_duration&.positive?
22
+ end
23
+
20
24
  def expired?
21
25
  return false unless leased?
22
26
 
@@ -7,7 +7,6 @@ module SettingsReader
7
7
  include Logging
8
8
 
9
9
  IDENTIFIER = 'vault://'.freeze
10
- DATABASE_MOUNT = 'database'.freeze
11
10
 
12
11
  attr_reader :config
13
12
 
@@ -22,7 +21,7 @@ module SettingsReader
22
21
  value.start_with?(IDENTIFIER)
23
22
  end
24
23
 
25
- # Expect value in format `vault://mount/path/to/secret?attribute_name`
24
+ # Expect value in format `vault://mount/path/to/secret#attribute_name`
26
25
  def resolve(value, _path)
27
26
  debug { "Resolving Vault secret at #{value}" }
28
27
  address = SettingsReader::VaultResolver::Address.new(value)
@@ -19,7 +19,7 @@ module SettingsReader
19
19
  def refresh
20
20
  info { 'Performing Vault leases refresh' }
21
21
  promises = cache.active_entries.map do |entry|
22
- debug { "Checking lease for #{entry}. Leased?: #{entry.leased?}. Expires in: #{entry.expires_in}s" }
22
+ debug { "Checking lease for #{entry}. Renewable?: #{entry.renewable?}. Expires in: #{entry.expires_in}s" }
23
23
  refresh_entry(entry)
24
24
  end.compact
25
25
  promises.each(&:wait)
@@ -1,5 +1,5 @@
1
1
  module SettingsReader
2
2
  module VaultResolver
3
- VERSION = '0.4.10'.freeze
3
+ VERSION = '0.6.1'.freeze
4
4
  end
5
5
  end
@@ -11,6 +11,7 @@ require_relative 'vault_resolver/engines/abstract'
11
11
  require_relative 'vault_resolver/engines/auth'
12
12
  require_relative 'vault_resolver/engines/kv2'
13
13
  require_relative 'vault_resolver/engines/database'
14
+ require_relative 'vault_resolver/engines/aws'
14
15
  require_relative 'vault_resolver/cache'
15
16
  require_relative 'vault_resolver/refresher'
16
17
  require_relative 'vault_resolver/refresher_observer'
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.4.10
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodymyr Mykhailyk
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2025-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -68,6 +68,7 @@ files:
68
68
  - ".rspec"
69
69
  - ".rubocop.yml"
70
70
  - ".simplecov"
71
+ - ".tool-versions"
71
72
  - CHANGELOG.md
72
73
  - CODE_OF_CONDUCT.md
73
74
  - Gemfile
@@ -77,7 +78,6 @@ files:
77
78
  - Rakefile
78
79
  - bin/console
79
80
  - bin/setup
80
- - codecov.yml
81
81
  - docker-compose.yml
82
82
  - lib/settings_reader/vault_resolver.rb
83
83
  - lib/settings_reader/vault_resolver/address.rb
@@ -85,6 +85,7 @@ files:
85
85
  - lib/settings_reader/vault_resolver/configuration.rb
86
86
  - lib/settings_reader/vault_resolver/engines/abstract.rb
87
87
  - lib/settings_reader/vault_resolver/engines/auth.rb
88
+ - lib/settings_reader/vault_resolver/engines/aws.rb
88
89
  - lib/settings_reader/vault_resolver/engines/database.rb
89
90
  - lib/settings_reader/vault_resolver/engines/kv2.rb
90
91
  - lib/settings_reader/vault_resolver/entry.rb
@@ -103,7 +104,7 @@ metadata:
103
104
  homepage_uri: https://github.com/matic-insurance/settings_reader-vault_resolver
104
105
  source_code_uri: https://github.com/matic-insurance/settings_reader-vault_resolver
105
106
  changelog_uri: https://github.com/matic-insurance/settings_reader-vault_resolver/blob/master/CHANGELOG.md
106
- post_install_message:
107
+ post_install_message:
107
108
  rdoc_options: []
108
109
  require_paths:
109
110
  - lib
@@ -119,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
120
  version: '0'
120
121
  requirements: []
121
122
  rubygems_version: 3.1.6
122
- signing_key:
123
+ signing_key:
123
124
  specification_version: 4
124
125
  summary: Settings Reader plugin to resolve values using in Hashicorp Vault
125
126
  test_files: []
data/codecov.yml DELETED
@@ -1,12 +0,0 @@
1
- codecov:
2
- require_ci_to_pass: yes
3
-
4
- coverage:
5
- precision: 2
6
- round: up
7
- range: "90...100"
8
-
9
- ignore:
10
- - "spec"
11
- - "bin"
12
- - "local"